@@ -21,8 +21,6 @@ class DataProduction(
2121):
2222 """Dataset production context metadata."""
2323
24- owner : str | None = None
25- license : str | None = None
2624 type : str | None = None
2725 physics : str | None = None
2826 simulator : str | None = None
@@ -52,15 +50,26 @@ class Infos(
5250):
5351 """Structured representation of a PLAID dataset ``infos`` payload."""
5452
55- # model_config = _PD_CONFIG
56-
5753 owner : str
5854 license : str
5955 data_production : DataProduction | None = None
6056 data_description : str | None = None
6157 num_samples : dict [str , int ] = Field (default_factory = dict )
6258 storage_backend : str | None = None
6359
60+ @classmethod
61+ def print_available_fields (cls ) -> None :
62+ """Print the public constructor fields accepted by :class:`Infos`."""
63+ print ("Infos fields:" )
64+ for field_name in cls .model_fields :
65+ print (f" - { field_name } " )
66+ if field_name in {"num_samples" , "storage_backend" }:
67+ print (" note: automatically filled when calling save_to_disk" )
68+ if field_name == "data_production" :
69+ print (" subfields:" )
70+ for subfield_name in DataProduction .model_fields :
71+ print (f" - { subfield_name } " )
72+
6473 def require_persisted (self ) -> "Infos" :
6574 """Validate fields that must exist in persisted dataset infos.
6675
@@ -142,8 +151,8 @@ def from_path(
142151 """Load and validate an :class:`Infos` from a YAML file.
143152
144153 Args:
145- path: Path to the YAML file (typically ``infos.yaml``) or to a
146- directory containing it .
154+ path: Path to the YAML file (typically ``infos.yaml``). If no
155+ suffix is provided, ``.yaml`` is appended .
147156 require_persisted: When True, require storage-derived metadata
148157 fields expected in a complete on-disk dataset.
149158
@@ -152,10 +161,15 @@ def from_path(
152161
153162 Raises:
154163 FileNotFoundError: If the resolved YAML file does not exist.
164+ IsADirectoryError: If ``path`` points to a directory.
155165 """
156166 path = Path (path )
157167 if path .is_dir ():
158- path = path / "infos.yaml"
168+ raise IsADirectoryError (
169+ f'Expected a YAML file path, got directory "{ path } "'
170+ )
171+ if path .suffix != ".yaml" :
172+ path = path .with_suffix (".yaml" )
159173 if not path .exists ():
160174 raise FileNotFoundError (f'File "{ path } " does not exist. Abort' )
161175
@@ -171,22 +185,28 @@ def save_to_file(self, path: Union[str, Path]) -> None:
171185 """Save infos to ``path`` as a YAML file.
172186
173187 Args:
174- path: File path (or directory) where the YAML will be written. If
175- ``path`` is a directory it will be extended with ``infos.yaml``.
188+ path: File path where the YAML will be written. If no suffix is
189+ provided, ``.yaml`` is appended.
190+
191+ Raises:
192+ IsADirectoryError: If ``path`` points to a directory.
176193 """
194+ self .require_persisted ()
195+
177196 path = Path (path )
178- if path .suffix == "" and not path . exists ():
179- # Treat suffix-less paths as directories.
180- path = path / "infos.yaml"
181- elif path . is_dir ():
182- path = path / "infos.yaml"
197+ if path .is_dir ():
198+ raise IsADirectoryError (
199+ f'Expected a YAML file path, got directory " { path } "'
200+ )
201+
183202 if path .suffix != ".yaml" :
184203 path = path .with_suffix (".yaml" )
185204
186205 path .parent .mkdir (parents = True , exist_ok = True )
187206
188207 data = self .model_dump (exclude_none = True , exclude_unset = True )
189208 ordered_data = {key : data [key ] for key in _KEY_ORDER if key in data }
209+
190210 # Preserve any future fields.
191211 for key , value in data .items ():
192212 if key not in ordered_data :
0 commit comments