python-datamodel 0.10.1__cp313-cp313-win32.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.
Files changed (78) hide show
  1. datamodel/__init__.py +13 -0
  2. datamodel/abstract.py +383 -0
  3. datamodel/adaptive/__init__.py +0 -0
  4. datamodel/adaptive/models.py +598 -0
  5. datamodel/aliases/__init__.py +26 -0
  6. datamodel/base.py +180 -0
  7. datamodel/converters.c +43471 -0
  8. datamodel/converters.cp313-win32.pyd +0 -0
  9. datamodel/converters.html +17387 -0
  10. datamodel/converters.pyx +1489 -0
  11. datamodel/exceptions.c +13455 -0
  12. datamodel/exceptions.cp313-win32.pyd +0 -0
  13. datamodel/exceptions.html +1261 -0
  14. datamodel/exceptions.pxd +13 -0
  15. datamodel/exceptions.pyx +50 -0
  16. datamodel/fields.cp313-win32.pyd +0 -0
  17. datamodel/fields.cpp +17401 -0
  18. datamodel/fields.html +3912 -0
  19. datamodel/fields.pyx +309 -0
  20. datamodel/functions.cp313-win32.pyd +0 -0
  21. datamodel/functions.cpp +9068 -0
  22. datamodel/functions.html +1766 -0
  23. datamodel/functions.pxd +9 -0
  24. datamodel/functions.pyx +82 -0
  25. datamodel/jsonld/__init__.py +45 -0
  26. datamodel/jsonld/models.py +500 -0
  27. datamodel/libs/__init__.py +1 -0
  28. datamodel/libs/mapping.c +15067 -0
  29. datamodel/libs/mapping.cp313-win32.pyd +0 -0
  30. datamodel/libs/mapping.html +2618 -0
  31. datamodel/libs/mapping.pxd +11 -0
  32. datamodel/libs/mapping.pyx +135 -0
  33. datamodel/libs/mutables.py +127 -0
  34. datamodel/models.py +814 -0
  35. datamodel/parsers/__init__.py +0 -0
  36. datamodel/parsers/encoders.py +15 -0
  37. datamodel/parsers/json.cp313-win32.pyd +0 -0
  38. datamodel/parsers/json.cpp +17004 -0
  39. datamodel/parsers/json.html +3365 -0
  40. datamodel/parsers/json.pyx +250 -0
  41. datamodel/profiler.py +21 -0
  42. datamodel/py.typed +0 -0
  43. datamodel/rs_core/Cargo.toml +17 -0
  44. datamodel/rs_core/src/lib.rs +294 -0
  45. datamodel/rs_parsers/Cargo.toml +22 -0
  46. datamodel/rs_parsers/src/lib.rs +571 -0
  47. datamodel/rs_parsers.cp313-win32.pyd +0 -0
  48. datamodel/rs_validators/Cargo.toml +17 -0
  49. datamodel/rs_validators/src/lib.rs +0 -0
  50. datamodel/typedefs/__init__.py +9 -0
  51. datamodel/typedefs/singleton.c +9169 -0
  52. datamodel/typedefs/singleton.cp313-win32.pyd +0 -0
  53. datamodel/typedefs/singleton.html +629 -0
  54. datamodel/typedefs/singleton.pxd +9 -0
  55. datamodel/typedefs/singleton.pyx +24 -0
  56. datamodel/typedefs/types.c +11716 -0
  57. datamodel/typedefs/types.cp313-win32.pyd +0 -0
  58. datamodel/typedefs/types.html +732 -0
  59. datamodel/typedefs/types.pxd +11 -0
  60. datamodel/typedefs/types.pyx +39 -0
  61. datamodel/types.c +7165 -0
  62. datamodel/types.cp313-win32.pyd +0 -0
  63. datamodel/types.html +716 -0
  64. datamodel/types.pyx +100 -0
  65. datamodel/validation.cp313-win32.pyd +0 -0
  66. datamodel/validation.cpp +17085 -0
  67. datamodel/validation.html +4769 -0
  68. datamodel/validation.pyx +315 -0
  69. datamodel/version.py +13 -0
  70. examples/nn/examples.py +311 -0
  71. examples/nn/stores.py +151 -0
  72. examples/tests/sp_types.py +294 -0
  73. examples/tests/speed_dates.py +26 -0
  74. python_datamodel-0.10.1.dist-info/LICENSE +29 -0
  75. python_datamodel-0.10.1.dist-info/METADATA +320 -0
  76. python_datamodel-0.10.1.dist-info/RECORD +78 -0
  77. python_datamodel-0.10.1.dist-info/WHEEL +5 -0
  78. python_datamodel-0.10.1.dist-info/top_level.txt +7 -0
datamodel/base.py ADDED
@@ -0,0 +1,180 @@
1
+ from collections.abc import Callable
2
+ from typing import Any, Dict
3
+ # Dataclass
4
+ from dataclasses import (
5
+ _FIELD,
6
+ )
7
+ from html import escape
8
+ from .converters import processing_fields, register_parser
9
+ from .fields import Field
10
+ from .exceptions import ValidationError
11
+ from .abstract import ModelMeta
12
+ from .models import ModelMixin
13
+
14
+
15
+ RendererFn = Callable[["BaseModel", bool], str]
16
+
17
+ HTML_RENDERERS: Dict[str, RendererFn] = {}
18
+
19
+ def register_renderer(schema_type: str):
20
+ """
21
+ Decorator to register a custom renderer function for a given schema_type.
22
+ """
23
+ def decorator(fn: RendererFn):
24
+ HTML_RENDERERS[schema_type] = fn
25
+ return fn
26
+ return decorator
27
+
28
+
29
+ class BaseModel(ModelMixin, metaclass=ModelMeta):
30
+ """
31
+ BaseModel.
32
+ Base Model for all DataModels.
33
+ """
34
+
35
+ def __post_init__(self) -> None:
36
+ """
37
+ Post init method.
38
+ Fill fields with function-factory or calling validations
39
+ """
40
+ # checking if an attribute is already a dataclass:
41
+ columns = list(self.__columns__.items())
42
+
43
+ if errors := processing_fields(self, columns):
44
+ if self.Meta.strict is True:
45
+ raise ValidationError(
46
+ f"""{self.modelName}: There are errors in Model. \
47
+ Hint: please check the "payload" attribute in the exception.""",
48
+ payload=errors
49
+ )
50
+ self.__errors__ = errors
51
+ object.__setattr__(self, "__valid__", False)
52
+ else:
53
+ object.__setattr__(self, "__valid__", True)
54
+
55
+ @classmethod
56
+ def register_parser(
57
+ cls,
58
+ target_type: Any,
59
+ func: Callable,
60
+ field_name: str = None
61
+ ):
62
+ key = (target_type, field_name) if field_name else target_type
63
+ register_parser(key, func)
64
+
65
+ @classmethod
66
+ def add_field(cls, name: str, value: Any = None) -> None:
67
+ if cls.Meta.strict is True:
68
+ raise TypeError(
69
+ f'Cannot create a new field {name} on a Strict Model.'
70
+ )
71
+ if name != '__errors__':
72
+ f = Field(required=False, default=value)
73
+ f.name = name
74
+ f.type = type(value)
75
+ f._field_type = _FIELD
76
+ cls.__columns__[name] = f
77
+ cls.__dataclass_fields__[name] = f
78
+
79
+ def create_field(self, name: str, value: Any) -> None:
80
+ """create_field.
81
+ create a new Field on Model (when strict is False).
82
+ Args:
83
+ name (str): name of the field
84
+ value (Any): value to be assigned.
85
+ Raises:
86
+ TypeError: when try to create a new field on an Strict Model.
87
+ """
88
+ if self.Meta.strict is True:
89
+ raise TypeError(
90
+ f'Cannot create a new field {name} on a Strict Model.'
91
+ )
92
+ if name != '__errors__':
93
+ f = Field(required=False, default=value)
94
+ f.name = name
95
+ f.type = type(value)
96
+ f._field_type = _FIELD
97
+ self.__columns__[name] = f
98
+ self.__dataclass_fields__[name] = f
99
+ setattr(self, name, value)
100
+
101
+ def set(self, name: str, value: Any) -> None:
102
+ """set.
103
+ Alias for Create Field.
104
+ Args:
105
+ name (str): name of the field
106
+ value (Any): value to be assigned.
107
+ """
108
+ if name in self.__columns__:
109
+ setattr(self, name, value)
110
+ elif name != '__errors__' and self.Meta.strict is False:
111
+ self.create_field(name, value)
112
+
113
+ def get_errors(self):
114
+ return self.__errors__
115
+
116
+ def to_html(self, top_level: bool = True) -> str:
117
+ """to_html.
118
+ Convert Model to HTML.
119
+
120
+ Args:
121
+ top_level (bool, optional): If True, adds the @context to the schema.
122
+ """
123
+ # 1) Determine the schema type from self.Meta or fallback to class name
124
+ schema_type = getattr(self.Meta, 'schema_type', self.__class__.__name__)
125
+
126
+ if schema_type in HTML_RENDERERS:
127
+ return HTML_RENDERERS[schema_type](self, top_level)
128
+
129
+ # 2) Container opening. For top-level objects, we specify:
130
+ # - vocab="https://schema.org/"
131
+ # - typeof="Recipe" (or other type)
132
+ # For nested objects, we might omit the 'vocab' attribute
133
+ # or rely on the parent's scope.
134
+ if top_level:
135
+ container_open = f'<div vocab="https://schema.org/" typeof="{escape(schema_type)}">'
136
+ else:
137
+ container_open = f'<div property="{escape(schema_type)}" typeof="{escape(schema_type)}">'
138
+
139
+ # We'll accumulate our HTML pieces here
140
+ pieces = [container_open]
141
+
142
+ # 3) Iterate over each field in this model
143
+ for field_name, value in self.__dict__.items():
144
+ # Skip internal or error fields
145
+ if field_name.startswith('_') or field_name == '__errors__':
146
+ continue
147
+
148
+ # Optionally skip if None
149
+ if value is None:
150
+ continue
151
+
152
+ # 4) If value is a nested model, convert it to HTML as well
153
+ if isinstance(value, BaseModel):
154
+ nested_html = value.to_html(False)
155
+ snippet = f'<div property="{escape(field_name)}">\n{nested_html}\n</div>'
156
+ pieces.append(snippet)
157
+
158
+ elif isinstance(value, list):
159
+ # We might iterate and produce multiple lines
160
+ for item in value:
161
+ if isinstance(item, BaseModel):
162
+ nested_html = item.to_html(False)
163
+ snippet = f'<div property="{escape(field_name)}">\n{nested_html}\n</div>'
164
+ else:
165
+ # If it's a simple scalar, just output a <span>
166
+ # e.g.: <span property="recipeIngredient">3 bananas</span>
167
+ val_escaped = escape(str(item))
168
+ snippet = f'<span property="{escape(field_name)}">{val_escaped}</span>'
169
+ pieces.append(snippet)
170
+ else:
171
+ # For simple scalars (str, int, etc.):
172
+ # We might choose <span> or <meta> based on type.
173
+ # We'll do something simple: a <span>
174
+ val_escaped = escape(str(value))
175
+ snippet = f'<span property="{escape(field_name)}">{val_escaped}</span>'
176
+ pieces.append(snippet)
177
+
178
+ # 4) Close the container
179
+ pieces.append('</div>')
180
+ return "\n".join(pieces)