fix(loaders): malformed spell_slots key raises CombatantLoadError, not bare ValueError
int(k) on a non-numeric JSON key escaped the loader as an unhandled ValueError traceback (CLI exit 1) instead of the documented exit code 2. Route the conversion through _parse_spell_slot_keys which wraps it in a CombatantLoadError with a clear message. Audited the other loader-side int()/conversions: foundry.py guards every int() with isinstance/isdigit checks and combatant.py has no other unguarded conversion.
This commit is contained in:
@@ -5,6 +5,8 @@ from __future__ import annotations
|
||||
import json
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import pytest
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
@@ -175,6 +177,23 @@ class TestSpells:
|
||||
assert c.spells == []
|
||||
|
||||
|
||||
class TestSpellSlots:
|
||||
def test_numeric_string_keys_converted(self, tmp_path: Path) -> None:
|
||||
data = _minimal_payload(spell_slots={"1": 4, "2": 3})
|
||||
c = load_combatant(_write(tmp_path, data))
|
||||
assert c.spell_slots == {1: 4, 2: 3}
|
||||
|
||||
def test_non_numeric_key_raises_load_error(self, tmp_path: Path) -> None:
|
||||
data = _minimal_payload(spell_slots={"one": 4})
|
||||
with pytest.raises(CombatantLoadError, match="spell_slots keys must be integer"):
|
||||
load_combatant(_write(tmp_path, data))
|
||||
|
||||
def test_float_key_raises_load_error(self, tmp_path: Path) -> None:
|
||||
data = _minimal_payload(spell_slots={"1.5": 4})
|
||||
with pytest.raises(CombatantLoadError, match="spell_slots keys must be integer"):
|
||||
load_combatant(_write(tmp_path, data))
|
||||
|
||||
|
||||
class TestBackwardCompatAliases:
|
||||
def test_monster_load_error_is_combatant_load_error(self) -> None:
|
||||
assert MonsterLoadError is CombatantLoadError
|
||||
|
||||
Reference in New Issue
Block a user