fix(workflows): reject falsy non-mapping catalog config in add/remove - #4319
fix(workflows): reject falsy non-mapping catalog config in add/remove#4319Noor-ul-ain001 wants to merge 4 commits into
Conversation
`WorkflowCatalog.remove_catalog`, `StepCatalog.add_catalog`, and
`StepCatalog.remove_catalog` all read their config file with
`yaml.safe_load(...) or {}`, which coerces a FALSY non-mapping
top-level document (`[]`, `false`, `0`, `''`) to `{}` before the
`isinstance(data, dict)` check ever runs — silently swallowing a
corrupted config instead of raising, while a truthy non-mapping
(`5`, a bare list with items) correctly raises.
`WorkflowCatalog._load_catalog_config` (used by `get_active_catalogs`)
and `WorkflowCatalog.add_catalog` already guard against this
correctly, with a comment explaining why `or {}` is wrong here; the
other three call sites in the same file reimplement the read inline
and missed the fix. Same shape as the falsy-or-coerce bug class fixed
in github#4094 (preset catalog add/remove) and github#4187 (integration
descriptor loading).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FW9fAYsCBCAgdKWovtSyqt
There was a problem hiding this comment.
🟢 Approval recommended
The functional fix is correct and comprehensively tested; only a non-blocking docstring correction remains.
Pull request overview
Fixes catalog mutation paths so falsy non-mapping YAML roots raise validation errors instead of being treated as empty configurations.
Changes:
- Corrects workflow and step catalog YAML shape validation.
- Adds regression coverage for four falsy non-mapping values.
File summaries
| File | Description |
|---|---|
src/specify_cli/workflows/catalog.py |
Preserves falsy values for type validation. |
tests/test_workflows.py |
Adds parameterized regression tests. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
An unclosed test docstring causes a syntax error and prevents test collection.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Balanced
| """A FALSY non-mapping top-level config ([], false, 0, '') must raise | ||
| 'corrupted (expected a mapping)', not be silently coerced to {} by | ||
| ``or {}``; empty and explicit-null documents still parse as None and | ||
| retain their existing empty-config behavior. |
test_add_catalog_rejects_falsy_non_mapping_config's docstring was missing its closing triple-quote, merging the docstring with the following import statement. This caused a SyntaxError on collection, preventing the whole test_workflows.py module (963 tests) from being collected.
…add-falsy-config # Conflicts: # src/specify_cli/workflows/catalog.py # tests/test_workflows.py
|
Thanks — good fix, but it's already in |
Summary
WorkflowCatalog.remove_catalog,StepCatalog.add_catalog, andStepCatalog.remove_catalog(all insrc/specify_cli/workflows/catalog.py) read their config file withyaml.safe_load(config_path.read_text(...)) or {}.or {}coerces a falsy non-mapping top-level document ([],false,0,'') to{}before theisinstance(data, dict)guard runs, so a corrupted config silently becomes "no catalogs" instead of raising"...corrupted (expected a mapping)". A truthy non-mapping (5, a bare list with items) already raised correctly — this was an inconsistency, and forremove_catalogit surfaces as a misleading"Catalog index N out of range"error instead.WorkflowCatalog._load_catalog_config(the shared loader behindget_active_catalogs) andWorkflowCatalog.add_catalogalready guard against exactly this, with an explanatory comment (# Do NOT coerce with or {} here: ...). The other three call sites in the same file reimplement the read inline and were missed.Test plan
test_remove_catalog_rejects_falsy_non_mapping_configtoTestWorkflowCatalogandtest_add_catalog_rejects_falsy_non_mapping_config/test_remove_catalog_rejects_falsy_non_mapping_configtoTestStepCatalog, each parametrized over[],false,0,''.TestWorkflowCatalog+TestStepCatalogin full — 100 passed, no regressions.Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01FW9fAYsCBCAgdKWovtSyqt