2121import logging
2222import os
2323import re
24- from collections .abc import Mapping , Sequence
24+ from collections .abc import Mapping , MutableMapping , Sequence
2525from datetime import datetime , timezone
2626from enum import Enum , auto
2727from functools import cache , lru_cache
@@ -154,7 +154,7 @@ def _log(self, path: str, log_type: ValidationProblem, value: Optional[Any], *ar
154154
155155 elif log_type == ValidationProblem .InvalidEnum :
156156 logger .warning (
157- f"The value { args [0 ]} at { path } should be one of the following: { value } ."
157+ f"The value ' { args [0 ]} ' at { path } should be one of the following: { value } ."
158158 )
159159 elif log_type == ValidationProblem .OpenEnumWithCustom :
160160 logger .info (
@@ -166,11 +166,13 @@ def _log(self, path: str, log_type: ValidationProblem, value: Optional[Any], *ar
166166 "When a different value is used, the boolean 'custom' attribute cannot be False."
167167 )
168168 elif log_type == ValidationProblem .OpenEnumWithMissingCustom :
169- logger . info (
169+ log_text = (
170170 f"The value '{ args [0 ]} ' at { path } does not match with the enumerated items from the open enumeration: { value } . "
171- "When a different value is used, a boolean 'custom=True' attribute must be added. It was added here automatically. "
171+ "When a different value is used, a boolean 'custom=True' attribute must be added."
172172 )
173-
173+ if args [1 ] is True :
174+ log_text += " It was added here automatically."
175+ logger .info (log_text )
174176 elif log_type == ValidationProblem .MissingRequiredGroup :
175177 logger .warning (f"The required group { path } hasn't been supplied." )
176178 elif log_type == ValidationProblem .MissingRequiredField :
@@ -878,6 +880,81 @@ def validate_data_value(value: Any, nxdl_type: str, path: str) -> Any:
878880 return validate_data_value (value , nxdl_type , path )
879881
880882
883+ def get_custom_attr_path (path : str ) -> str :
884+ if path .split ("/" )[- 1 ].startswith ("@" ):
885+ attr_name = path .split ("/" )[- 1 ][1 :] # remove "@"
886+ return f"{ path } _custom"
887+ return f"{ path } /@custom"
888+
889+
890+ def is_valid_enum (
891+ value : Any ,
892+ nxdl_enum : list ,
893+ nxdl_enum_open : bool ,
894+ path : str ,
895+ mapping : MutableMapping ,
896+ ):
897+ """Check enumeration."""
898+
899+ if isinstance (value , dict ) and set (value .keys ()) == {"compress" , "strength" }:
900+ value = value ["compress" ]
901+
902+ if nxdl_enum is not None :
903+ if (
904+ isinstance (value , np .ndarray )
905+ and isinstance (nxdl_enum , list )
906+ and isinstance (nxdl_enum [0 ], list )
907+ ):
908+ enum_value = list (value )
909+ else :
910+ enum_value = value
911+
912+ if enum_value not in nxdl_enum :
913+ if nxdl_enum_open :
914+ custom_path = get_custom_attr_path (path )
915+
916+ if isinstance (mapping , h5py .Group ):
917+ parent_path , attr_name = custom_path .rsplit ("@" , 1 )
918+ custom_attr = mapping .get (parent_path ).attrs .get (attr_name )
919+ custom_added_auto = False
920+ else :
921+ custom_attr = mapping .get (custom_path )
922+ custom_added_auto = True
923+
924+ if custom_attr == True : # noqa: E712
925+ collector .collect_and_log (
926+ path ,
927+ ValidationProblem .OpenEnumWithCustom ,
928+ nxdl_enum ,
929+ value ,
930+ )
931+ elif custom_attr == False : # noqa: E712
932+ collector .collect_and_log (
933+ path ,
934+ ValidationProblem .OpenEnumWithCustomFalse ,
935+ nxdl_enum ,
936+ value ,
937+ )
938+
939+ elif custom_attr is None :
940+ try :
941+ mapping [custom_path ] = True
942+ except ValueError :
943+ # we are in the HDF5 validation, cannot set custom attribute.
944+ pass
945+ collector .collect_and_log (
946+ path ,
947+ ValidationProblem .OpenEnumWithMissingCustom ,
948+ nxdl_enum ,
949+ value ,
950+ custom_added_auto ,
951+ )
952+ else :
953+ collector .collect_and_log (
954+ path , ValidationProblem .InvalidEnum , nxdl_enum , value
955+ )
956+
957+
881958def split_class_and_name_of (name : str ) -> tuple [Optional [str ], str ]:
882959 """
883960 Return the class and the name of a data dict entry of the form
0 commit comments