python-datamodel 0.6.28__cp313-cp313-win_amd64.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.
@@ -0,0 +1,116 @@
1
+ import sys
2
+ from collections.abc import MutableMapping, Iterator, Iterable
3
+ from typing import Any, Optional, Union
4
+ from datamodel import Field
5
+
6
+ if sys.version_info < (3, 10):
7
+ from typing_extensions import ParamSpec
8
+ else:
9
+ from typing import ParamSpec
10
+ P = ParamSpec("P")
11
+
12
+ class ClassDict(dict, MutableMapping):
13
+ """ClassDict.
14
+
15
+ Mapping that works like both a simple Dictionary or a Mutable Object.
16
+ """
17
+ def __init__(self, *args: P.args, data: Optional[Union[tuple, dict]] = None, default: Any = None, **kwargs: P.kwargs):
18
+ self._columns: list = []
19
+ self.mapping = {}
20
+ self.default = default
21
+ self.mapping.update(*args, **kwargs)
22
+ self.update(data, **kwargs)
23
+
24
+ def update(self, items: Optional[Iterable] = None, **kwargs): # pylint: disable=W0221
25
+ if isinstance(items, dict):
26
+ for key, value in items.items():
27
+ # self.mapping[key] = value
28
+ self.mapping[key] = value
29
+ else:
30
+ for k,v in kwargs.items():
31
+ attr = getattr(self, k)
32
+ if isinstance(attr, Field):
33
+ try:
34
+ fn = attr.default
35
+ if callable(fn):
36
+ v = fn(v)
37
+ setattr(self, k, v)
38
+ else:
39
+ setattr(self, k, fn)
40
+ except KeyError:
41
+ pass
42
+ # self.mapping[k] = v
43
+ self.mapping[k] = v
44
+ self._columns = list(self.mapping.keys())
45
+
46
+ def __missing__(self, key):
47
+ return self.default
48
+
49
+ def items(self) -> zip: # type: ignore
50
+ return zip(self._columns, self.mapping)
51
+
52
+ def keys(self) -> list:
53
+ return self._columns
54
+
55
+ def set(self, key, value) -> None:
56
+ self.mapping[key] = value
57
+ if not key in self._columns:
58
+ self._columns.append(key)
59
+
60
+ ### Section: Simple magic methods
61
+ def __len__(self) -> int:
62
+ return len(self.mapping)
63
+
64
+ def __str__(self) -> str:
65
+ return f"<{type(self).__name__}({self.mapping})>"
66
+
67
+ def __repr__(self) -> str:
68
+ return f"<{type(self).__name__}({self.mapping})>"
69
+
70
+ def __contains__(self, key: str) -> bool:
71
+ return key in self._columns
72
+
73
+ def __delitem__(self, key) -> None:
74
+ value = self[key]
75
+ del self.mapping[key]
76
+ self._columns.remove(key)
77
+ self.pop(value, None)
78
+
79
+ def __delattr__(self, name: str) -> None:
80
+ value = self[name]
81
+ del self.mapping[name]
82
+ self._columns.remove(name)
83
+ self.pop(value, None)
84
+
85
+ def __setitem__(self, key, value):
86
+ self.mapping[key] = value
87
+ if not key in self._columns:
88
+ self._columns.append(key)
89
+
90
+ def __getitem__(self, key: Union[str, int]) -> Any:
91
+ """
92
+ Sequence-like operators
93
+ """
94
+ try:
95
+ return self.mapping[key]
96
+ except (KeyError, TypeError):
97
+ return None
98
+
99
+ def __getattr__(self, attr: str) -> Any:
100
+ """
101
+ Attributes for dict keys
102
+ """
103
+ try:
104
+ return self.__getitem__(attr)
105
+ except KeyError as ex:
106
+ raise KeyError(
107
+ f"User Error: invalid field name {attr} on {self.mapping!r}"
108
+ ) from ex
109
+ except TypeError as ex:
110
+ raise TypeError(
111
+ f"User Error: invalid attribute value on {self.mapping!r} for {attr}"
112
+ ) from ex
113
+
114
+ def __iter__(self) -> Iterator:
115
+ for value in self.mapping:
116
+ yield value
datamodel/models.py ADDED
@@ -0,0 +1,111 @@
1
+ from __future__ import annotations
2
+ from typing import Any
3
+ # Dataclass
4
+ from dataclasses import asdict as as_dict
5
+ from operator import attrgetter
6
+ from datamodel.fields import fields
7
+ from .abstract import ModelMeta, Meta
8
+ from .fields import Field
9
+
10
+ class ModelMixin:
11
+ """Interface for shared methods on Model classes.
12
+ """
13
+ def __unicode__(self):
14
+ return str(__class__)
15
+
16
+ def columns(self):
17
+ return self.__columns__
18
+
19
+ @classmethod
20
+ def get_columns(cls):
21
+ return cls.__columns__
22
+
23
+ @classmethod
24
+ def get_column(cls, name: str) -> Field:
25
+ try:
26
+ return cls.__columns__[name]
27
+ except KeyError:
28
+ raise AttributeError(
29
+ f"{cls.__name__} has no column {name}"
30
+ )
31
+
32
+ def get_fields(self):
33
+ return self.__fields__
34
+
35
+ def __getitem__(self, item):
36
+ return getattr(self, item)
37
+
38
+ def reset_values(self):
39
+ try:
40
+ self.__values__ = {}
41
+ except AttributeError:
42
+ pass
43
+
44
+ def old_value(self, name: str) -> Any:
45
+ """
46
+ old_value.
47
+ Get the old value of an attribute.
48
+ Args:
49
+ name (str): name of the attribute.
50
+ Returns:
51
+ Any: value of the attribute.
52
+ """
53
+ try:
54
+ return self.__values__[name]
55
+ except KeyError:
56
+ raise AttributeError(
57
+ f"{self.__class__.__name__} has no attribute {name}"
58
+ )
59
+
60
+ def column(self, name: str) -> Field:
61
+ return self.__columns__[name]
62
+
63
+ def __repr__(self) -> str:
64
+ f_repr = ", ".join(f"{f.name}={getattr(self, f.name)}" for f in fields(self))
65
+ return f"{self.__class__.__name__}({f_repr})"
66
+
67
+ def remove_nulls(self, obj: Any) -> dict[str, Any]:
68
+ """Recursively removes any fields with None values from the given object."""
69
+ if isinstance(obj, list):
70
+ return [self.remove_nulls(item) for item in obj]
71
+ elif isinstance(obj, dict):
72
+ return {
73
+ key: self.remove_nulls(value) for key, value in obj.items()
74
+ if value is not None
75
+ }
76
+ else:
77
+ return obj
78
+
79
+ def to_dict(self):
80
+ if self.Meta.remove_nulls is True:
81
+ return self.remove_nulls(as_dict(self, dict_factory=dict))
82
+ return as_dict(self)
83
+
84
+ def json(self, **kwargs):
85
+ encoder = self.__encoder__(**kwargs)
86
+ return encoder(as_dict(self))
87
+
88
+ to_json = json
89
+
90
+ def is_valid(self) -> bool:
91
+ """is_valid.
92
+
93
+ returns True when current Model is valid under datatype validations.
94
+ Returns:
95
+ bool: True if current model is valid.
96
+ """
97
+ return bool(self.__valid__)
98
+
99
+ class Model(ModelMixin, metaclass=ModelMeta):
100
+ """Model.
101
+
102
+ Basic dataclass-based Model.
103
+ """
104
+ Meta = Meta
105
+
106
+ def __post_init__(self) -> None:
107
+ """
108
+ Post init method.
109
+ Useful for making Post-validations of Model.
110
+ """
111
+ self.__initialised__ = True
File without changes
@@ -0,0 +1,15 @@
1
+ """
2
+ JSON Encoders.
3
+ """
4
+ from .json import JSONContent, json_encoder
5
+
6
+ DefaultEncoder = JSONContent
7
+
8
+ class BaseEncoder:
9
+ """
10
+ Encoder replacement for json.dumps using orjson
11
+ """
12
+
13
+ def __init__(self, *args, **kwargs):
14
+ encoder = DefaultEncoder(*args, **kwargs)
15
+ self.encode = encoder.__call__