|
34 | 34 | from cachetools.keys import hashkey |
35 | 35 |
|
36 | 36 | from pynxtools.dataconverter.helpers import ( |
37 | | - RESERVED_SUFFIXES, |
38 | 37 | Collector, |
39 | 38 | ValidationProblem, |
40 | 39 | check_reserved_prefix, |
| 40 | + check_reserved_suffix, |
41 | 41 | clean_str_attr, |
42 | 42 | collector, |
43 | 43 | convert_nexus_to_caps, |
44 | 44 | is_valid_data_field, |
| 45 | + split_class_and_name_of, |
45 | 46 | ) |
46 | 47 | from pynxtools.dataconverter.nexus_tree import ( |
47 | 48 | NexusEntity, |
@@ -110,31 +111,6 @@ def default_to_regular_dict(d): |
110 | 111 | return default_to_regular_dict(data_tree) |
111 | 112 |
|
112 | 113 |
|
113 | | -def split_class_and_name_of(name: str) -> tuple[Optional[str], str]: |
114 | | - """ |
115 | | - Return the class and the name of a data dict entry of the form |
116 | | - `split_class_and_name_of("ENTRY[entry]")`, which will return `("ENTRY", "entry")`. |
117 | | - If this is a simple string it will just return this string, i.e. |
118 | | - `split_class_and_name_of("entry")` will return `None, "entry"`. |
119 | | -
|
120 | | - Args: |
121 | | - name (str): The data dict entry |
122 | | -
|
123 | | - Returns: |
124 | | - tuple[Optional[str], str]: |
125 | | - First element is the class name of the entry, second element is the name. |
126 | | - The class name will be None if it is not present. |
127 | | - """ |
128 | | - name_match = re.search(r"([^\[]+)\[([^\]]+)\](\@.*)?", name) |
129 | | - if name_match is None: |
130 | | - return None, name |
131 | | - |
132 | | - prefix = name_match.group(3) |
133 | | - return name_match.group( |
134 | | - 1 |
135 | | - ), f"{name_match.group(2)}{'' if prefix is None else prefix}" |
136 | | - |
137 | | - |
138 | 114 | def is_valid_unit_for_node( |
139 | 115 | node: NexusEntity, unit: str, unit_path: str, hints: dict[str, Any] |
140 | 116 | ) -> None: |
@@ -464,37 +440,6 @@ def _check_for_nxcollection_parent(node: NexusNode): |
464 | 440 |
|
465 | 441 | return False |
466 | 442 |
|
467 | | - def check_reserved_suffix(path: str, parent_data: h5py.Group): |
468 | | - """ |
469 | | - Check if an associated field exists for a key with a reserved suffix. |
470 | | -
|
471 | | - Reserved suffixes imply the presence of an associated base field (e.g., |
472 | | - "temperature_errors" implies "temperature" must exist in the mapping). |
473 | | -
|
474 | | - Args: |
475 | | - path (str): |
476 | | - The full path in the HDF5 file (e.g., "/entry1/sample/temperature_errors"). |
477 | | - parent_data (h5py.Group): |
478 | | - The parent group of the field/attribute path to check. |
479 | | - """ |
480 | | - |
481 | | - name = path.strip("/").split("/")[-1] |
482 | | - |
483 | | - for suffix in RESERVED_SUFFIXES: |
484 | | - if name.endswith(suffix): |
485 | | - associated_field = name.rsplit(suffix, 1)[0] |
486 | | - |
487 | | - if associated_field not in parent_data: |
488 | | - collector.collect_and_log( |
489 | | - path, |
490 | | - ValidationProblem.ReservedSuffixWithoutField, |
491 | | - associated_field, |
492 | | - suffix, |
493 | | - ) |
494 | | - return |
495 | | - break # We found the suffix and it passed |
496 | | - return |
497 | | - |
498 | 443 | def has_breakpoint(key_path: str) -> bool: |
499 | 444 | """ |
500 | 445 | Walk up the path hierarchy and check if a parent is an NXcollection |
@@ -805,8 +750,7 @@ def validate(path: str, h5_obj: Union[h5py.Group, h5py.Dataset]): |
805 | 750 | handle_group(path, h5_obj) |
806 | 751 | elif isinstance(h5_obj, h5py.Dataset): |
807 | 752 | handle_field(path, h5_obj) |
808 | | - parent_path = path.strip("/").rsplit("/", 1)[0] |
809 | | - check_reserved_suffix(f"{entry_name}/{path}", data[parent_path]) |
| 753 | + check_reserved_suffix(f"{entry_name}/{path}", h5_obj.parent) |
810 | 754 | handle_attributes(path, h5_obj.attrs, h5_obj) |
811 | 755 |
|
812 | 756 | def visititems(group: h5py.Group, path: str = "", filename: str = ""): |
@@ -1336,7 +1280,7 @@ def handle_field(node: NexusNode, keys: Mapping[str, Any], prev_path: str): |
1336 | 1280 | variant_path, |
1337 | 1281 | ) |
1338 | 1282 |
|
1339 | | - check_reserved_suffix(variant_path, mapping) |
| 1283 | + check_reserved_suffix(variant_path, keys) |
1340 | 1284 | check_reserved_prefix(variant_path, get_definition(variant_path), "field") |
1341 | 1285 |
|
1342 | 1286 | # Check unit category |
@@ -1801,45 +1745,6 @@ def find_instance_name_conflicts(mapping: MutableMapping[str, str]) -> None: |
1801 | 1745 | ) |
1802 | 1746 | keys_to_remove.append(valid_key) |
1803 | 1747 |
|
1804 | | - def check_reserved_suffix(key: str, mapping: MutableMapping[str, Any]): |
1805 | | - """ |
1806 | | - Check if an associated field exists for a key with a reserved suffix. |
1807 | | -
|
1808 | | - Reserved suffixes imply the presence of an associated base field (e.g., |
1809 | | - "temperature_errors" implies "temperature" must exist in the mapping). |
1810 | | -
|
1811 | | - Args: |
1812 | | - key (str): |
1813 | | - The full key path (e.g., "/ENTRY[entry1]/sample/temperature_errors"). |
1814 | | - mapping (MutableMapping[str, Any]): |
1815 | | - The mapping containing the data to validate. |
1816 | | - This should be a dict of `/` separated paths. |
1817 | | - """ |
1818 | | - |
1819 | | - parent_path, name = key.rsplit("/", 1) |
1820 | | - concept_name, instance_name = split_class_and_name_of(name) |
1821 | | - |
1822 | | - for suffix in RESERVED_SUFFIXES: |
1823 | | - if instance_name.endswith(suffix): |
1824 | | - associated_field = instance_name.rsplit(suffix, 1)[0] |
1825 | | - |
1826 | | - if not any( |
1827 | | - k.startswith(parent_path + "/") |
1828 | | - and ( |
1829 | | - k.endswith(associated_field) |
1830 | | - or k.endswith(f"[{associated_field}]") |
1831 | | - ) |
1832 | | - for k in mapping |
1833 | | - ): |
1834 | | - collector.collect_and_log( |
1835 | | - key, |
1836 | | - ValidationProblem.ReservedSuffixWithoutField, |
1837 | | - associated_field, |
1838 | | - suffix, |
1839 | | - ) |
1840 | | - return |
1841 | | - break # We found the suffix and it passed |
1842 | | - |
1843 | 1748 | def get_definition( |
1844 | 1749 | key: str, |
1845 | 1750 | ) -> Optional[str]: |
|
0 commit comments