Skip to content

Commit b92118a

Browse files
authored
Fixes bugs in model validation when using "set_fields" (#144)
* Changes model warnings to errors * Adds clause to "set_fields" to address bug * Updates tests
1 parent b89eb00 commit b92118a

File tree

4 files changed

+52
-71
lines changed

4 files changed

+52
-71
lines changed

RATapi/classlist.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,11 @@ def set_fields(self, index: Union[int, slice, str, T], **kwargs) -> None:
318318
if isinstance(index, (str, self._class_handle)):
319319
index = self.index(index)
320320

321+
# Prioritise changing language to avoid CustomFile validator bug
322+
value = kwargs.pop("language", None)
323+
if value is not None:
324+
kwargs = {"language": value, **kwargs}
325+
321326
if importlib.util.find_spec("pydantic"):
322327
# Pydantic is installed, so set up a context manager that will
323328
# suppress custom validation errors until all fields have been set.

RATapi/models.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,8 @@ class Background(Signal):
119119
name: str = Field(default_factory=lambda: f"New Background {next(background_number)}", min_length=1)
120120

121121
@model_validator(mode="after")
122-
def warn_parameters(self):
123-
"""Raise a warning if the parameters given are not expected for the given type."""
122+
def check_unsupported_parameters(self):
123+
"""Raise an error if the parameters given are not supported for the given type."""
124124
if self.type == TypeOptions.Constant:
125125
expected_empty_fields = ["value_1", "value_2", "value_3", "value_4", "value_5"]
126126
elif self.type == TypeOptions.Data:
@@ -130,10 +130,9 @@ def warn_parameters(self):
130130

131131
non_empty_fields = [v for v in expected_empty_fields if getattr(self, v) != ""]
132132
if non_empty_fields:
133-
warnings.warn(
134-
"The following values are not recognised by this background type and will be ignored: "
135-
f"{', '.join(non_empty_fields)}",
136-
stacklevel=2,
133+
raise ValueError(
134+
f'The following values are not supported by the "{self.type}" Background type: '
135+
f"{', '.join(non_empty_fields)}"
137136
)
138137

139138
return self
@@ -630,8 +629,8 @@ def validate_unimplemented_resolutions(cls, type: TypeOptions):
630629
return type
631630

632631
@model_validator(mode="after")
633-
def warn_parameters(self):
634-
"""Raise a warning if the parameters given are not expected for the given type."""
632+
def check_unsupported_parameters(self):
633+
"""Raise an error if the parameters given are not supported for the given type."""
635634
if self.type == TypeOptions.Constant:
636635
expected_empty_fields = ["value_1", "value_2", "value_3", "value_4", "value_5"]
637636
elif self.type == TypeOptions.Data:
@@ -641,10 +640,9 @@ def warn_parameters(self):
641640

642641
non_empty_fields = [v for v in expected_empty_fields if getattr(self, v) != ""]
643642
if non_empty_fields:
644-
warnings.warn(
645-
"The following values are not recognised by this resolution type and will be ignored: "
646-
f"{', '.join(non_empty_fields)}",
647-
stacklevel=2,
643+
raise ValueError(
644+
f'The following values are not supported by the "{self.type}" Resolution type: '
645+
f"{', '.join(non_empty_fields)}"
648646
)
649647

650648
return self

tests/test_models.py

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -334,22 +334,50 @@ def test_contrast_bad_ratio():
334334
RATapi.models.Contrast(name="My Contrast", domain_ratio="bad ratio")
335335

336336

337-
@pytest.mark.parametrize("model", [RATapi.models.Background, RATapi.models.Resolution])
338-
@pytest.mark.filterwarnings("ignore:The following values are not recognised by this*:UserWarning")
339-
def test_type_change_clear(model):
337+
@pytest.mark.parametrize(
338+
["model", "type", "values"],
339+
[
340+
(RATapi.models.Background, "function", ["val1", "val2", "val3", "val4", "val5"]),
341+
(RATapi.models.Resolution, "constant", ["", "", "", "", ""]),
342+
],
343+
)
344+
def test_type_change_clear(model, type, values):
340345
"""If the type of a background or resolution is changed, it should wipe the other fields and warn the user."""
341346
model_instance = model(
342347
name="Test",
343-
type="constant",
348+
type=type,
344349
source="src",
345-
value_1="val1",
346-
value_2="val2",
347-
value_3="val3",
348-
value_4="val4",
349-
value_5="val5",
350+
value_1=values[0],
351+
value_2=values[1],
352+
value_3=values[2],
353+
value_4=values[3],
354+
value_5=values[4],
350355
)
351356

352357
with pytest.warns(UserWarning, match="Changing the type of Test clears its source and value fields."):
353358
model_instance.type = "data"
354359
for attr in ["source", "value_1", "value_2", "value_3", "value_4", "value_5"]:
355360
assert getattr(model_instance, attr) == ""
361+
362+
363+
@pytest.mark.parametrize(
364+
["model", "signal_type", "values"],
365+
[
366+
(RATapi.models.Background, "constant", ["value_1", "value_2", "value_3", "value_4", "value_5"]),
367+
(RATapi.models.Background, "data", ["value_2", "value_3", "value_4", "value_5"]),
368+
(RATapi.models.Resolution, "constant", ["value_1", "value_2", "value_3", "value_4", "value_5"]),
369+
(RATapi.models.Resolution, "data", ["value_1", "value_2", "value_3", "value_4", "value_5"]),
370+
],
371+
)
372+
def test_unsupported_parameters_error(model, signal_type, values):
373+
"""If a value is inputted for an unsupported field for a particular type of background or resolution then we should
374+
raise an error."""
375+
for value in values:
376+
with pytest.raises(
377+
pydantic.ValidationError,
378+
match=(
379+
f"1 validation error for {model.__name__}\n Value error, The following values are not supported"
380+
f' by the "{signal_type}" {model.__name__} type: {value}'
381+
),
382+
):
383+
model(**{"type": signal_type, value: "unsupported"})

tests/test_project.py

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,17 +1137,7 @@ def test_write_script_wrong_extension(test_project, extension: str) -> None:
11371137
["class_list", "model_type", "field"],
11381138
[
11391139
("backgrounds", "constant", "source"),
1140-
("backgrounds", "", "value_1"),
1141-
("backgrounds", "", "value_2"),
1142-
("backgrounds", "", "value_3"),
1143-
("backgrounds", "", "value_4"),
1144-
("backgrounds", "", "value_5"),
11451140
("resolutions", "constant", "source"),
1146-
("resolutions", "", "value_1"),
1147-
("resolutions", "", "value_2"),
1148-
("resolutions", "", "value_3"),
1149-
("resolutions", "", "value_4"),
1150-
("resolutions", "", "value_5"),
11511141
("layers", "", "thickness"),
11521142
("layers", "", "SLD"),
11531143
("layers", "", "roughness"),
@@ -1216,17 +1206,7 @@ def test_wrap_del(test_project, class_list: str, parameter: str, field: str) ->
12161206
["class_list", "model_type", "field", "model_params"],
12171207
[
12181208
("backgrounds", "constant", "source", {}),
1219-
("backgrounds", "", "value_1", {}),
1220-
("backgrounds", "", "value_2", {}),
1221-
("backgrounds", "", "value_3", {}),
1222-
("backgrounds", "", "value_4", {}),
1223-
("backgrounds", "", "value_5", {}),
12241209
("resolutions", "constant", "source", {}),
1225-
("resolutions", "", "value_1", {}),
1226-
("resolutions", "", "value_2", {}),
1227-
("resolutions", "", "value_3", {}),
1228-
("resolutions", "", "value_4", {}),
1229-
("resolutions", "", "value_5", {}),
12301210
("layers", "", "thickness", layer_params),
12311211
("layers", "", "SLD", layer_params),
12321212
("layers", "", "roughness", layer_params),
@@ -1263,17 +1243,7 @@ def test_wrap_iadd(test_project, class_list: str, model_type: str, field: str, m
12631243
["class_list", "model_type", "field", "model_params"],
12641244
[
12651245
("backgrounds", "constant", "source", {}),
1266-
("backgrounds", "", "value_1", {}),
1267-
("backgrounds", "", "value_2", {}),
1268-
("backgrounds", "", "value_3", {}),
1269-
("backgrounds", "", "value_4", {}),
1270-
("backgrounds", "", "value_5", {}),
12711246
("resolutions", "constant", "source", {}),
1272-
("resolutions", "", "value_1", {}),
1273-
("resolutions", "", "value_2", {}),
1274-
("resolutions", "", "value_3", {}),
1275-
("resolutions", "", "value_4", {}),
1276-
("resolutions", "", "value_5", {}),
12771247
("layers", "", "thickness", layer_params),
12781248
("layers", "", "SLD", layer_params),
12791249
("layers", "", "roughness", layer_params),
@@ -1311,17 +1281,7 @@ def test_wrap_append(test_project, class_list: str, model_type: str, field: str,
13111281
["class_list", "model_type", "field", "model_params"],
13121282
[
13131283
("backgrounds", "constant", "source", {}),
1314-
("backgrounds", "", "value_1", {}),
1315-
("backgrounds", "", "value_2", {}),
1316-
("backgrounds", "", "value_3", {}),
1317-
("backgrounds", "", "value_4", {}),
1318-
("backgrounds", "", "value_5", {}),
13191284
("resolutions", "constant", "source", {}),
1320-
("resolutions", "", "value_1", {}),
1321-
("resolutions", "", "value_2", {}),
1322-
("resolutions", "", "value_3", {}),
1323-
("resolutions", "", "value_4", {}),
1324-
("resolutions", "", "value_5", {}),
13251285
("layers", "", "thickness", layer_params),
13261286
("layers", "", "SLD", layer_params),
13271287
("layers", "", "roughness", layer_params),
@@ -1492,17 +1452,7 @@ def test_wrap_clear(test_project, class_list: str, parameter: str, field: str) -
14921452
["class_list", "model_type", "field", "model_params"],
14931453
[
14941454
("backgrounds", "constant", "source", {}),
1495-
("backgrounds", "", "value_1", {}),
1496-
("backgrounds", "", "value_2", {}),
1497-
("backgrounds", "", "value_3", {}),
1498-
("backgrounds", "", "value_4", {}),
1499-
("backgrounds", "", "value_5", {}),
15001455
("resolutions", "constant", "source", {}),
1501-
("resolutions", "", "value_1", {}),
1502-
("resolutions", "", "value_2", {}),
1503-
("resolutions", "", "value_3", {}),
1504-
("resolutions", "", "value_4", {}),
1505-
("resolutions", "", "value_5", {}),
15061456
("layers", "", "thickness", layer_params),
15071457
("layers", "", "SLD", layer_params),
15081458
("layers", "", "roughness", layer_params),

0 commit comments

Comments
 (0)