Skip to content

Commit 0986b0a

Browse files
committed
use feature branch from pynxtools-xps
1 parent 0a8d199 commit 0986b0a

File tree

4 files changed

+70
-66
lines changed

4 files changed

+70
-66
lines changed

.github/workflows/plugin_test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
branch: main
4343
tests_to_run: tests/.
4444
- plugin: pynxtools-xps
45-
branch: main
45+
branch: custom-attr-for-open-enum
4646
tests_to_run: tests/.
4747
- plugin: pynxtools-xrd
4848
branch: main

src/pynxtools/dataconverter/helpers.py

Lines changed: 22 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,9 @@ class ValidationProblem(Enum):
5757
UnitWithoutDocumentation = auto()
5858
InvalidUnit = auto()
5959
InvalidEnum = auto()
60-
OpenEnumWithCorrectNewItem = auto()
61-
OpenEnumWithIncorrectNewItem = auto()
60+
OpenEnumWithCustom = auto()
61+
OpenEnumWithCustomFalse = auto()
62+
OpenEnumWithMissingCustom = auto()
6263
MissingRequiredGroup = auto()
6364
MissingRequiredField = auto()
6465
MissingRequiredAttribute = auto()
@@ -85,7 +86,6 @@ class ValidationProblem(Enum):
8586
KeysWithAndWithoutConcept = auto()
8687
InvalidCompressionStrength = auto()
8788
CompressionStrengthZero = auto()
88-
# DoNotCompressStringsBoolean = auto()
8989

9090

9191
class Collector:
@@ -119,22 +119,22 @@ def _log(self, path: str, log_type: ValidationProblem, value: Optional[Any], *ar
119119

120120
elif log_type == ValidationProblem.InvalidEnum:
121121
logger.warning(
122-
f"The value at {path} should be one of the following: {value}."
122+
f"The value '{args[0]}' at {path} should be one of the following: {value}."
123123
)
124-
elif log_type == ValidationProblem.OpenEnumWithCorrectNewItem:
124+
elif log_type == ValidationProblem.OpenEnumWithCustom:
125125
logger.info(
126126
f"The value '{args[0]}' at {path} does not match with the enumerated items from the open enumeration: {value}."
127127
)
128-
elif log_type == ValidationProblem.OpenEnumWithIncorrectNewItem:
129-
actual_value, custom_attr = args
130-
131-
log_text = f"The value '{actual_value}' at {path} does not match with the enumerated items from the open enumeration: {value}."
132-
if custom_attr == "custom_missing":
133-
log_text += f" When a different value is used, a boolean 'custom' attribute must be added."
134-
logger.warning(log_text)
135-
elif custom_attr == "custom_false":
136-
log_text += f" When a different value is used, the boolean 'custom' attribute cannot be False."
137-
logger.warning(log_text)
128+
elif log_type == ValidationProblem.OpenEnumWithCustomFalse:
129+
logger.warning(
130+
f"The value '{args[0]}' at {path} does not match with the enumerated items from the open enumeration: {value}."
131+
"When a different value is used, the boolean 'custom' attribute cannot be False."
132+
)
133+
elif log_type == ValidationProblem.OpenEnumWithMissingCustom:
134+
logger.info(
135+
f"The value '{args[0]}' at {path} does not match with the enumerated items from the open enumeration: {value}. "
136+
"When a different value is used, a boolean 'custom=True' attribute must be added. It was added here automatically."
137+
)
138138

139139
elif log_type == ValidationProblem.MissingRequiredGroup:
140140
logger.warning(f"The required group, {path}, hasn't been supplied.")
@@ -231,18 +231,6 @@ def _log(self, path: str, log_type: ValidationProblem, value: Optional[Any], *ar
231231
logger.warning(
232232
f"Compression strength for {path} = {value} should be between 0 and 9."
233233
)
234-
# elif log_type == ValidationProblem.DoNotCompressStringsBoolean:
235-
# value = cast(dict, value)
236-
# dtype = type(value["compress"]).__name__
237-
# dtype_map = {
238-
# "str": "string",
239-
# "bool": "boolean",
240-
# }
241-
# dtype_str = dtype_map.get(dtype, dtype)
242-
243-
# logger.info(
244-
# f"Compression for {path} = {value} should not be used for {dtype_str} values."
245-
# )
246234

247235
def collect_and_log(
248236
self,
@@ -264,9 +252,9 @@ def collect_and_log(
264252
# info messages should not fail validation
265253
if log_type not in (
266254
ValidationProblem.UnitWithoutDocumentation,
267-
ValidationProblem.OpenEnumWithNewItem,
268255
ValidationProblem.CompressionStrengthZero,
269-
ValidationProblem.OpenEnumWithCorrectNewItem,
256+
ValidationProblem.OpenEnumWithCustom,
257+
ValidationProblem.OpenEnumWithMissingCustom,
270258
):
271259
self.data.add(path + str(log_type) + str(value))
272260

@@ -777,10 +765,8 @@ def convert_int_to_float(value):
777765
def is_valid_data_field(value: Any, nxdl_type: str, path: str) -> Any:
778766
"""Checks whether a given value is valid according to the type defined in the NXDL."""
779767

780-
def validate_data_value(
781-
value: Any, nxdl_type: str, nxdl_enum: list, nxdl_enum_open: bool, path: str
782-
) -> Any:
783-
"""Validate and possibly convert a primitive value according to NXDL type/enum rules."""
768+
def validate_data_value(value: Any, nxdl_type: str, path: str) -> Any:
769+
"""Validate and possibly convert a primitive value according to NXDL type rules."""
784770
accepted_types = NEXUS_TO_PYTHON_DATA_TYPES[nxdl_type]
785771
original_value = value
786772

@@ -811,16 +797,6 @@ def validate_data_value(
811797
path, ValidationProblem.InvalidDatetime, value
812798
)
813799

814-
if nxdl_enum is not None and value not in nxdl_enum:
815-
if nxdl_enum_open:
816-
collector.collect_and_log(
817-
path, ValidationProblem.OpenEnumWithNewItem, nxdl_enum
818-
)
819-
else:
820-
collector.collect_and_log(
821-
path, ValidationProblem.InvalidEnum, nxdl_enum
822-
)
823-
824800
return value
825801

826802
if isinstance(value, dict) and set(value.keys()) == {"compress", "strength"}:
@@ -836,24 +812,14 @@ def validate_data_value(
836812
path, ValidationProblem.InvalidCompressionStrength, value
837813
)
838814
# In this case, we remove the compression.
839-
return validate_data_value(
840-
value["compress"], nxdl_type, nxdl_enum, nxdl_enum_open, path
841-
)
842-
843-
# TODO: Do we need to issue a warning if string/bool compression is used
844-
# # elif isinstance(compressed_value, (str, bool)):
845-
# collector.collect_and_log(
846-
# path, ValidationProblem.DoNotCompressStringsBoolean, value
847-
# )
815+
return validate_data_value(value["compress"], nxdl_type, path)
848816

849817
# Apply standard validation to compressed value
850-
value["compress"] = validate_data_value(
851-
compressed_value, nxdl_type, nxdl_enum, nxdl_enum_open, path
852-
)
818+
value["compress"] = validate_data_value(compressed_value, nxdl_type, path)
853819

854820
return value
855821

856-
return validate_data_value(value, nxdl_type, nxdl_enum, nxdl_enum_open, path)
822+
return validate_data_value(value, nxdl_type, path)
857823

858824

859825
@cache

src/pynxtools/dataconverter/validation.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1241,7 +1241,11 @@ def is_valid_enum(
12411241
path: str,
12421242
mapping: MutableMapping,
12431243
):
1244-
# Check enumeration
1244+
"""Check enumeration."""
1245+
1246+
if isinstance(value, dict) and set(value.keys()) == {"compress", "strength"}:
1247+
value = value["compress"]
1248+
12451249
if nxdl_enum is not None and value not in nxdl_enum:
12461250
if nxdl_enum_open:
12471251
if path.split("/")[-1].startswith("@"):
@@ -1256,23 +1260,29 @@ def is_valid_enum(
12561260
if custom_attr is True:
12571261
collector.collect_and_log(
12581262
path,
1259-
ValidationProblem.OpenEnumWithCorrectNewItem,
1263+
ValidationProblem.OpenEnumWithCustom,
12601264
nxdl_enum,
12611265
value,
12621266
)
1263-
else:
1267+
elif custom_attr is False:
1268+
collector.collect_and_log(
1269+
path,
1270+
ValidationProblem.OpenEnumWithCustomFalse,
1271+
nxdl_enum,
1272+
value,
1273+
)
1274+
1275+
elif custom_attr is None:
1276+
mapping[path] = True
12641277
collector.collect_and_log(
12651278
path,
1266-
ValidationProblem.OpenEnumWithIncorrectNewItem,
1279+
ValidationProblem.OpenEnumWithMissingCustom,
12671280
nxdl_enum,
12681281
value,
1269-
"custom_false" if custom_attr is False else "custom_missing",
12701282
)
12711283
else:
12721284
collector.collect_and_log(
1273-
path,
1274-
ValidationProblem.InvalidEnum,
1275-
nxdl_enum,
1285+
path, ValidationProblem.InvalidEnum, nxdl_enum, value
12761286
)
12771287

12781288
def check_reserved_suffix(key: str, mapping: MutableMapping[str, Any]) -> bool:

tests/dataconverter/test_validation.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,32 @@ def listify_template(data_dict: Template):
856856
],
857857
id="open-enum-with-new-item",
858858
),
859+
pytest.param(
860+
alter_dict(
861+
alter_dict(
862+
alter_dict(
863+
alter_dict(
864+
TEMPLATE,
865+
"/ENTRY[my_entry]/NXODD_name[nxodd_name]/type2",
866+
{"compress": "a very different type", "strength": 2},
867+
),
868+
"/ENTRY[my_entry]/NXODD_name[nxodd_name]/type2/@custom",
869+
True,
870+
),
871+
"/ENTRY[my_entry]/NXODD_name[nxodd_name]/type2/@attribute_with_open_enum",
872+
{"compress": "3rd option", "strength": 4},
873+
),
874+
"/ENTRY[my_entry]/NXODD_name[nxodd_name]/type2/@attribute_with_open_enum_custom",
875+
True,
876+
),
877+
[
878+
"The value 'a very different type' at /ENTRY[my_entry]/NXODD_name[nxodd_name]/type2 does not match "
879+
"with the enumerated items from the open enumeration: ['1st type open', '2nd type open'].",
880+
"The value '3rd option' at /ENTRY[my_entry]/NXODD_name[nxodd_name]/type2/@attribute_with_open_enum "
881+
"does not match with the enumerated items from the open enumeration: ['1st option', '2nd option'].",
882+
],
883+
id="open-enum-with-new-item-compressed",
884+
),
859885
pytest.param(
860886
alter_dict(
861887
alter_dict(
@@ -1879,12 +1905,14 @@ def format_error_message(msg: str) -> str:
18791905
"field-with-illegal-unit",
18801906
"baseclass-field-with-illegal-unit",
18811907
"open-enum-with-new-item",
1908+
"open-enum-with-new-item-compressed",
18821909
"baseclass-open-enum-with-new-item",
18831910
"appdef-compressed-strength-0",
18841911
):
18851912
with caplog.at_level(logging.INFO):
18861913
assert validate_dict_against("NXtest", data_dict)
1887-
assert error_messages[0] in caplog.text
1914+
for expected_message, rec in zip(error_messages, caplog.records):
1915+
assert expected_message == format_error_message(rec.message)
18881916
else:
18891917
with caplog.at_level(logging.WARNING):
18901918
assert not validate_dict_against("NXtest", data_dict)

0 commit comments

Comments
 (0)