Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/specify_cli/presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1903,12 +1903,24 @@ def _load_catalog_config(self, config_path: Path) -> Optional[List[PresetCatalog
if not url:
continue
self._validate_catalog_url(url)
raw_priority = item.get("priority", idx + 1)
# Reject bools explicitly: ``bool`` is a subclass of ``int`` so
# ``int(True)`` silently returns 1, which would let a YAML
# ``priority: true`` slip through as a valid priority of 1. The
# sibling integration-catalog reader in ``catalogs.py`` already
# guards this; mirror the check here so the three catalog
# validators stay consistent.
if isinstance(raw_priority, bool):
raise PresetValidationError(
f"Invalid priority for catalog '{item.get('name', idx + 1)}': "
f"expected integer, got {raw_priority!r}"
)
try:
priority = int(item.get("priority", idx + 1))
priority = int(raw_priority)
except (TypeError, ValueError):
raise PresetValidationError(
f"Invalid priority for catalog '{item.get('name', idx + 1)}': "
f"expected integer, got {item.get('priority')!r}"
f"expected integer, got {raw_priority!r}"
)
raw_install = item.get("install_allowed", False)
if isinstance(raw_install, str):
Expand Down
25 changes: 25 additions & 0 deletions tests/test_presets.py
Original file line number Diff line number Diff line change
Expand Up @@ -1830,6 +1830,31 @@ def test_load_catalog_config_invalid_priority(self, project_dir):
with pytest.raises(PresetValidationError, match="Invalid priority"):
catalog._load_catalog_config(config_path)

def test_load_catalog_config_rejects_boolean_priority(self, project_dir):
"""A YAML ``priority: true`` is a typo, not a request for priority 1.

``bool`` is a subclass of ``int`` in Python, so ``int(True)`` silently
returns ``1``. Without an explicit guard a malformed config like
``priority: yes`` would be accepted as a valid priority of 1 and
silently change catalog ordering. The sibling integration-catalog
reader rejects this case (see ``catalogs.py``); the preset catalog
reader must stay consistent.
"""
config_path = project_dir / ".specify" / "preset-catalogs.yml"
config_path.write_text(yaml.dump({
"catalogs": [
{
"name": "bool-priority",
"url": "https://example.com/catalog.json",
"priority": True,
}
]
}))

catalog = PresetCatalog(project_dir)
with pytest.raises(PresetValidationError, match="Invalid priority|expected integer"):
catalog._load_catalog_config(config_path)

def test_load_catalog_config_install_allowed_string(self, project_dir):
"""Test that install_allowed accepts string values."""
config_path = project_dir / ".specify" / "preset-catalogs.yml"
Expand Down