Skip to content

Commit

Permalink
Include YAML path in validation errors
Browse files Browse the repository at this point in the history
  • Loading branch information
GDYendell committed Mar 27, 2024
1 parent 50cb1be commit ec24832
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/pvi/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
BaseModel,
ConfigDict,
Field,
ValidationError,
field_validator,
model_validator,
)
Expand Down Expand Up @@ -463,7 +464,14 @@ def deserialize(cls, yaml: Path) -> Device:
"""
serialized = cls.validate_yaml(yaml)
return cls(**serialized)
try:
return cls(**serialized)
except ValidationError as e:
# Re-raise exception with YAML file path included
raise ValidationError.from_exception_data(
f"{e.title} {yaml}",
e.errors(), # type: ignore
) from None

def deserialize_parents(self, yaml_paths: list[Path]):
"""Populate Device with Components from Device yaml of parent classes.
Expand Down
44 changes: 44 additions & 0 deletions tests/bad.pvi.device.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
label: label
parent: parent
children:

- type: Group
name: Parameters
layout:
type: Grid
labelled: true
children:

- type: SignalW
name: WidthUnits
write_pv: WIDTH:UNITS
write_widget:
type: ComboBox

- type: SignalRW
name: Width
write_pv: WIDTH
write_widget:
type: TextWrite
read_pv: WIDTH_RBV
read_widget:
type: TextRead

- type: SignalW
name: Table
write_pv: TABLE
write_widget:
type: TableWrite
widgets:

- type: CheckBox

- type: ComboBox

- type: TextWrite

- type: SignalR
name: OutA
red_pv: OUTA
read_widget:
type: LED
7 changes: 7 additions & 0 deletions tests/test_device_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ def device():


DEVICE_YAML = Path(__file__).parent / "test.pvi.device.yaml"
BAD_DEVICE_YAML = Path(__file__).parent / "bad.pvi.device.yaml"


def test_serialize(device: Device):
Expand All @@ -72,6 +73,12 @@ def test_deserialize(device: Device):
assert d == device


def test_deserialize_raises(tmp_path):
# Check that an exception is raised with the file name included
with pytest.raises(ValidationError, match=str(BAD_DEVICE_YAML)):
Device.deserialize(BAD_DEVICE_YAML)


def test_validate_fails():
class NotTypedModel(BaseModel):
pass
Expand Down

0 comments on commit ec24832

Please sign in to comment.