diff --git a/core/wren/src/wren/context.py b/core/wren/src/wren/context.py index 7ad8a2917c..402d8eb421 100644 --- a/core/wren/src/wren/context.py +++ b/core/wren/src/wren/context.py @@ -1554,13 +1554,21 @@ def _apply_v4_to_v5(project_path: Path) -> None: def _prop_description(item: dict) -> str | None: - return (item.get("properties") or {}).get("description") + props = item.get("properties") or {} + if not isinstance(props, dict): + return None + return props.get("description") def _check_descriptions(manifest: dict, *, strict: bool = False) -> list[str]: warnings: list[str] = [] - for model in manifest.get("models", []): + models = manifest.get("models", []) or [] + if not isinstance(models, list): + models = [] + for model in models: + if not isinstance(model, dict): + continue name = model.get("name", "") if not _prop_description(model): warnings.append( @@ -1568,14 +1576,24 @@ def _check_descriptions(manifest: dict, *, strict: bool = False) -> list[str]: "add properties.description to improve memory search and agent comprehension" ) if strict: - for col in model.get("columns", []): + cols = model.get("columns", []) or [] + if not isinstance(cols, list): + cols = [] + for col in cols: + if not isinstance(col, dict): + continue col_name = col.get("name", "") if not _prop_description(col): warnings.append( f"Column '{col_name}' in model '{name}' has no description" ) - for view in manifest.get("views", []): + views = manifest.get("views", []) or [] + if not isinstance(views, list): + views = [] + for view in views: + if not isinstance(view, dict): + continue view_name = view.get("name", "") if not _prop_description(view): warnings.append( diff --git a/core/wren/tests/unit/test_check_descriptions_guards.py b/core/wren/tests/unit/test_check_descriptions_guards.py new file mode 100644 index 0000000000..5a8ca922fc --- /dev/null +++ b/core/wren/tests/unit/test_check_descriptions_guards.py @@ -0,0 +1,28 @@ +from wren.context import _check_descriptions + + +def test_check_descriptions_skips_non_dict_models_and_columns(): + warnings = _check_descriptions( + { + "models": [ + "bad", + { + "name": "orders", + "properties": "oops", + "columns": "x", + }, + { + "name": "ok", + "properties": {"description": "d"}, + "columns": [None, {"name": "id"}], # missing col desc when strict + }, + ], + "views": ["nope", {"name": "v1"}], + }, + strict=True, + ) + # orders model missing desc; ok column id missing desc; v1 view missing desc + joined = "\n".join(warnings) + assert "Model 'orders'" in joined + assert "Column 'id' in model 'ok'" in joined + assert "View 'v1'" in joined