fix: Handle None ai_analysis in how-to guide builder (PR #247) (#274)

* Fix how-to guide builder edge case

* Resolve merge conflict

* fix: Handle None ai_analysis in how-to guide builder

Fixes NoneType AttributeError when ai_analysis is explicitly None.

The issue occurred when workflow.get('ai_analysis') returned None and
code attempted to call .get() without checking if it was None first.

Using 'workflow.get("ai_analysis", {})' only provides default {} when
the key is missing, not when the value is None. Changed to use
'workflow.get("ai_analysis") or {}' pattern which handles both cases.

Also added isinstance() type safety check in _extract_workflow_examples
to gracefully handle malformed data.

Changes:
- _group_by_ai_tutorial_group: ai_analysis = workflow.get() or {}
- _extract_workflow_examples: isinstance(ex, dict) check added
- _create_guide: ai_analysis = primary_workflow.get() or {} (2 locations)
- _generate_overview: ai_analysis = primary_workflow.get() or {}

All 34 how-to guide builder tests passing.

Closes #242

Co-authored-by: yashrastogi019-cell <yashrastogi019@gmail.com>

---------

Co-authored-by: yashrastogi019-cell <yashrastogi019@gmail.com>
This commit is contained in:
yusyus
2026-01-31 22:17:19 +03:00
committed by GitHub
parent 91bd2184e5
commit 3a79ceba93

View File

@@ -452,7 +452,7 @@ class WorkflowGrouper:
ungrouped = []
for workflow in workflows:
ai_analysis = workflow.get("ai_analysis", {})
ai_analysis = workflow.get("ai_analysis") or {}
tutorial_group = ai_analysis.get("tutorial_group")
if tutorial_group:
@@ -908,7 +908,7 @@ class HowToGuideBuilder:
def _extract_workflow_examples(self, examples: list[dict]) -> list[dict]:
"""Filter to workflow category only"""
return [ex for ex in examples if ex.get("category") == "workflow"]
return [ex for ex in examples if isinstance(ex, dict) and ex.get("category") == "workflow"]
def _create_guide(self, title: str, workflows: list[dict], enhancer=None) -> HowToGuide:
"""
@@ -933,8 +933,10 @@ class HowToGuideBuilder:
# Extract use case from AI analysis or title
use_case = title
if primary_workflow.get("ai_analysis"):
use_case = primary_workflow["ai_analysis"].get("tutorial_group", title)
ai_analysis = primary_workflow.get("ai_analysis") or {}
if ai_analysis:
use_case = ai_analysis.get("tutorial_group", title)
# Determine overview
overview = self._generate_overview(primary_workflow, workflows)
@@ -967,19 +969,22 @@ class HowToGuideBuilder:
)
# Add AI enhancements if enhancer is available
ai_analysis_for_enhancement = primary_workflow.get("ai_analysis") or {}
if enhancer:
self._enhance_guide_with_ai(guide, primary_workflow.get("ai_analysis", {}), enhancer)
elif self.enhance_with_ai and primary_workflow.get("ai_analysis"):
self._enhance_guide_with_ai(guide, ai_analysis_for_enhancement, enhancer)
elif self.enhance_with_ai and ai_analysis_for_enhancement:
# Fallback to old enhancement method (basic)
self._enhance_guide_with_ai_basic(guide, primary_workflow["ai_analysis"])
self._enhance_guide_with_ai_basic(guide, ai_analysis_for_enhancement)
return guide
def _generate_overview(self, primary_workflow: dict, _all_workflows: list[dict]) -> str:
"""Generate guide overview"""
# Try to get explanation from AI analysis
if primary_workflow.get("ai_analysis"):
explanation = primary_workflow["ai_analysis"].get("explanation")
ai_analysis = primary_workflow.get("ai_analysis") or {}
if ai_analysis:
explanation = ai_analysis.get("explanation")
if explanation:
return explanation