GraphAtoms 0.0.3__tar.gz → 1.0.0__tar.gz

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.
Files changed (61) hide show
  1. graphatoms-1.0.0/GraphAtoms/common/__init__.py +16 -0
  2. graphatoms-1.0.0/GraphAtoms/common/_abc.py +52 -0
  3. graphatoms-1.0.0/GraphAtoms/common/base.py +482 -0
  4. graphatoms-1.0.0/GraphAtoms/containner/__init__.py +21 -0
  5. graphatoms-1.0.0/GraphAtoms/containner/_aMixin.py +169 -0
  6. graphatoms-1.0.0/GraphAtoms/containner/_aOther.py +233 -0
  7. graphatoms-1.0.0/GraphAtoms/containner/_atomic.py +62 -0
  8. graphatoms-0.0.3/GraphAtoms/containner/_mDataPyG.py → graphatoms-1.0.0/GraphAtoms/containner/_g2DataPyG.py +8 -6
  9. graphatoms-0.0.3/GraphAtoms/containner/_mIGraph.py → graphatoms-1.0.0/GraphAtoms/containner/_g2IGraph.py +4 -4
  10. graphatoms-0.0.3/GraphAtoms/containner/_mNetworkX.py → graphatoms-1.0.0/GraphAtoms/containner/_g2NetworkX.py +1 -1
  11. graphatoms-0.0.3/GraphAtoms/containner/_mRustworkX.py → graphatoms-1.0.0/GraphAtoms/containner/_g2RustworkX.py +1 -1
  12. graphatoms-1.0.0/GraphAtoms/containner/_gBonded.py +219 -0
  13. {graphatoms-0.0.3 → graphatoms-1.0.0}/GraphAtoms/containner/_graph.py +181 -305
  14. {graphatoms-0.0.3 → graphatoms-1.0.0}/GraphAtoms/containner/_sysCluster.py +14 -17
  15. graphatoms-1.0.0/GraphAtoms/containner/_sysGas.py +223 -0
  16. graphatoms-1.0.0/GraphAtoms/containner/_system.py +16 -0
  17. graphatoms-1.0.0/GraphAtoms/reaction/__init__.py +9 -0
  18. graphatoms-1.0.0/GraphAtoms/reaction/_dtSQL.py +279 -0
  19. graphatoms-1.0.0/GraphAtoms/reaction/_event.py +310 -0
  20. graphatoms-1.0.0/GraphAtoms/utils/__init__.py +5 -0
  21. graphatoms-1.0.0/GraphAtoms/utils/_pyarrow.py +90 -0
  22. graphatoms-1.0.0/GraphAtoms/utils/bytes.py +118 -0
  23. {graphatoms-0.0.3/GraphAtoms/common → graphatoms-1.0.0/GraphAtoms/utils}/geometry.py +1 -1
  24. graphatoms-1.0.0/GraphAtoms/utils/ndarray.py +60 -0
  25. graphatoms-0.0.3/GraphAtoms/containner/_mRDKit.py → graphatoms-1.0.0/GraphAtoms/utils/rdtool.py +8 -12
  26. graphatoms-1.0.0/GraphAtoms/utils/string.py +71 -0
  27. {graphatoms-0.0.3 → graphatoms-1.0.0}/GraphAtoms.egg-info/PKG-INFO +4 -5
  28. graphatoms-1.0.0/GraphAtoms.egg-info/SOURCES.txt +42 -0
  29. {graphatoms-0.0.3 → graphatoms-1.0.0}/GraphAtoms.egg-info/requires.txt +3 -10
  30. {graphatoms-0.0.3 → graphatoms-1.0.0}/PKG-INFO +4 -5
  31. {graphatoms-0.0.3 → graphatoms-1.0.0}/pyproject.toml +23 -21
  32. {graphatoms-0.0.3 → graphatoms-1.0.0}/tests/test_abc.py +4 -4
  33. graphatoms-1.0.0/tests/test_container.py +345 -0
  34. graphatoms-1.0.0/tests/test_reaction.py +55 -0
  35. graphatoms-0.0.3/tests/test_mRDKit.py → graphatoms-1.0.0/tests/test_uRDtool.py +1 -1
  36. graphatoms-1.0.0/tests/test_utils.py +116 -0
  37. graphatoms-0.0.3/GraphAtoms/common/__init__.py +0 -4
  38. graphatoms-0.0.3/GraphAtoms/common/abc.py +0 -392
  39. graphatoms-0.0.3/GraphAtoms/common/ndarray.py +0 -3
  40. graphatoms-0.0.3/GraphAtoms/common/ndarray.pyi +0 -5
  41. graphatoms-0.0.3/GraphAtoms/common/string.py +0 -138
  42. graphatoms-0.0.3/GraphAtoms/containner/__init__.py +0 -20
  43. graphatoms-0.0.3/GraphAtoms/containner/_atomic.py +0 -366
  44. graphatoms-0.0.3/GraphAtoms/containner/_bonded.py +0 -90
  45. graphatoms-0.0.3/GraphAtoms/containner/_mConnComp.py +0 -45
  46. graphatoms-0.0.3/GraphAtoms/containner/_mFreeE.py +0 -117
  47. graphatoms-0.0.3/GraphAtoms/containner/_mNetworKit.py +0 -12
  48. graphatoms-0.0.3/GraphAtoms/containner/_sysGas.py +0 -81
  49. graphatoms-0.0.3/GraphAtoms/containner/_system.py +0 -15
  50. graphatoms-0.0.3/GraphAtoms.egg-info/SOURCES.txt +0 -37
  51. graphatoms-0.0.3/tests/test_container.py +0 -270
  52. graphatoms-0.0.3/tests/test_rotation.py +0 -44
  53. graphatoms-0.0.3/tests/test_utils.py +0 -49
  54. {graphatoms-0.0.3 → graphatoms-1.0.0}/GraphAtoms/__init__.py +0 -0
  55. {graphatoms-0.0.3 → graphatoms-1.0.0}/GraphAtoms/common/error.py +0 -0
  56. {graphatoms-0.0.3/GraphAtoms/common → graphatoms-1.0.0/GraphAtoms/utils}/rotation.py +0 -0
  57. {graphatoms-0.0.3 → graphatoms-1.0.0}/GraphAtoms.egg-info/dependency_links.txt +0 -0
  58. {graphatoms-0.0.3 → graphatoms-1.0.0}/GraphAtoms.egg-info/top_level.txt +0 -0
  59. {graphatoms-0.0.3 → graphatoms-1.0.0}/LICENSE +0 -0
  60. {graphatoms-0.0.3 → graphatoms-1.0.0}/README.md +0 -0
  61. {graphatoms-0.0.3 → graphatoms-1.0.0}/setup.cfg +0 -0
@@ -0,0 +1,16 @@
1
+ """The module for common use.
2
+
3
+ Many other modules depend on this module.
4
+ """
5
+
6
+ from ._abc import BaseMixin, XxxKeyMixin
7
+ from .base import AllBaseModel, BaseModel, ExtendedBaseModel, NpzPklBaseModel
8
+
9
+ __all__ = [
10
+ "AllBaseModel",
11
+ "BaseMixin",
12
+ "BaseModel",
13
+ "ExtendedBaseModel",
14
+ "NpzPklBaseModel",
15
+ "XxxKeyMixin",
16
+ ]
@@ -0,0 +1,52 @@
1
+ # ruff: noqa: D100 D102
2
+
3
+ import numpy as np
4
+ from numpy.typing import ArrayLike
5
+
6
+
7
+ class BaseMixin:
8
+ """The base mixin class which provides some useful classmethods."""
9
+
10
+ @staticmethod
11
+ def get_mask_or_index(k: ArrayLike, n: int) -> np.ndarray:
12
+ if np.isscalar(k):
13
+ if isinstance(k, bool):
14
+ k = [k] * n
15
+ elif isinstance(k, int):
16
+ k = [k]
17
+ else:
18
+ raise TypeError(f"Unsupported type({type(k)}): {k}.")
19
+ subset = np.asarray(k)
20
+ if subset.dtype == bool:
21
+ if subset.size != n:
22
+ raise KeyError(
23
+ f"Except {n} boolean array, but {subset.size} got."
24
+ )
25
+ else:
26
+ subset = np.unique(subset.astype(int))
27
+ if not 0 <= max(subset) < n:
28
+ raise KeyError(
29
+ f"Except 0-{n - 1} integer array, but the "
30
+ f"max({max(subset)}),min({min(subset)}) got."
31
+ )
32
+ return subset.flatten()
33
+
34
+ @classmethod
35
+ def get_index(cls, k: ArrayLike, n: int) -> np.ndarray:
36
+ result = cls.get_mask_or_index(k=k, n=n)
37
+ if result.dtype == bool:
38
+ result = np.arange(n)[result]
39
+ return result.astype(int, copy=False)
40
+
41
+ @classmethod
42
+ def get_mask(cls, k: ArrayLike, n: int) -> np.ndarray:
43
+ result = cls.get_mask_or_index(k=k, n=n)
44
+ if result.dtype != bool:
45
+ result = np.isin(np.arange(n), result)
46
+ return result.astype(bool, copy=False)
47
+
48
+
49
+ class XxxKeyMixin:
50
+ @property
51
+ def _DICT(self) -> dict[str, str]:
52
+ return {k: getattr(self, k) for k in dir(self) if k[0] != "_"}
@@ -0,0 +1,482 @@
1
+ # ruff: noqa: D100 D102
2
+ from collections.abc import Callable, Hashable, Mapping, Sequence
3
+ from pickle import dumps, loads
4
+ from sys import version_info
5
+ from typing import Annotated, Literal, override
6
+
7
+ import numpy as np
8
+ import pydantic
9
+ import tomli_w as toml_w
10
+ import yaml
11
+ from joblib import dump, load
12
+ from pyarrow import Schema
13
+ from typing_extensions import Any, Self
14
+
15
+ from GraphAtoms.utils import bytes as bytesutils
16
+ from GraphAtoms.utils import string as stringutils
17
+ from GraphAtoms.utils._pyarrow import get_pyarrow_schema
18
+
19
+ if version_info < (3, 11):
20
+ import tomli as tomllib # type: ignore
21
+ else:
22
+ import tomllib
23
+ __all__ = [
24
+ "BaseModel",
25
+ "ExtendedBaseModel",
26
+ "NpzPklBaseModel",
27
+ ]
28
+
29
+
30
+ class __Json(pydantic.BaseModel):
31
+ @pydantic.validate_call
32
+ def write_json(
33
+ self,
34
+ filename: pydantic.FilePath | pydantic.NewPath,
35
+ indent: int | None = 4,
36
+ **kwargs,
37
+ ) -> pydantic.FilePath:
38
+ kwargs["exclude_none"] = True
39
+ text = self.model_dump_json(indent=indent, **kwargs)
40
+ filename.write_text(text, encoding="utf-8")
41
+ return filename
42
+
43
+ @classmethod
44
+ @pydantic.validate_call
45
+ def read_json(cls, filename: pydantic.FilePath, **kwargs) -> Self:
46
+ return cls.model_validate_json(filename.read_bytes(), **kwargs)
47
+
48
+
49
+ class __Toml(pydantic.BaseModel):
50
+ @pydantic.validate_call
51
+ def write_toml(
52
+ self,
53
+ filename: pydantic.FilePath | pydantic.NewPath,
54
+ indent: int = 4,
55
+ **kwargs,
56
+ ) -> pydantic.FilePath:
57
+ kwargs["exclude_none"] = True
58
+ with filename.open("wb") as f:
59
+ toml_w.dump(
60
+ self.model_dump(mode="python", **kwargs),
61
+ f,
62
+ indent=indent,
63
+ multiline_strings=True,
64
+ )
65
+ return filename
66
+
67
+ @classmethod
68
+ @pydantic.validate_call
69
+ def read_toml(cls, filename: pydantic.FilePath, **kwargs) -> Self:
70
+ with filename.open("rb") as f:
71
+ data = tomllib.load(f)
72
+ return cls.model_validate(data, **kwargs)
73
+
74
+
75
+ class __Yaml(pydantic.BaseModel):
76
+ @pydantic.validate_call
77
+ def write_yaml(
78
+ self,
79
+ filename: pydantic.FilePath | pydantic.NewPath,
80
+ indent: int | None = 2,
81
+ **kwargs,
82
+ ) -> pydantic.FilePath:
83
+ kwargs["exclude_none"] = True
84
+ with filename.open("w", encoding="utf-8") as f:
85
+ yaml.safe_dump(
86
+ self.model_dump(mode="python", **kwargs),
87
+ f,
88
+ encoding="utf-8",
89
+ default_flow_style=False,
90
+ indent=indent,
91
+ )
92
+ return filename
93
+
94
+ @classmethod
95
+ @pydantic.validate_call
96
+ def read_yaml(cls, filename: pydantic.FilePath, **kwargs) -> Self:
97
+ with filename.open(encoding="utf-8") as f:
98
+ data = yaml.safe_load(f)
99
+ return cls.model_validate(data, **kwargs)
100
+
101
+
102
+ class __Npz(pydantic.BaseModel):
103
+ @pydantic.validate_call
104
+ def write_npz(
105
+ self,
106
+ filename: pydantic.FilePath | pydantic.NewPath,
107
+ compress: bool = True,
108
+ **kwargs,
109
+ ) -> pydantic.FilePath:
110
+ kwargs["exclude_none"] = True
111
+ (np.savez_compressed if compress else np.savez)(
112
+ filename,
113
+ allow_pickle=False,
114
+ **self.model_dump(mode="python", **kwargs),
115
+ )
116
+ return filename
117
+
118
+ @classmethod
119
+ @pydantic.validate_call
120
+ def read_npz(cls, filename: pydantic.FilePath, **kwargs) -> Self:
121
+ return cls.model_validate(np.load(filename), **kwargs)
122
+
123
+
124
+ class __Pickle(pydantic.BaseModel):
125
+ @pydantic.validate_call
126
+ def write_pickle(
127
+ self,
128
+ filename: pydantic.FilePath | pydantic.NewPath,
129
+ compress: bool | int | tuple[str, int] = 3,
130
+ **kwargs,
131
+ ) -> pydantic.FilePath:
132
+ """Persist the dictionary of this object into one file.
133
+
134
+ Read more in the reference:
135
+ https://joblib.readthedocs.io/en/latest/generated/joblib.dump.html
136
+
137
+ Args:
138
+ filename (str | Path | TextIOWrapper): The file object or path
139
+ of the file in which it is to be stored. The compression
140
+ method corresponding to one of the supported filename
141
+ extensions ('.z', '.gz', '.bz2', '.xz' or '.lzma')
142
+ will be used automatically.
143
+ compress (bool | int | tuple[str, int], optional):
144
+ Optional compression level for the data.
145
+ 0 or False is no compression.
146
+ Higher value means more compression, but also
147
+ slower read and write times.
148
+ Using a value of 3 is often a good compromise.
149
+ Defaults to 3.
150
+ exclude_defaults (bool): ...
151
+ exclude_none (bool): ...
152
+ **kwargs: ...
153
+
154
+ Note:
155
+ If compress is True, the compression level used is 3.
156
+ If compress is a 2-tuple, the first element must correspond to
157
+ a string between supported compressors (e.g 'zlib', 'gzip',
158
+ 'bz2', 'lzma' 'xz'), the second element must be an integer
159
+ from 0 to 9, corresponding to the compression level.
160
+ """
161
+ kwargs["exclude_none"] = True
162
+ dump(
163
+ self.model_dump(mode="python", **kwargs),
164
+ filename,
165
+ compress=compress, # type: ignore
166
+ )
167
+ return filename
168
+
169
+ @classmethod
170
+ @pydantic.validate_call
171
+ def read_pickle(cls, filename: pydantic.FilePath, **kwargs) -> Self:
172
+ return cls.model_validate(load(filename), **kwargs)
173
+
174
+
175
+ class _IoFactoryMixin(__Json):
176
+ @classmethod
177
+ def SUPPORTED_IO_FORMATS(cls) -> tuple[str]:
178
+ return ("json",)
179
+
180
+ @classmethod
181
+ @pydantic.validate_call
182
+ def __get_format(cls, fname: pydantic.FilePath | pydantic.NewPath) -> str:
183
+ format: str = fname.name.split(".")[-1].lower()
184
+ assert format in cls.SUPPORTED_IO_FORMATS(), (
185
+ f"Invalid format: {format}. Only "
186
+ f"{cls.SUPPORTED_IO_FORMATS()} are available."
187
+ )
188
+ if format in ("yml", "yaml"):
189
+ format = "yaml"
190
+ elif format == "json":
191
+ format = "json"
192
+ elif format == "toml":
193
+ format = "toml"
194
+ elif format == "npz":
195
+ format = "npz"
196
+ elif format in ("pkl", "pickle"):
197
+ format = "pickle"
198
+ return format
199
+
200
+ @pydantic.validate_call
201
+ def write(
202
+ self,
203
+ fname: pydantic.FilePath | pydantic.NewPath,
204
+ **kwargs,
205
+ ) -> pydantic.FilePath:
206
+ """The factory method for writing file of this object.
207
+
208
+ Support: json, yml/yaml, toml, pkl(pickle).
209
+ """
210
+ f = getattr(self, f"write_{self.__get_format(fname)}")
211
+ return f(fname, **kwargs)
212
+
213
+ @classmethod
214
+ @pydantic.validate_call
215
+ def read(cls, fname: pydantic.FilePath, **kwargs) -> Self:
216
+ """The factory classmethod for reading file.
217
+
218
+ Support: json, yml/yaml, toml, pkl(pickle).
219
+ """
220
+ f = getattr(cls, f"read_{cls.__get_format(fname)}")
221
+ return f(fname, **kwargs)
222
+
223
+
224
+ class __Bytes(pydantic.BaseModel):
225
+ @pydantic.validate_call
226
+ def to_bytes(
227
+ self,
228
+ compressformat: str = "snappy",
229
+ compresslevel: Annotated[int, pydantic.Field(ge=0, le=9)] = 0,
230
+ **kwargs,
231
+ ) -> bytes:
232
+ """Return the json bytes of this object."""
233
+ kwargs["exclude_none"] = True
234
+ return bytesutils.compress(
235
+ dumps(self.model_dump_json(**kwargs)), # type: ignore
236
+ format=compressformat, # type: ignore
237
+ compresslevel=compresslevel,
238
+ )
239
+
240
+ @classmethod
241
+ @pydantic.validate_call
242
+ def from_bytes(
243
+ cls,
244
+ data: bytes,
245
+ compressformat: str = "snappy",
246
+ **kw,
247
+ ) -> Self:
248
+ return cls.model_validate_json(
249
+ loads(
250
+ bytesutils.decompress(
251
+ data,
252
+ format=compressformat, # type: ignore
253
+ )
254
+ ),
255
+ **kw,
256
+ )
257
+
258
+
259
+ class __Str(pydantic.BaseModel):
260
+ @pydantic.validate_call
261
+ def to_str(self, **kwargs) -> str:
262
+ """Return the json string of this object."""
263
+ kwargs["exclude_none"] = True
264
+ return self.model_dump_json(**kwargs)
265
+
266
+ @classmethod
267
+ @pydantic.validate_call
268
+ def from_str(cls, data: str, **kw) -> Self:
269
+ return cls.model_validate_json(data, **kw)
270
+
271
+
272
+ class _ConvertFactoryMixin(__Bytes, __Str):
273
+ @pydantic.validate_call
274
+ def convert_to(self, format="bytes", **kw) -> Any:
275
+ return getattr(self, f"to_{format}")(**kw)
276
+
277
+ @classmethod
278
+ @pydantic.validate_call
279
+ def convert_from(cls, data: Any, format="bytes", **kw) -> Self:
280
+ return getattr(cls, f"from_{format}")(data, **kw)
281
+
282
+
283
+ class BaseModel(_IoFactoryMixin, _ConvertFactoryMixin, Hashable, __Pickle):
284
+ """A base class for creating Pydantic models.
285
+
286
+ This class support many file formats:
287
+ json by `pydantic`
288
+ pickle by `joblib`
289
+ And it support many object format:
290
+ bytes
291
+ str
292
+ """
293
+
294
+ model_config = pydantic.ConfigDict(frozen=True)
295
+
296
+ def _string(self) -> str:
297
+ """The string representation of this class.
298
+
299
+ The expression like `str(obj)` will output
300
+ `f"{self.__class__.__name__}({this_value})"`.
301
+ """
302
+ return "object"
303
+
304
+ @override
305
+ def model_dump(
306
+ self,
307
+ *,
308
+ mode: Literal["json", "python"] | str = "python",
309
+ include: pydantic.main.IncEx | None = None,
310
+ exclude: pydantic.main.IncEx | None = None,
311
+ context: Any | None = None,
312
+ by_alias: bool | None = None,
313
+ exclude_unset: bool = False,
314
+ exclude_defaults: bool = False,
315
+ exclude_none: bool = False,
316
+ round_trip: bool = False,
317
+ warnings: bool | Literal["none", "warn", "error"] = True,
318
+ fallback: Callable[[Any], Any] | None = None,
319
+ serialize_as_any: bool = False,
320
+ numpy_ndarray_compatible: bool = True,
321
+ ) -> dict[str, Any]:
322
+ result = super().model_dump(
323
+ mode=mode,
324
+ include=include,
325
+ exclude=exclude,
326
+ context=context,
327
+ by_alias=by_alias,
328
+ exclude_unset=exclude_unset,
329
+ exclude_defaults=exclude_defaults,
330
+ exclude_none=exclude_none,
331
+ round_trip=round_trip,
332
+ warnings=warnings,
333
+ fallback=fallback,
334
+ serialize_as_any=serialize_as_any,
335
+ )
336
+ if mode == "python" and numpy_ndarray_compatible:
337
+ for k, v0 in result.items():
338
+ v1 = getattr(self, k, None)
339
+ if type(v0) is not type(v1) and isinstance(v1, np.ndarray):
340
+ result[k] = v1
341
+ return result
342
+
343
+ def get_data_hash(self, algo: str = "blake2b", digest_size: int = 6) -> str:
344
+ """Get the hash of the data of this object."""
345
+ data = bytesutils.hash(self.to_bytes(), True, algo)
346
+ assert isinstance(data, str), "data isn't string."
347
+ return stringutils.hash(data, algo, digest_size)
348
+
349
+ @classmethod
350
+ def get_pyarrow_schema(cls) -> Schema:
351
+ """Get the pyarrow schema of this class."""
352
+ return get_pyarrow_schema(cls)
353
+
354
+ @classmethod
355
+ @override
356
+ def SUPPORTED_IO_FORMATS(cls) -> tuple[str]:
357
+ result: tuple[str] = super().SUPPORTED_IO_FORMATS()
358
+ return result + ("pickle", "pkl") # type: ignore
359
+
360
+ @override
361
+ def __hash__(self) -> int:
362
+ return hash(self.get_data_hash())
363
+
364
+ @override
365
+ def __str__(self) -> str:
366
+ return f"{self.__class__.__name__}({self._string()})"
367
+
368
+ @override
369
+ def __repr__(self) -> str:
370
+ return super().__repr__()
371
+
372
+ @override
373
+ def __eq__(self, other) -> bool:
374
+ if not isinstance(other, self.__class__):
375
+ return False
376
+ for k in self.__pydantic_fields__:
377
+ v0 = getattr(self, k, None)
378
+ v1 = getattr(other, k, None)
379
+ if (v0 is None) != (v1 is None):
380
+ return False
381
+ elif v0 is None and v1 is None:
382
+ continue
383
+ elif np.isscalar(v0) and np.isscalar(v1):
384
+ if abs(v0 - v1) > 1e-9: # type: ignore
385
+ return False
386
+ else:
387
+ continue
388
+
389
+ type0, type1 = type(v0), type(v1)
390
+ if type0 is not type1:
391
+ return False
392
+ elif issubclass(type0, pydantic.BaseModel | Sequence | Mapping):
393
+ if not v0.__eq__(v1):
394
+ return False
395
+ elif type0 is np.ndarray:
396
+ assert isinstance(v0, np.ndarray)
397
+ assert isinstance(v1, np.ndarray)
398
+ if v0.shape != v1.shape:
399
+ return False
400
+ if not np.allclose(v0, v1):
401
+ return False
402
+ else:
403
+ raise NotImplementedError(
404
+ "Unsupported type for __eq__: ", type0
405
+ )
406
+ return True
407
+
408
+
409
+ class ExtendedBaseModel(BaseModel, __Yaml, __Toml):
410
+ """A extended base class for creating Pydantic models.
411
+
412
+ This class support many file formats:
413
+ json by `pydantic`
414
+ yaml/yml by `pyyaml`
415
+ pickle by `joblib`
416
+ toml by `tomli_w`, `tomli`, & `toml`
417
+ And it support many object format:
418
+ bytes
419
+ str
420
+ """
421
+
422
+ @override
423
+ def __hash__(self) -> int:
424
+ return super().__hash__()
425
+
426
+ @classmethod
427
+ @override
428
+ def SUPPORTED_IO_FORMATS(cls) -> tuple[str]:
429
+ result: tuple[str] = super().SUPPORTED_IO_FORMATS()
430
+ return result + ("yaml", "yml", "toml") # type: ignore
431
+
432
+
433
+ class NpzPklBaseModel(BaseModel, __Npz):
434
+ """A extended base class for creating Pydantic models.
435
+
436
+ This class support many file formats:
437
+ json by `pydantic`
438
+ pickle by `joblib`
439
+ npz by `numpy`
440
+ And it support many object format:
441
+ bytes
442
+ str
443
+
444
+ Note: only numpy ndarray & numpy-compatible scalar value supported.
445
+ """
446
+
447
+ @override
448
+ def __hash__(self) -> int:
449
+ return super().__hash__()
450
+
451
+ @classmethod
452
+ @override
453
+ def SUPPORTED_IO_FORMATS(cls) -> tuple[str]:
454
+ result: tuple[str] = super().SUPPORTED_IO_FORMATS()
455
+ return result + ("npz",) # type: ignore
456
+
457
+
458
+ class AllBaseModel(ExtendedBaseModel, __Npz):
459
+ """A extended base class for creating Pydantic models.
460
+
461
+ This class support many file formats:
462
+ json by `pydantic`
463
+ npz by `numpy`
464
+ pickle by `joblib`
465
+ yaml/yml by `pyyaml`
466
+ toml by `tomli_w`, `tomli`, & `toml`
467
+ And it support many object format:
468
+ bytes
469
+ str
470
+
471
+ Note: only numpy ndarray & numpy-compatible scalar value supported.
472
+ """
473
+
474
+ @override
475
+ def __hash__(self) -> int:
476
+ return super().__hash__()
477
+
478
+ @classmethod
479
+ @override
480
+ def SUPPORTED_IO_FORMATS(cls) -> tuple[str]:
481
+ result: tuple[str] = super().SUPPORTED_IO_FORMATS()
482
+ return result + ("npz",) # type: ignore
@@ -0,0 +1,21 @@
1
+ """The Basic Classes For Systems and its Sub Classes."""
2
+
3
+ from GraphAtoms.containner._aOther import OTHER_KEY
4
+ from GraphAtoms.containner._atomic import ATOM_KEY, AtomsWithBoxEng
5
+ from GraphAtoms.containner._gBonded import BOND_KEY, BondsWithComp
6
+ from GraphAtoms.containner._graph import Graph
7
+ from GraphAtoms.containner._sysCluster import Cluster
8
+ from GraphAtoms.containner._sysGas import Gas
9
+ from GraphAtoms.containner._system import System
10
+
11
+ __all__ = [
12
+ "ATOM_KEY",
13
+ "AtomsWithBoxEng",
14
+ "BOND_KEY",
15
+ "BondsWithComp",
16
+ "Cluster",
17
+ "OTHER_KEY",
18
+ "Gas",
19
+ "Graph",
20
+ "System",
21
+ ]