mirror of
https://github.com/github/spec-kit.git
synced 2026-08-03 06:26:30 +08:00
fix(catalogs): 'priority: .inf' yields a clean validation error instead of crashing (#3525)
* fix(catalogs): priority: .inf yields a clean validation error, not OverflowError
_load_catalog_config coerces a catalog entry's priority with int() inside
except (TypeError, ValueError). int(float('inf')) raises OverflowError, which is
not in that tuple, so a YAML 'priority: .inf' escaped as an uncaught traceback
instead of the intended 'expected integer' validation error (the bool-is-int
case is already guarded just above). Add OverflowError to the except tuple.
Test mirrors the existing rejects_boolean_priority test with priority: .inf
(fails before: OverflowError; passes after: ValidationError naming the config).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(presets): priority: .inf in a preset catalog config yields a clean error
The PresetCatalog._load_catalog_config priority parser has its own loader
(separate from CatalogStackBase) that caught only TypeError/ValueError, so a
YAML 'priority: .inf' escaped as an uncaught OverflowError from int(float('inf')).
Add OverflowError to the except tuple (the bool-is-int case is already guarded
just above), matching catalogs.py.
Test mirrors rejects_boolean_priority with priority: .inf (fails before:
OverflowError; passes after: PresetValidationError).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -149,7 +149,10 @@ class CatalogStackBase:
|
||||
)
|
||||
try:
|
||||
priority = int(raw_priority)
|
||||
except (TypeError, ValueError):
|
||||
except (TypeError, ValueError, OverflowError):
|
||||
# OverflowError: int(float("inf")) — a YAML ``priority: .inf``
|
||||
# would otherwise escape as an uncaught traceback instead of the
|
||||
# clean validation error.
|
||||
raise self._validation_error(
|
||||
f"Invalid catalog config {config_path}: "
|
||||
f"Invalid priority for catalog '{item.get('name', idx + 1)}': "
|
||||
|
||||
@@ -2235,7 +2235,10 @@ class PresetCatalog:
|
||||
)
|
||||
try:
|
||||
priority = int(raw_priority)
|
||||
except (TypeError, ValueError):
|
||||
except (TypeError, ValueError, OverflowError):
|
||||
# OverflowError: int(float("inf")) — a YAML ``priority: .inf``
|
||||
# would otherwise escape as an uncaught traceback instead of the
|
||||
# clean validation error (mirrors catalogs.py).
|
||||
raise PresetValidationError(
|
||||
f"Invalid priority for catalog '{item.get('name', idx + 1)}': "
|
||||
f"expected integer, got {raw_priority!r}"
|
||||
|
||||
@@ -4542,6 +4542,36 @@ class TestCatalogStack:
|
||||
catalog.get_active_catalogs()
|
||||
assert str(config_path) in str(exc_info.value)
|
||||
|
||||
def test_load_catalog_config_rejects_infinite_priority(self, temp_dir):
|
||||
"""A ``priority: .inf`` yields a clean validation error, not an uncaught
|
||||
OverflowError from int(float('inf'))."""
|
||||
import yaml as yaml_module
|
||||
|
||||
project_dir = self._make_project(temp_dir)
|
||||
config_path = project_dir / ".specify" / "extension-catalogs.yml"
|
||||
config_path.write_text(
|
||||
yaml_module.dump(
|
||||
{
|
||||
"catalogs": [
|
||||
{
|
||||
"name": "inf-priority",
|
||||
"url": "https://example.com/catalog.json",
|
||||
"priority": float("inf"),
|
||||
}
|
||||
]
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
catalog = ExtensionCatalog(project_dir)
|
||||
|
||||
with pytest.raises(
|
||||
ValidationError, match="Invalid priority|expected integer"
|
||||
) as exc_info:
|
||||
catalog.get_active_catalogs()
|
||||
assert str(config_path) in str(exc_info.value)
|
||||
|
||||
def test_load_catalog_config_defaults_blank_names(self, temp_dir):
|
||||
"""Blank and null names normalize by valid catalog order."""
|
||||
import yaml as yaml_module
|
||||
|
||||
@@ -2671,6 +2671,24 @@ class TestPresetCatalogMultiCatalog:
|
||||
with pytest.raises(PresetValidationError, match="Invalid priority|expected integer"):
|
||||
catalog._load_catalog_config(config_path)
|
||||
|
||||
def test_load_catalog_config_rejects_infinite_priority(self, project_dir):
|
||||
"""A ``priority: .inf`` yields a clean validation error, not an uncaught
|
||||
OverflowError from int(float('inf'))."""
|
||||
config_path = project_dir / ".specify" / "preset-catalogs.yml"
|
||||
config_path.write_text(yaml.dump({
|
||||
"catalogs": [
|
||||
{
|
||||
"name": "inf-priority",
|
||||
"url": "https://example.com/catalog.json",
|
||||
"priority": float("inf"),
|
||||
}
|
||||
]
|
||||
}))
|
||||
|
||||
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"
|
||||
|
||||
Reference in New Issue
Block a user