FourCIPP 1.14.0__py3-none-any.whl → 1.15.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fourcipp/fourc_input.py CHANGED
@@ -41,8 +41,8 @@ from fourcipp.utils.dict_utils import (
41
41
  compare_nested_dicts_or_lists,
42
42
  sort_by_key_order,
43
43
  )
44
- from fourcipp.utils.not_set import NotSet, check_if_set
45
- from fourcipp.utils.typing import Path
44
+ from fourcipp.utils.not_set import NOT_SET, check_if_set
45
+ from fourcipp.utils.type_hinting import Path
46
46
  from fourcipp.utils.validation import ValidationError, validate_using_json_schema
47
47
  from fourcipp.utils.yaml_io import dump_yaml, load_yaml
48
48
 
@@ -289,7 +289,7 @@ class FourCInput:
289
289
  f"Section '{key}' not set. Did out mean '{difflib.get_close_matches(key.upper(), self.all_sections_names, n=1, cutoff=0.3)[0]}'? The set sections are:\n - {sections}"
290
290
  )
291
291
 
292
- def pop(self, key: str, default_value: Any = NotSet) -> Any:
292
+ def pop(self, key: str, default_value: Any = NOT_SET) -> Any:
293
293
  """Pop entry.
294
294
 
295
295
  Args:
@@ -27,7 +27,7 @@ from fourcipp.legacy_io.element import read_element, write_element
27
27
  from fourcipp.legacy_io.node import read_node, write_node
28
28
  from fourcipp.legacy_io.node_topology import read_node_topology, write_node_topology
29
29
  from fourcipp.legacy_io.particle import read_particle, write_particle
30
- from fourcipp.utils.typing import T
30
+ from fourcipp.utils.type_hinting import T
31
31
 
32
32
 
33
33
  def _iterate_and_evaluate(function: Callable[..., T], iterable: Sequence) -> list[T]:
@@ -30,7 +30,7 @@ from fourcipp.legacy_io.inline_dat import (
30
30
  nested_casting_factory,
31
31
  to_dat_string,
32
32
  )
33
- from fourcipp.utils.typing import LineCastingDict
33
+ from fourcipp.utils.type_hinting import LineCastingDict
34
34
 
35
35
  ElementCastingDict: TypeAlias = dict[str, dict[str, LineCastingDict]]
36
36
 
@@ -24,8 +24,8 @@
24
24
  from functools import partial
25
25
  from typing import Any
26
26
 
27
- from fourcipp.utils.metadata import METADATA_TO_PYTHON
28
- from fourcipp.utils.typing import (
27
+ from fourcipp.utils.metadata import Primitive
28
+ from fourcipp.utils.type_hinting import (
29
29
  Extractor,
30
30
  LineCastingDict,
31
31
  LineListExtractor,
@@ -34,7 +34,7 @@ from fourcipp.utils.typing import (
34
34
  )
35
35
 
36
36
  # Metadata types currently supported
37
- SUPPORTED_METADATA_TYPES = list(METADATA_TO_PYTHON.keys()) + ["vector", "enum"]
37
+ SUPPORTED_METADATA_TYPES = Primitive.PRIMITIVE_TYPES + ["enum", "vector"]
38
38
 
39
39
 
40
40
  def to_dat_string(object: Any) -> str:
@@ -121,10 +121,12 @@ def _entry_casting_factory(spec: dict) -> LineListExtractor:
121
121
  Returns:
122
122
  Casting function for the spec
123
123
  """
124
- if spec["type"] in METADATA_TO_PYTHON:
125
- return partial(_extract_entry, extractor=METADATA_TO_PYTHON[spec["type"]])
124
+ if spec["type"] in Primitive.PRIMITIVE_TYPES_TO_PYTHON:
125
+ return partial(
126
+ _extract_entry, extractor=Primitive.PRIMITIVE_TYPES_TO_PYTHON[spec["type"]]
127
+ )
126
128
  elif spec["type"] == "vector":
127
- value_type = METADATA_TO_PYTHON[spec["value_type"]["type"]]
129
+ value_type = Primitive.PRIMITIVE_TYPES_TO_PYTHON[spec["value_type"]["type"]]
128
130
  return partial(_extract_vector, extractor=value_type, size=spec["size"])
129
131
  elif spec["type"] == "enum":
130
132
  choices = [s["name"] for s in spec["choices"]]
@@ -31,7 +31,7 @@ from fourcipp.legacy_io.inline_dat import (
31
31
  inline_dat_read,
32
32
  to_dat_string,
33
33
  )
34
- from fourcipp.utils.typing import LineCastingDict
34
+ from fourcipp.utils.type_hinting import LineCastingDict
35
35
 
36
36
  _particle_casting = casting_factory(CONFIG.fourc_metadata["legacy_particle_specs"])
37
37
 
fourcipp/utils/cli.py CHANGED
@@ -33,7 +33,7 @@ from fourcipp.utils.configuration import (
33
33
  change_profile,
34
34
  show_config,
35
35
  )
36
- from fourcipp.utils.typing import Path
36
+ from fourcipp.utils.type_hinting import Path
37
37
  from fourcipp.utils.yaml_io import dump_yaml, load_yaml
38
38
 
39
39
 
@@ -28,7 +28,7 @@ from dataclasses import dataclass, field
28
28
 
29
29
  from loguru import logger
30
30
 
31
- from fourcipp.utils.typing import Path
31
+ from fourcipp.utils.type_hinting import Path
32
32
  from fourcipp.utils.yaml_io import dump_yaml, load_yaml
33
33
 
34
34
  CONFIG_PACKAGE: pathlib.Path = pathlib.Path(__file__).parents[1] / "config"
@@ -19,14 +19,999 @@
19
19
  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
21
  # THE SOFTWARE.
22
- """Metadata utils."""
22
+ """Metadata objects from the 4C input metadata."""
23
23
 
24
- import pathlib
24
+ from __future__ import annotations
25
25
 
26
- METADATA_TO_PYTHON: dict = {
27
- "int": int,
28
- "double": float,
29
- "string": str,
30
- "bool": bool,
31
- "path": pathlib.Path,
32
- }
26
+ import abc
27
+ import re
28
+ from collections.abc import Generator, Sequence
29
+ from typing import Callable, Literal, Protocol, TypeAlias, TypeVar
30
+
31
+ from fourcipp.utils.not_set import NotSet, check_if_set
32
+ from fourcipp.utils.type_hinting import NotSetAlias
33
+
34
+ PRIMITIVES_PYTHON_TYPES = float | bool | int | str
35
+
36
+ ValidatorAlias: TypeAlias = Callable[[object], bool] | None
37
+
38
+ NotSetString: NotSetAlias[str] = NotSet(str)
39
+
40
+ T = TypeVar("T", int, float)
41
+ G = TypeVar("G", contravariant=True)
42
+
43
+
44
+ class InputSpec:
45
+ """Input spec base class."""
46
+
47
+ def __init__(
48
+ self,
49
+ spec_type: str,
50
+ name: NotSetAlias[str] = NotSetString,
51
+ description: NotSetAlias[str] = NotSetString,
52
+ required: bool = False,
53
+ noneable: bool = False,
54
+ validator: ValidatorAlias = None,
55
+ ) -> None:
56
+ """Initialise InputSpec.
57
+
58
+ Args:
59
+ spec_type (str): Type of input spec
60
+ name: Name
61
+ description: Description
62
+ required: True if parameter is required
63
+ noneable: True if parameter can be None
64
+ validator: Validator callable
65
+ """
66
+ self.spec_type = spec_type
67
+ self.name = name
68
+ self.description = description
69
+ self.required = required
70
+ self.noneable = noneable
71
+ self.validator = validator
72
+
73
+ @classmethod
74
+ @abc.abstractmethod
75
+ def from_4C_metadata(cls, data_dict: dict) -> InputSpec:
76
+ """Create InputSpec from 4C metadata file.
77
+
78
+ Args:
79
+ data_dict: Data from 4C metadata file
80
+
81
+ Returns:
82
+ InputSpec
83
+ """
84
+
85
+
86
+ class All_Of:
87
+ def __init__(
88
+ self,
89
+ specs: Sequence[Spec],
90
+ description: NotSetAlias[str] = NotSetString,
91
+ ) -> None:
92
+ """Initialise All_Of.
93
+
94
+ Args:
95
+ specs: Specs of the All_Of
96
+ description: Description
97
+ """
98
+ self.specs: list[InputSpec | One_Of] = All_Of.condense(specs)
99
+ self.description = description
100
+
101
+ @staticmethod
102
+ def condense(specs: Sequence[Spec]) -> list[InputSpec | One_Of]:
103
+ """Condense All_Of.
104
+
105
+ All_Ofs of All_Ofs are joined, aka flattened or condensed.
106
+
107
+ Args:
108
+ specs: Specs to condense
109
+
110
+ Returns:
111
+ Condensed specs
112
+ """
113
+ new_specs: list[InputSpec | One_Of] = []
114
+ one_ofs: list[One_Of] = []
115
+
116
+ for spec in specs:
117
+ match spec:
118
+ case InputSpec():
119
+ new_specs.append(spec)
120
+ case All_Of():
121
+ # Check if it is an One_Of
122
+ if spec.is_one_of():
123
+ one_ofs.append(spec.specs[0]) # type: ignore
124
+ else:
125
+ new_specs.extend(All_Of.condense(spec.specs))
126
+ case One_Of():
127
+ one_ofs.append(spec)
128
+ case _:
129
+ raise TypeError(f"Invalid spec {spec}")
130
+
131
+ if len(one_ofs) > 1:
132
+ oo = "\n".join([str(oo) for oo in one_ofs])
133
+ raise ValueError(f"More than one_of is not allowed {oo}")
134
+
135
+ if one_ofs:
136
+ new_specs = [one_ofs[0].add_specs(new_specs)]
137
+
138
+ return new_specs
139
+
140
+ def add_specs(self, input_specs: Sequence[Spec]) -> All_Of:
141
+ """Add specs to the All_Of.
142
+
143
+ Returns:
144
+ All_Of object.
145
+ """
146
+ self.specs = All_Of.condense(self.specs + list(input_specs))
147
+ return self
148
+
149
+ def is_one_of(self) -> bool:
150
+ """Check if All_Of only hold a One_Of.
151
+
152
+ In essence this means that the All_Of is simply a One_Of.
153
+
154
+ Returns:
155
+ True if is a One_Of in disguise
156
+ """
157
+ return len(self.specs) == 1 and isinstance(self.specs[0], One_Of)
158
+
159
+ @classmethod
160
+ def from_4C_metadata(cls, data_dict: dict) -> All_Of:
161
+ """Create All_Of from 4C metadata file.
162
+
163
+ Args:
164
+ data_dict: Data from 4C metadata file
165
+
166
+ Returns:
167
+ All_Of
168
+ """
169
+ data_dict.pop("type", None)
170
+ specs = data_dict.pop("specs", [])
171
+ specs = [metadata_from_dict(spec) for spec in specs]
172
+ return cls(specs=specs, **data_dict)
173
+
174
+ def __str__(self) -> str: # pragma: no cover
175
+ """String method."""
176
+ return "All_of(" + ", ".join([str(spec) for spec in self.specs]) + ")"
177
+
178
+ def __repr__(self) -> str: # pragma: no cover
179
+ """Representation method."""
180
+ return "All_of(" + ", ".join([str(spec) for spec in self.specs]) + ")"
181
+
182
+ def __len__(self) -> int:
183
+ """Len of the All_Of.
184
+
185
+ Returns:
186
+ number of specs
187
+ """
188
+ return len(self.specs)
189
+
190
+ def __iter__(self) -> Generator[One_Of | InputSpec]:
191
+ """Iterate All_Of.
192
+
193
+ Yields:
194
+ All_Of specs
195
+ """
196
+ yield from self.specs
197
+
198
+
199
+ class One_Of:
200
+ def __init__(
201
+ self,
202
+ specs: Sequence[Spec],
203
+ description: NotSetAlias[str] = NotSetString,
204
+ ) -> None:
205
+ """Initialise One_Of.
206
+
207
+ Args:
208
+ specs: Specs of the One_Of, i.e., each distinct branch
209
+ description: Description
210
+ """
211
+ self.specs: list[All_Of] = One_Of.condense(specs)
212
+ self.description = description
213
+
214
+ @staticmethod
215
+ def condense(specs: Sequence[Spec]) -> list[All_Of]:
216
+ """Condense One_Of.
217
+
218
+ One_Ofs of One_Ofs are combined to a single One_Of.
219
+
220
+ Args:
221
+ specs: Specs of the One_Of
222
+
223
+ Returns:
224
+ condesed specs
225
+ """
226
+ new_specs: list[All_Of] = []
227
+
228
+ for spec in specs:
229
+ match spec:
230
+ case InputSpec():
231
+ new_specs.append(All_Of([spec]))
232
+ case All_Of():
233
+ if spec.is_one_of():
234
+ # One_of in One_of
235
+ new_specs.extend(One_Of.condense(spec.specs[0].specs)) # type: ignore
236
+ else:
237
+ new_specs.append(spec)
238
+ case One_Of():
239
+ # One_of in one_of
240
+ new_specs.extend(One_Of.condense(spec.specs))
241
+ case _:
242
+ raise TypeError(f"Not supported type {type(spec)} for {spec}")
243
+
244
+ return new_specs
245
+
246
+ def add_specs(self, input_specs: Sequence[Spec]) -> One_Of:
247
+ """Add specs to the One_Of.
248
+
249
+ Returns:
250
+ One_Of object.
251
+ """
252
+ for i in range(len(self.specs)):
253
+ self.specs[i].add_specs(input_specs)
254
+ self.specs = One_Of.condense(self.specs)
255
+ return self
256
+
257
+ @classmethod
258
+ def from_4C_metadata(cls, data_dict: dict) -> One_Of:
259
+ """Create One_Of from 4C metadata file.
260
+
261
+ Args:
262
+ data_dict: Data from 4C metadata file
263
+
264
+ Returns:
265
+ One_Of
266
+ """
267
+ data_dict.pop("type", None)
268
+ specs = [metadata_from_dict(spec) for spec in data_dict.pop("specs")]
269
+ return cls(specs=specs, **data_dict)
270
+
271
+ def __str__(self) -> str: # pragma: no cover
272
+ """String method."""
273
+ return "One_of(" + ", ".join([str(spec) for spec in self.specs]) + ")"
274
+
275
+ def __repr__(self) -> str: # pragma: no cover
276
+ """Representation method."""
277
+ return "One_of(" + ", ".join([str(spec) for spec in self.specs]) + ")"
278
+
279
+ def __len__(self) -> int:
280
+ """Len of the One_Of.
281
+
282
+ Returns:
283
+ number of One_Of branches
284
+ """
285
+ return len(self.specs)
286
+
287
+ def __iter__(self) -> Generator[All_Of]:
288
+ """Iterate One_of.
289
+
290
+ Yields:
291
+ One_Of branches
292
+ """
293
+ yield from self.specs
294
+
295
+
296
+ class Primitive(InputSpec):
297
+ PRIMITIVE_TYPES: list[str] = ["double", "bool", "int", "string", "path"]
298
+ PRIMITIVE_TYPES_TO_PYTHON: dict[str, type] = {
299
+ "double": float,
300
+ "bool": bool,
301
+ "int": int,
302
+ "string": str,
303
+ "path": str,
304
+ }
305
+
306
+ def __init__(
307
+ self,
308
+ spec_type: Literal["double", "int", "bool", "string", "path"],
309
+ name: NotSetAlias[
310
+ str
311
+ ] = NotSetString, # Name is only optional with vectors, maps, tuple
312
+ description: NotSetAlias[str] = NotSetString,
313
+ required: bool = True,
314
+ noneable: bool = False,
315
+ validator: ValidatorAlias = None,
316
+ default: NotSetAlias[PRIMITIVES_PYTHON_TYPES] = NotSet("default"),
317
+ ) -> None:
318
+ """Initialise primitive.
319
+
320
+ Args:
321
+ spec_type: Type of primitive
322
+ name: Name
323
+ description: Description
324
+ required: True if parameter is required
325
+ noneable: True if parameter can be None
326
+ validator: Validator callable
327
+ default: Default value of the spec
328
+ """
329
+ if spec_type not in Primitive.PRIMITIVE_TYPES:
330
+ raise TypeError(
331
+ f"Spec type {spec_type} is not supported. Supported ones are: {Primitive.PRIMITIVE_TYPES}"
332
+ )
333
+ super().__init__(spec_type, name, description, required, noneable, validator)
334
+ if check_if_set(default) and default is not None and False:
335
+ if not isinstance(default, Primitive.PRIMITIVE_TYPES_TO_PYTHON[spec_type]):
336
+ raise TypeError(
337
+ f"Default {default} for the parameter of type '{spec_type}' is not Python type {Primitive.PRIMITIVE_TYPES_TO_PYTHON[spec_type]}"
338
+ )
339
+ self.default = default
340
+
341
+ @classmethod
342
+ def from_4C_metadata(cls, data_dict: dict) -> Primitive:
343
+ """Create primitive from 4C metadata file.
344
+
345
+ Args:
346
+ data_dict: Data from 4C metadata file
347
+
348
+ Returns:
349
+ primitive
350
+ """
351
+ spec_type = data_dict.pop("type")
352
+ if "validator" in data_dict:
353
+ data_dict["validator"] = validator_from_dict(data_dict["validator"])
354
+ return cls(spec_type=spec_type, **data_dict)
355
+
356
+ def __str__(self) -> str: # pragma: no cover
357
+ """String method."""
358
+ return f"{self.name}"
359
+
360
+ def __repr__(self) -> str: # pragma: no cover
361
+ """Representation method."""
362
+ return f"{self.name}"
363
+
364
+
365
+ class Enum(InputSpec):
366
+ def __init__(
367
+ self,
368
+ choices: Sequence[str],
369
+ name: NotSetAlias[str] = NotSetString,
370
+ description: NotSetAlias[str] = NotSetString,
371
+ required: bool = True,
372
+ noneable: bool = False,
373
+ validator: ValidatorAlias = None,
374
+ default: NotSetAlias[str] = NotSet("default"),
375
+ ) -> None:
376
+ """Initialise enum.
377
+
378
+ Args:
379
+ choices: Enum choices
380
+ name: Name
381
+ description: Description
382
+ required: True if parameter is required
383
+ noneable: True if parameter can be None
384
+ validator: Validator callable
385
+ default: Default value
386
+ """
387
+ super().__init__("enum", name, description, required, noneable, validator)
388
+ if check_if_set(default):
389
+ if default not in choices:
390
+ raise ValueError(
391
+ f"Default choice {default} is not in the valid enum choices {choices}"
392
+ )
393
+ self.choices = choices
394
+ self.default = default
395
+
396
+ @classmethod
397
+ def from_4C_metadata(cls, data_dict: dict) -> Enum:
398
+ """Create enum from 4C metadata file.
399
+
400
+ Args:
401
+ data_dict: Data from 4C metadata file
402
+
403
+ Returns:
404
+ enum
405
+ """
406
+ data_dict.pop("type", None)
407
+ choices = [c["name"] for c in data_dict.pop("choices")]
408
+ # TODO add description from choices
409
+ if "validator" in data_dict:
410
+ data_dict["validator"] = validator_from_dict(data_dict["validator"])
411
+ return cls(choices=choices, **data_dict)
412
+
413
+ def __str__(self) -> str: # pragma: no cover
414
+ """String method."""
415
+ return f"{self.name}"
416
+
417
+ def __repr__(self) -> str: # pragma: no cover
418
+ """Representation method."""
419
+ return f"{self.name}"
420
+
421
+
422
+ class Vector(InputSpec):
423
+ def __init__(
424
+ self,
425
+ value_type: NATIVE_CPP_ALIAS,
426
+ size: int | None = None,
427
+ name: NotSetAlias[str] = NotSetString,
428
+ description: NotSetAlias[str] = NotSetString,
429
+ required: bool = True,
430
+ noneable: bool = False,
431
+ validator: ValidatorAlias = None,
432
+ default: NotSetAlias[Sequence[NATIVE_CPP_ALIAS]] = NotSet("default"),
433
+ ) -> None:
434
+ """Initialise vector.
435
+
436
+ Args:
437
+ value_type: Type of vector elements
438
+ size: Vector dimension
439
+ name: Name
440
+ description: Description
441
+ required: True if parameter is required
442
+ noneable: True if parameter can be None
443
+ validator: Validator callable
444
+ default: Default value
445
+ """
446
+ super().__init__("vector", name, description, required, noneable, validator)
447
+ if not isinstance(value_type, NATIVE_CPP_TYPES):
448
+ raise TypeError(
449
+ f"Value type {value_type} has to be of type: {NATIVE_CPP_TYPES}"
450
+ )
451
+ self.value_type = value_type
452
+ self.size = size
453
+ self.default = default
454
+
455
+ @classmethod
456
+ def from_4C_metadata(cls, data_dict: dict) -> Vector:
457
+ """Create vector from 4C metadata file.
458
+
459
+ Args:
460
+ data_dict: Data from 4C metadata file
461
+
462
+ Returns:
463
+ vector
464
+ """
465
+ data_dict.pop("type", None)
466
+ value_type: NATIVE_CPP_ALIAS = metadata_from_dict(data_dict.pop("value_type")) # type: ignore
467
+ if "validator" in data_dict:
468
+ data_dict["validator"] = validator_from_dict(data_dict["validator"])
469
+ return cls(value_type=value_type, **data_dict)
470
+
471
+ def __str__(self) -> str: # pragma: no cover
472
+ """String method."""
473
+ return f"{self.name}"
474
+
475
+ def __repr__(self) -> str: # pragma: no cover
476
+ """Representation method."""
477
+ return f"{self.name}"
478
+
479
+ def __iter__(self) -> Generator[NATIVE_CPP_ALIAS]:
480
+ """Iterate vector.
481
+
482
+ Yields:
483
+ value type of the vector
484
+ """
485
+ yield self.value_type
486
+
487
+
488
+ class Map(InputSpec):
489
+ def __init__(
490
+ self,
491
+ value_type: NATIVE_CPP_ALIAS,
492
+ size: int | None = None,
493
+ name: NotSetAlias[str] = NotSetString,
494
+ description: NotSetAlias[str] = NotSetString,
495
+ required: bool = True,
496
+ noneable: bool = False,
497
+ validator: ValidatorAlias = None,
498
+ default: NotSetAlias[dict[str, NATIVE_CPP_ALIAS]] = NotSet("default"),
499
+ ) -> None:
500
+ """Initialise map.
501
+
502
+ Args:
503
+ value_type: Type of map elements
504
+ size: Number of entries in the map
505
+ name: Name
506
+ description: Description
507
+ required: True if parameter is required
508
+ noneable: True if parameter can be None
509
+ validator: Validator callable
510
+ default: Default value
511
+ """
512
+ if not isinstance(value_type, NATIVE_CPP_TYPES):
513
+ raise TypeError(
514
+ f"Value type {value_type} has to be of type: {NATIVE_CPP_TYPES}"
515
+ )
516
+ super().__init__("map", name, description, required, noneable, validator)
517
+ self.value_type: NATIVE_CPP_ALIAS = value_type
518
+ self.size = size
519
+ self.default = default
520
+
521
+ @classmethod
522
+ def from_4C_metadata(cls, data_dict: dict) -> Map:
523
+ """Create map from 4C metadata file.
524
+
525
+ Args:
526
+ data_dict: Data from 4C metadata file
527
+
528
+ Returns:
529
+ map
530
+ """
531
+ data_dict.pop("type", None)
532
+ value_type: NATIVE_CPP_ALIAS = metadata_from_dict(data_dict.pop("value_type")) # type: ignore
533
+ if "validator" in data_dict:
534
+ data_dict["validator"] = validator_from_dict(data_dict["validator"])
535
+ return cls(value_type=value_type, **data_dict)
536
+
537
+ def __str__(self) -> str: # pragma: no cover
538
+ """String method."""
539
+ return f"{self.name}"
540
+
541
+ def __repr__(self) -> str: # pragma: no cover
542
+ """Representation method."""
543
+ return f"{self.name}"
544
+
545
+ def __iter__(self) -> Generator[NATIVE_CPP_ALIAS]:
546
+ """Iterate map.
547
+
548
+ Yields:
549
+ value type of the map
550
+ """
551
+ yield self.value_type
552
+
553
+
554
+ class Tuple(InputSpec):
555
+ def __init__(
556
+ self,
557
+ value_types: Sequence[NATIVE_CPP_ALIAS],
558
+ size: int,
559
+ name: NotSetAlias[str] = NotSetString,
560
+ description: NotSetAlias[str] = NotSetString,
561
+ required: bool = True,
562
+ noneable: bool = False,
563
+ validator: ValidatorAlias = None,
564
+ default: NotSetAlias[Sequence[NATIVE_CPP_ALIAS]] = NotSet("default"),
565
+ ) -> None:
566
+ """Initialise tuple.
567
+
568
+ Args:
569
+ value_types: Types of the tuple element
570
+ size: Number of tuple entries
571
+ name: Name
572
+ description: Description
573
+ required: True if parameter is required
574
+ noneable: True if parameter can be None
575
+ validator: Validator callable
576
+ default: Default value
577
+ """
578
+ super().__init__("tuple", name, description, required, noneable, validator)
579
+ for i, value_type in enumerate(value_types):
580
+ if not isinstance(value_type, NATIVE_CPP_TYPES):
581
+ raise TypeError(
582
+ f"Value type {value_type} (parameter number {i + 1} in {value_types}) has to be of type: {NATIVE_CPP_TYPES}"
583
+ )
584
+ self.value_types = value_types
585
+ self.size = size
586
+ if self.size != len(self.value_types):
587
+ raise ValueError(
588
+ f"Tuple size {self.size} does not match the number of value types "
589
+ f"{len(self.value_types)}"
590
+ )
591
+ self.default = default
592
+
593
+ @classmethod
594
+ def from_4C_metadata(cls, data_dict: dict) -> Tuple:
595
+ """Create tuple from 4C metadata file.
596
+
597
+ Args:
598
+ data_dict: Data from 4C metadata file
599
+
600
+ Returns:
601
+ tuple
602
+ """
603
+ data_dict.pop("type", None)
604
+ value_types = [
605
+ metadata_from_dict(value_type)
606
+ for value_type in data_dict.pop("value_types")
607
+ ]
608
+ if "validator" in data_dict:
609
+ data_dict["validator"] = validator_from_dict(data_dict["validator"])
610
+ return cls(value_types=value_types, **data_dict) # type: ignore
611
+
612
+ def __str__(self) -> str: # pragma: no cover
613
+ """String method."""
614
+ return f"{self.name}"
615
+
616
+ def __repr__(self) -> str: # pragma: no cover
617
+ """Representation method."""
618
+ return f"{self.name}"
619
+
620
+ def __iter__(self) -> Generator[NATIVE_CPP_ALIAS]:
621
+ """Iterate tuple.
622
+
623
+ Yields:
624
+ value types of the tuple
625
+ """
626
+ yield from self.value_types
627
+
628
+
629
+ class Selection(InputSpec):
630
+ def __init__(
631
+ self,
632
+ name: NotSetAlias[str],
633
+ choices: dict[str, Spec],
634
+ description: NotSetAlias[str] = NotSetString,
635
+ required: bool = True,
636
+ noneable: bool = False,
637
+ defaultable: bool = False,
638
+ validator: ValidatorAlias = None,
639
+ ) -> None:
640
+ """Initialise selection.
641
+
642
+ Args:
643
+ name: Name
644
+ choices: Choices of the selection
645
+ description: Description
646
+ required: True if parameter is required
647
+ noneable: True if parameter can be None
648
+ defaultable: Can have a default
649
+ validator: Validator callable
650
+ """
651
+ super().__init__("selection", name, description, required, noneable, validator)
652
+ self.choices: dict[str, All_Of] = {k: All_Of([v]) for k, v in choices.items()}
653
+ self.defautable = defaultable
654
+
655
+ @classmethod
656
+ def from_4C_metadata(cls, data_dict: dict) -> Selection:
657
+ """Create selection from 4C metadata file.
658
+
659
+ Args:
660
+ data_dict: Data from 4C metadata file
661
+
662
+ Returns:
663
+ selection
664
+ """
665
+ data_dict.pop("type", None)
666
+
667
+ choices = {}
668
+ for choice in data_dict.pop("choices"):
669
+ spec = choice.pop("spec")
670
+ choices[choice.pop("name")] = metadata_from_dict(spec)
671
+ if "validator" in data_dict:
672
+ data_dict["validator"] = validator_from_dict(data_dict["validator"])
673
+ return cls(choices=choices, **data_dict)
674
+
675
+ def __iter__(self) -> Generator[Spec]:
676
+ """Iterate selection.
677
+
678
+ Yields:
679
+ choices of the selection
680
+ """
681
+ yield from self.choices.values()
682
+
683
+ def __len__(self) -> int:
684
+ """Len of the selection.
685
+
686
+ Returns:
687
+ number of choices
688
+ """
689
+ return len(self.choices)
690
+
691
+
692
+ class Group(InputSpec):
693
+ def __init__(
694
+ self,
695
+ name: NotSetAlias[str],
696
+ spec: Spec,
697
+ description: NotSetAlias[str] = NotSetString,
698
+ required: bool = True,
699
+ noneable: bool = False,
700
+ defaultable: bool = False,
701
+ validator: ValidatorAlias = None,
702
+ ) -> None:
703
+ """Initialise group.
704
+
705
+ Args:
706
+ name: Name
707
+ spec: Spec of the group
708
+ description: Description
709
+ required: True if parameter is required
710
+ noneable: True if parameter can be None
711
+ defaultable: Can have a default
712
+ validator: Validator callable
713
+ """
714
+ super().__init__("group", name, description, required, noneable, validator)
715
+ self.spec: All_Of = All_Of([spec])
716
+ self.defautable = defaultable
717
+
718
+ @classmethod
719
+ def from_4C_metadata(cls, data_dict: dict) -> Group:
720
+ """Create group from 4C metadata file.
721
+
722
+ Args:
723
+ data_dict: Data from 4C metadata file
724
+
725
+ Returns:
726
+ group
727
+ """
728
+ data_dict.pop("type", None)
729
+ specs = [metadata_from_dict(spec) for spec in data_dict.pop("specs", [])]
730
+ if "validator" in data_dict:
731
+ data_dict["validator"] = validator_from_dict(data_dict["validator"])
732
+ return cls(spec=All_Of(specs), **data_dict)
733
+
734
+ def __iter__(self) -> Generator[All_Of]:
735
+ """Iterate group.
736
+
737
+ Yields:
738
+ group spec
739
+ """
740
+ yield self.spec
741
+
742
+ def __str__(self) -> str: # pragma: no cover
743
+ """String method."""
744
+ return f"{self.name} Group({self.spec})"
745
+
746
+ def __repr__(self) -> str: # pragma: no cover
747
+ """Representation method."""
748
+ return f"{self.name} Group({self.spec})"
749
+
750
+
751
+ class List(InputSpec):
752
+ def __init__(
753
+ self,
754
+ name: NotSetAlias[str],
755
+ spec: Spec,
756
+ size: int | None = None,
757
+ description: NotSetAlias[str] = NotSetString,
758
+ required: bool = True,
759
+ noneable: bool = False,
760
+ defaultable: bool = False,
761
+ validator: ValidatorAlias = None,
762
+ ) -> None:
763
+ """Initialise list.
764
+
765
+ Args:
766
+ name: Name
767
+ spec: Spec of the list entries
768
+ size: Number of list entries
769
+ description: Description
770
+ required: True if parameter is required
771
+ noneable: True if parameter can be None
772
+ defaultable: Can have a default
773
+ validator: Validator callable
774
+ """
775
+ super().__init__("list", name, description, required, noneable, validator)
776
+ self.spec: All_Of = All_Of([spec])
777
+ self.size = size
778
+ self.defautable = defaultable
779
+
780
+ @classmethod
781
+ def from_4C_metadata(cls, data_dict: dict) -> List:
782
+ """Create list from 4C metadata file.
783
+
784
+ Args:
785
+ data_dict: Data from 4C metadata file
786
+
787
+ Returns:
788
+ list
789
+ """
790
+ data_dict.pop("type", None)
791
+ spec = metadata_from_dict(data_dict.pop("spec"))
792
+ if "validator" in data_dict:
793
+ data_dict["validator"] = validator_from_dict(data_dict["validator"])
794
+ return cls(spec=All_Of([spec]), **data_dict)
795
+
796
+ def __iter__(self) -> Generator[All_Of]:
797
+ """Iterate list.
798
+
799
+ Yields:
800
+ spec
801
+ """
802
+ yield self.spec
803
+
804
+ def __str__(self) -> str: # pragma: no cover
805
+ """String method."""
806
+ return f"{self.name} List({self.spec})"
807
+
808
+ def __repr__(self) -> str: # pragma: no cover
809
+ """Representation method."""
810
+ return f"{self.name} List({self.spec})"
811
+
812
+
813
+ Spec: TypeAlias = InputSpec | All_Of | One_Of
814
+ NATIVE_CPP_ALIAS: TypeAlias = Primitive | Enum | Vector | Map | Tuple
815
+ NATIVE_CPP_TYPES = (Primitive, Enum, Vector, Map, Tuple)
816
+
817
+ _METADATA_TYPE_TO_CLASS: dict[str, type[Spec]] = {
818
+ i.__name__.lower(): i
819
+ for i in [Enum, Vector, Map, Tuple, Selection, Group, List, All_Of, One_Of]
820
+ } | {i: Primitive for i in Primitive.PRIMITIVE_TYPES}
821
+
822
+
823
+ def metadata_from_dict(data_dict: dict) -> Spec:
824
+ """Create metadata object from 4C metadata dict.
825
+
826
+ Args:
827
+ data_dict: Data from 4C metadata file
828
+
829
+ Returns:
830
+ metadata object
831
+ """
832
+ entry_type: str = data_dict.get("type") # type: ignore
833
+
834
+ metadata_class: type[Spec] | None = _METADATA_TYPE_TO_CLASS.get(entry_type, None)
835
+
836
+ if metadata_class is not None:
837
+ return metadata_class.from_4C_metadata(data_dict)
838
+
839
+ raise TypeError(
840
+ f"Unknown type {entry_type} for {data_dict}, known ones are {list(_METADATA_TYPE_TO_CLASS.keys())}"
841
+ )
842
+
843
+
844
+ class Validator(Protocol[G]):
845
+ """Validator protocol."""
846
+
847
+ def _validate(self, entry: G) -> bool:
848
+ """Validate object.
849
+
850
+ Args:
851
+ entry: Object to validate
852
+
853
+ Returns:
854
+ True if valid
855
+ """
856
+ pass
857
+
858
+ def __call__(self, entry: G) -> bool:
859
+ """Call method."""
860
+ return self._validate(entry)
861
+
862
+
863
+ class RangeValidator(Validator[T]):
864
+ def __init__(
865
+ self,
866
+ minimum: T,
867
+ maximum: T,
868
+ minimum_exclusive: bool = False,
869
+ maximum_exclusive: bool = False,
870
+ ) -> None:
871
+ """Range validator.
872
+
873
+ Args:
874
+ entry: Entry value
875
+ minimum: Minimum value
876
+ maximum: Maximum value
877
+ minimum_exclusive: Minimum is exclusive
878
+ maximum_exclusive: Maximum is exclusive
879
+ """
880
+ self.minimum: T = minimum
881
+ self.maximum: T = maximum
882
+ self.minimum_exclusive = minimum_exclusive
883
+ self.maximum_exclusive = maximum_exclusive
884
+
885
+ def _validate(self, entry: T) -> bool:
886
+ """Validate if float or in is in range.
887
+
888
+ Args:
889
+ entry: Entry value
890
+ minimum: Minimum value
891
+ maximum: Maximum value
892
+ minimum_exclusive: Minimum is exclusive
893
+ maximum_exclusive: Maximum is exclusive
894
+
895
+ Returns:
896
+ True if in range
897
+ """
898
+ if self.minimum_exclusive:
899
+ if entry <= self.minimum:
900
+ return False
901
+ else:
902
+ if entry < self.minimum:
903
+ return False
904
+
905
+ if self.maximum_exclusive:
906
+ if entry >= self.maximum:
907
+ return False
908
+ else:
909
+ if entry > self.maximum:
910
+ return False
911
+
912
+ return True
913
+
914
+ @classmethod
915
+ def from_4C_metadata_dict(cls, data_dict: dict) -> RangeValidator:
916
+ """Create validator from 4C metadata dict.
917
+
918
+ Args:
919
+ data_dict: Data from 4C metadata file
920
+
921
+ Returns:
922
+ range validator
923
+ """
924
+ return cls(**data_dict)
925
+
926
+
927
+ class AllEmementsValidator(Validator[Sequence]):
928
+ def __init__(self, element_validator: Callable[[Sequence], bool]) -> None:
929
+ """All elements validator.
930
+
931
+ Validates each entry of a sequence with the `element_validator`.
932
+
933
+ Args:
934
+ element_validator: Validator for each entry
935
+ """
936
+ self.element_validator = element_validator
937
+
938
+ def _validate(self, entry: Sequence) -> bool:
939
+ """Validate sequence.
940
+
941
+ Args:
942
+ entry: Sequence to validate
943
+
944
+ Returns:
945
+ True if all entries are valid
946
+ """
947
+ return all([self.element_validator(e) for e in entry])
948
+
949
+ @classmethod
950
+ def from_4C_metadata_dict(cls, data_dict: dict) -> AllEmementsValidator:
951
+ """Create validator from 4C metadata dict.
952
+
953
+ Args:
954
+ data_dict: Data from 4C metadata file
955
+
956
+ Returns:
957
+ all elements validator
958
+ """
959
+ element_validator = validator_from_dict(data_dict)
960
+ return cls(element_validator)
961
+
962
+
963
+ class PatternValidator(Validator):
964
+ def __init__(self, pattern: str):
965
+ """Regex pattern validator.
966
+
967
+ Args:
968
+ pattern: Pattern to match
969
+ """
970
+ self.pattern = re.compile(pattern)
971
+
972
+ def _validate(self, entry: str) -> bool:
973
+ """Validate pattern.
974
+
975
+ Args:
976
+ entry: Entry to validate
977
+
978
+ Returns:
979
+ True if pattern matches
980
+ """
981
+ return bool(self.pattern.match(entry))
982
+
983
+ @classmethod
984
+ def from_4C_metadata_dict(cls, data_dict: dict) -> PatternValidator:
985
+ """Create validator from 4C metadata dict.
986
+
987
+ Args:
988
+ data_dict: Data from 4C metadata file
989
+
990
+ Returns:
991
+ validator
992
+ """
993
+ return cls(**data_dict)
994
+
995
+
996
+ def validator_from_dict(data_dict: dict) -> Validator:
997
+ """Create validator from dict.
998
+
999
+ Args:
1000
+ data_dict: Data from 4C metadata file
1001
+
1002
+ Returns:
1003
+ validator
1004
+ """
1005
+ if len(data_dict) == 0:
1006
+ raise ValueError(f"Can not construct value error from {data_dict}.")
1007
+ validator_name = list(data_dict.keys())[0]
1008
+ validator_data = data_dict[validator_name]
1009
+ match validator_name:
1010
+ case "range":
1011
+ return RangeValidator.from_4C_metadata_dict(validator_data)
1012
+ case "all_elements":
1013
+ return AllEmementsValidator.from_4C_metadata_dict(validator_data)
1014
+ case "pattern":
1015
+ return PatternValidator.from_4C_metadata_dict(validator_data)
1016
+ case _:
1017
+ raise KeyError(f"Unknown validator {data_dict}")
fourcipp/utils/not_set.py CHANGED
@@ -21,18 +21,31 @@
21
21
  # THE SOFTWARE.
22
22
  """Not set utils."""
23
23
 
24
- from typing import Any
25
24
 
26
-
27
- class _NotSet:
25
+ class NotSet:
28
26
  """Not set object."""
29
27
 
28
+ def __init__(self, expected: object = object) -> None:
29
+ """Not set object.
30
+
31
+ Args:
32
+ expected: Expected object to to display
33
+ """
34
+ self.expected = expected
35
+
36
+ def __str__(self) -> str: # pragma: no cover
37
+ """String method."""
38
+ return f"NotSet({self.expected})"
39
+
40
+ def __repr__(self) -> str: # pragma: no cover
41
+ """Representation method."""
42
+ return f"NotSet({self.expected})"
43
+
30
44
 
31
- # Not set object
32
- NotSet = _NotSet()
45
+ NOT_SET = NotSet()
33
46
 
34
47
 
35
- def check_if_set(obj: Any) -> bool:
48
+ def check_if_set(obj: object) -> bool:
36
49
  """Check if object or is NotSet.
37
50
 
38
51
  Args:
@@ -42,10 +55,10 @@ def check_if_set(obj: Any) -> bool:
42
55
  True if object is set
43
56
  """
44
57
  # Check if object is not of type _NotSet, i.e. it has a value
45
- return not isinstance(obj, _NotSet)
58
+ return not isinstance(obj, NotSet)
46
59
 
47
60
 
48
- def pop_arguments(key: str, default: Any = NotSet) -> tuple:
61
+ def pop_arguments(key: str, default: object = NOT_SET) -> tuple:
49
62
  """Create arguments for the pop method.
50
63
 
51
64
  We need this utility since pop is not implemented using kwargs, instead the default is checked
@@ -25,6 +25,8 @@ import pathlib
25
25
  from collections.abc import Callable
26
26
  from typing import TypeAlias, TypeVar
27
27
 
28
+ from fourcipp.utils.not_set import NotSet
29
+
28
30
  # Generic type variable
29
31
  T = TypeVar("T")
30
32
 
@@ -37,3 +39,6 @@ Extractor: TypeAlias = Callable[[str], T]
37
39
  LineListExtractor: TypeAlias = Callable[[list[str]], T]
38
40
  LineCastingDict: TypeAlias = dict[str, LineListExtractor]
39
41
  NestedCastingDict: TypeAlias = dict[str, LineCastingDict | LineListExtractor]
42
+
43
+ # NotSet
44
+ NotSetAlias: TypeAlias = NotSet | T
fourcipp/utils/yaml_io.py CHANGED
@@ -28,7 +28,7 @@ from typing import Callable
28
28
  import regex
29
29
  import ryml
30
30
 
31
- from fourcipp.utils.typing import Path
31
+ from fourcipp.utils.type_hinting import Path
32
32
 
33
33
 
34
34
  def load_yaml(path_to_yaml_file: Path) -> dict:
fourcipp/version.py CHANGED
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
28
28
  commit_id: COMMIT_ID
29
29
  __commit_id__: COMMIT_ID
30
30
 
31
- __version__ = version = '1.14.0'
32
- __version_tuple__ = version_tuple = (1, 14, 0)
31
+ __version__ = version = '1.15.0'
32
+ __version_tuple__ = version_tuple = (1, 15, 0)
33
33
 
34
34
  __commit_id__ = commit_id = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: FourCIPP
3
- Version: 1.14.0
3
+ Version: 1.15.0
4
4
  Summary: A streamlined Python Parser for 4C input files
5
5
  Author: FourCIPP Authors
6
6
  License: The MIT License (MIT)
@@ -0,0 +1,28 @@
1
+ fourcipp/__init__.py,sha256=4pz7DVXErSbUcLqPTaHnQfdJzKkpfZDivBqbHbTgpRE,1388
2
+ fourcipp/fourc_input.py,sha256=1-EMbwc5tWbWtbZqzRF4_ytrvkcQVgtC5ZX1uz6NFuQ,23954
3
+ fourcipp/version.py,sha256=gvymR90UfRuuIQ_1PRcQFHGu4ixvgau9sZalU_-52us,706
4
+ fourcipp/config/4C_metadata.yaml,sha256=j3DmYTTuKewugGAG6joSzdcuEpefF4B32Ipkk_9TigY,11887345
5
+ fourcipp/config/4C_schema.json,sha256=Ndrzh5G5tdpIpbq4ExSyh4clBQwELEaQt5Ze77ElKsk,16417772
6
+ fourcipp/config/config.yaml,sha256=n2c2a6E4HKfAdNWOQz1kLUuf5p4NLxIddaAi2t5eM38,460
7
+ fourcipp/legacy_io/__init__.py,sha256=L3MWW-WjPbPAJVX8Z0Uheftn0dRPnqNnSBic3uloFhI,5750
8
+ fourcipp/legacy_io/element.py,sha256=rP8F-m-8ZCwCxtV_OASvvLeNYr01zsmgZsDZSJ_G1gY,3977
9
+ fourcipp/legacy_io/inline_dat.py,sha256=t8eMmJ_mAK7kKYAhNNlsES9JbZ760DHR0101Mj9vkSQ,6723
10
+ fourcipp/legacy_io/node.py,sha256=e7m0W7dai_b1XgaqD37k3QS44ySCas3HetmyTLS9_78,3522
11
+ fourcipp/legacy_io/node_topology.py,sha256=hqGGzhyNhFX-BMW8SzztfzM8zoZLLltVScMv-p4hDH0,5394
12
+ fourcipp/legacy_io/particle.py,sha256=8LoRsyKVfhl5Qf_EoO8vLmbH0QSpB_Nho464ifkHAZc,2172
13
+ fourcipp/utils/__init__.py,sha256=ccdlf4taJ0mKLg_ru8ilXEa72PoO9N2UIxHNHDEtQmY,1151
14
+ fourcipp/utils/cli.py,sha256=Tn9jx0KhC421zv-DMpqNU2hpb6fyi4-r4qV17f-ts4Y,5807
15
+ fourcipp/utils/configuration.py,sha256=_9Yo_2Rxw1QDhib9OV_MjLXBhVPfIBA2qmdOG3EuIKU,6467
16
+ fourcipp/utils/converter.py,sha256=D40YQ96WqPEEpB7fwAB5XC2v-jRki4v1sIJ-ngO08nU,5194
17
+ fourcipp/utils/dict_utils.py,sha256=uC0uaBNP3Wh2v3kFy9JHnAYARMukAN4cl40pmiBT13Y,12891
18
+ fourcipp/utils/metadata.py,sha256=wYu07eCrOTNHSnhDxHyQzF6OU8D_2ZuJfytiIpn3sxY,30895
19
+ fourcipp/utils/not_set.py,sha256=NHf0UXDmTuZfvfnIIgkkx4EohxRsN4MVUHUpt7VOnaQ,2433
20
+ fourcipp/utils/type_hinting.py,sha256=izPEhbMdmhrIBamCLqqF_6iDZW-w7a8kplUugbQILyw,1714
21
+ fourcipp/utils/validation.py,sha256=FejHOj1MddaU7gEpMN-f8Mz3rYjflakd1qcsKnctHqA,5292
22
+ fourcipp/utils/yaml_io.py,sha256=jPgVnxE858XTpDC6BVhfbbljQegL58zc3u2VPYCTvGE,5771
23
+ fourcipp-1.15.0.dist-info/licenses/LICENSE,sha256=lkSOHdH9IZ8c3Vnz0fFjqls1cRlmLADBP8QEIwUlH3o,1082
24
+ fourcipp-1.15.0.dist-info/METADATA,sha256=sG1SQJhzC-K7904TyarihRHwJvsdstz3DoD8m1EnWZ0,7916
25
+ fourcipp-1.15.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
+ fourcipp-1.15.0.dist-info/entry_points.txt,sha256=44XBG4bwhuq1EwOZ0U055HYP8_qN6_d30ecVsa5Igng,53
27
+ fourcipp-1.15.0.dist-info/top_level.txt,sha256=oZ6jgFFmvi157VwGUEFuKT3D8oS5mOkpOVx8zZURZrQ,9
28
+ fourcipp-1.15.0.dist-info/RECORD,,
@@ -1,28 +0,0 @@
1
- fourcipp/__init__.py,sha256=4pz7DVXErSbUcLqPTaHnQfdJzKkpfZDivBqbHbTgpRE,1388
2
- fourcipp/fourc_input.py,sha256=ocyxXdu8NFIRM94dc4EG_r8XsBkJajvw1YWHmZh-G6Y,23946
3
- fourcipp/version.py,sha256=B_zXbaY_VjR5QzFDQUWID71ivmfxjMpJLAttgWbEkMU,706
4
- fourcipp/config/4C_metadata.yaml,sha256=j3DmYTTuKewugGAG6joSzdcuEpefF4B32Ipkk_9TigY,11887345
5
- fourcipp/config/4C_schema.json,sha256=Ndrzh5G5tdpIpbq4ExSyh4clBQwELEaQt5Ze77ElKsk,16417772
6
- fourcipp/config/config.yaml,sha256=n2c2a6E4HKfAdNWOQz1kLUuf5p4NLxIddaAi2t5eM38,460
7
- fourcipp/legacy_io/__init__.py,sha256=y6aTjgUe61OQSl1NMiZ-fQAGTab_xNT1eJTnaTnsIkc,5744
8
- fourcipp/legacy_io/element.py,sha256=b8--f3IR9nB68R25mk4DHHOBdDLqASewtAdPZAkA2t4,3971
9
- fourcipp/legacy_io/inline_dat.py,sha256=n9qWrIX33Atv0JruuLWAxy6lrCaeuCZRIvtl3Jr1a1U,6659
10
- fourcipp/legacy_io/node.py,sha256=e7m0W7dai_b1XgaqD37k3QS44ySCas3HetmyTLS9_78,3522
11
- fourcipp/legacy_io/node_topology.py,sha256=hqGGzhyNhFX-BMW8SzztfzM8zoZLLltVScMv-p4hDH0,5394
12
- fourcipp/legacy_io/particle.py,sha256=0rxwdiMnHI1QUGZPqWgsxqyslrxB7aq7qxgNMb_y_rk,2166
13
- fourcipp/utils/__init__.py,sha256=ccdlf4taJ0mKLg_ru8ilXEa72PoO9N2UIxHNHDEtQmY,1151
14
- fourcipp/utils/cli.py,sha256=I0N6mcJQGX7seLtXpfrPJA5EWrmhgOph_gHrrxEs6JE,5801
15
- fourcipp/utils/configuration.py,sha256=HDrvHrH4K5mdienzVsAt_sh9j2Pv81bxWBqqbeNb1KE,6461
16
- fourcipp/utils/converter.py,sha256=D40YQ96WqPEEpB7fwAB5XC2v-jRki4v1sIJ-ngO08nU,5194
17
- fourcipp/utils/dict_utils.py,sha256=uC0uaBNP3Wh2v3kFy9JHnAYARMukAN4cl40pmiBT13Y,12891
18
- fourcipp/utils/metadata.py,sha256=98jz9Gm8qdvZ-b1jwYObNJTaiMQWwbknvS70Nv6Gwhk,1291
19
- fourcipp/utils/not_set.py,sha256=04C_3axe2cupBYgfpgDAcGs1zHVzG3I58UGO58TH05A,2017
20
- fourcipp/utils/typing.py,sha256=8iX9PuKe8B1WJ3vEjiM5ZfefvgYnaZDiSdB7Nx9SrVw,1625
21
- fourcipp/utils/validation.py,sha256=FejHOj1MddaU7gEpMN-f8Mz3rYjflakd1qcsKnctHqA,5292
22
- fourcipp/utils/yaml_io.py,sha256=GZtgBn-5OB7xAJmgjo66eG3JwkHnfQFp4VIA2-rVVSg,5765
23
- fourcipp-1.14.0.dist-info/licenses/LICENSE,sha256=lkSOHdH9IZ8c3Vnz0fFjqls1cRlmLADBP8QEIwUlH3o,1082
24
- fourcipp-1.14.0.dist-info/METADATA,sha256=ABNia81ZL2ubbhDiRoNsm7_Aj_qTgFFDfDlso_XNxLU,7916
25
- fourcipp-1.14.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
26
- fourcipp-1.14.0.dist-info/entry_points.txt,sha256=44XBG4bwhuq1EwOZ0U055HYP8_qN6_d30ecVsa5Igng,53
27
- fourcipp-1.14.0.dist-info/top_level.txt,sha256=oZ6jgFFmvi157VwGUEFuKT3D8oS5mOkpOVx8zZURZrQ,9
28
- fourcipp-1.14.0.dist-info/RECORD,,