schemez 0.2.2__py3-none-any.whl → 0.2.3__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.
schemez/__init__.py CHANGED
@@ -1,4 +1,4 @@
1
- __version__ = "0.2.2"
1
+ __version__ = "0.2.3"
2
2
 
3
3
 
4
4
  from schemez.schema import Schema
schemez/pydantic_types.py CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Annotated
5
+ from typing import Annotated, Any
6
6
 
7
- from pydantic import Field
7
+ from pydantic import BaseModel, Field
8
8
 
9
9
 
10
10
  ModelIdentifier = Annotated[
@@ -40,3 +40,13 @@ MimeType = Annotated[
40
40
  description="Standard MIME type identifying file formats and content types",
41
41
  ),
42
42
  ]
43
+
44
+
45
+ def get_field_type(model: type[BaseModel], field_name: str) -> dict[str, Any]:
46
+ """Extract field_type metadata from a model field."""
47
+ field_info = model.model_fields[field_name]
48
+ metadata = {}
49
+ if field_info.json_schema_extra and isinstance(field_info.json_schema_extra, dict):
50
+ metadata.update(field_info.json_schema_extra)
51
+
52
+ return metadata
schemez/schema.py CHANGED
@@ -216,11 +216,21 @@ class Schema(BaseModel):
216
216
 
217
217
  return get_ctor_basemodel(target_cls)
218
218
 
219
- def model_dump_yaml(self) -> str:
219
+ def model_dump_yaml(
220
+ self,
221
+ exclude_none: bool = True,
222
+ exclude_defaults: bool = False,
223
+ exclude_unset: bool = False,
224
+ ) -> str:
220
225
  """Dump configuration to YAML string."""
221
226
  import yamling
222
227
 
223
- return yamling.dump_yaml(self.model_dump(exclude_none=True))
228
+ text = self.model_dump(
229
+ exclude_none=exclude_none,
230
+ exclude_defaults=exclude_defaults,
231
+ exclude_unset=exclude_unset,
232
+ )
233
+ return yamling.dump_yaml(text)
224
234
 
225
235
  def save(self, path: StrPath, overwrite: bool = False) -> None:
226
236
  """Save configuration to a YAML file.
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from enum import Enum
5
6
  from typing import Annotated, Any, Literal
6
7
 
7
8
  from pydantic import BaseModel, Field, create_model
@@ -16,6 +17,7 @@ class SchemaField(Schema):
16
17
  - Data type specification
17
18
  - Optional description
18
19
  - Validation constraints
20
+ - Enum values (when type is 'enum')
19
21
 
20
22
  Used by InlineSchemaDef to structure response fields.
21
23
  """
@@ -26,8 +28,58 @@ class SchemaField(Schema):
26
28
  description: str | None = None
27
29
  """Optional description of what this field represents"""
28
30
 
31
+ values: list[Any] | None = None
32
+ """Values for enum type fields"""
33
+
34
+ # Common validation constraints
35
+ default: Any | None = None
36
+ """Default value for the field"""
37
+
38
+ title: str | None = None
39
+ """Title for the field in generated JSON Schema"""
40
+
41
+ pattern: str | None = None
42
+ """Regex pattern for string validation"""
43
+
44
+ min_length: int | None = None
45
+ """Minimum length for collections"""
46
+
47
+ max_length: int | None = None
48
+ """Maximum length for collections"""
49
+
50
+ gt: float | None = None
51
+ """Greater than (exclusive) validation for numbers"""
52
+
53
+ ge: float | None = None
54
+ """Greater than or equal (inclusive) validation for numbers"""
55
+
56
+ lt: float | None = None
57
+ """Less than (exclusive) validation for numbers"""
58
+
59
+ le: float | None = None
60
+ """Less than or equal (inclusive) validation for numbers"""
61
+
62
+ multiple_of: float | None = None
63
+ """Number must be a multiple of this value"""
64
+
65
+ literal_value: Any | None = None
66
+ """Value for Literal type constraint, makes field accept only this specific value"""
67
+
68
+ examples: list[Any] | None = None
69
+ """Examples for this field in JSON Schema"""
70
+
71
+ optional: bool = False
72
+ """Whether this field is optional (None value allowed)"""
73
+
74
+ json_schema_extra: dict[str, Any] | None = None
75
+ """Additional JSON Schema information"""
76
+
77
+ field_config: dict[str, Any] | None = None
78
+ """Configuration for Pydantic model fields"""
79
+
80
+ # Extensibility for future or custom constraints
29
81
  constraints: dict[str, Any] = Field(default_factory=dict)
30
- """Optional validation constraints for the field"""
82
+ """Additional constraints not covered by explicit fields"""
31
83
 
32
84
 
33
85
  class BaseSchemaDef(Schema):
@@ -66,12 +118,95 @@ class InlineSchemaDef(BaseSchemaDef):
66
118
  """Create Pydantic model from inline definition."""
67
119
  fields = {}
68
120
  for name, field in self.fields.items():
69
- python_type = helpers.resolve_type_string(field.type)
70
- if not python_type:
71
- msg = f"Unsupported field type: {field.type}"
72
- raise ValueError(msg)
73
-
74
- field_info = Field(description=field.description, **(field.constraints))
121
+ # Initialize constraint dictionary
122
+ field_constraints = {}
123
+
124
+ # Handle enum type
125
+ if field.type == "enum":
126
+ if not field.values:
127
+ msg = f"Field '{name}' has type 'enum' but no values defined"
128
+ raise ValueError(msg)
129
+
130
+ # Create dynamic Enum class
131
+ enum_name = f"{name.capitalize()}Enum"
132
+
133
+ # Create enum members dictionary
134
+ enum_members = {}
135
+ for i, value in enumerate(field.values):
136
+ if isinstance(value, str) and value.isidentifier():
137
+ # If value is a valid Python identifier, use it as is
138
+ key = value
139
+ else:
140
+ # Otherwise, create a synthetic name
141
+ key = f"VALUE_{i}"
142
+ enum_members[key] = value
143
+
144
+ # Create the enum class
145
+ enum_class = Enum(enum_name, enum_members)
146
+ python_type: Any = enum_class
147
+
148
+ # Handle enum default value specially
149
+ if field.default is not None:
150
+ # Store default value as the enum value string
151
+ # Pydantic v2 will convert it to the enum instance
152
+ if field.default in list(field.values):
153
+ field_constraints["default"] = field.default
154
+ else:
155
+ msg = (
156
+ f"Default value {field.default!r} not found "
157
+ f"in enum values for field {name!r}"
158
+ )
159
+ raise ValueError(msg)
160
+ else:
161
+ python_type = helpers.resolve_type_string(field.type)
162
+ if not python_type:
163
+ msg = f"Unsupported field type: {field.type}"
164
+ raise ValueError(msg)
165
+
166
+ # Handle literal constraint if provided
167
+ if field.literal_value is not None:
168
+ from typing import Literal as LiteralType
169
+
170
+ python_type = LiteralType[field.literal_value]
171
+
172
+ # Handle optional fields (allowing None)
173
+ if field.optional:
174
+ python_type = python_type | None # type: ignore
175
+
176
+ # Add standard Pydantic constraints
177
+ # Collect all constraint values
178
+ for constraint in [
179
+ "default",
180
+ "title",
181
+ "min_length",
182
+ "max_length",
183
+ "pattern",
184
+ "min_length",
185
+ "max_length",
186
+ "gt",
187
+ "ge",
188
+ "lt",
189
+ "le",
190
+ "multiple_of",
191
+ ]:
192
+ value = getattr(field, constraint, None)
193
+ if value is not None:
194
+ field_constraints[constraint] = value
195
+
196
+ # Handle examples separately (Pydantic v2 way)
197
+ if field.examples:
198
+ if field.json_schema_extra is None:
199
+ field.json_schema_extra = {}
200
+ field.json_schema_extra["examples"] = field.examples
201
+
202
+ # Add json_schema_extra if provided
203
+ if field.json_schema_extra:
204
+ field_constraints["json_schema_extra"] = field.json_schema_extra
205
+
206
+ # Add any additional constraints
207
+ field_constraints.update(field.constraints)
208
+
209
+ field_info = Field(description=field.description, **field_constraints)
75
210
  fields[name] = (python_type, field_info)
76
211
 
77
212
  cls_name = self.description or "ResponseType"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: schemez
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Pydantic shim for config stuff
5
5
  Project-URL: Documentation, https://phil65.github.io/schemez/
6
6
  Project-URL: Source, https://github.com/phil65/schemez
@@ -0,0 +1,14 @@
1
+ schemez/__init__.py,sha256=QrVN-zXLiAwYYdMbCxin08TTcks9QkRXZt4FyS5XwLw,565
2
+ schemez/code.py,sha256=usZLov9i5KpK1W2VJxngUzeetgrINtodiooG_AxN-y4,2072
3
+ schemez/convert.py,sha256=b6Sz11lq0HvpXfMREOqnnw8rcVg2XzTKhjjPNc4YIoE,4403
4
+ schemez/docstrings.py,sha256=kmd660wcomXzKac0SSNYxPRNbVCUovrpmE9jwnVRS6c,4115
5
+ schemez/helpers.py,sha256=Ee3wvFbt65ljhWDFdb6ACVUJK4KLjJFVzl4Le75pOBQ,5159
6
+ schemez/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ schemez/pydantic_types.py,sha256=iiaHqVkWVd1TZry933aDYJnyzMD0HJIABfROR9txxhA,1581
8
+ schemez/schema.py,sha256=VeNSFec6aCR9GgqXLBE3t4TZeUoS9BDmIoofe9nbqVI,8804
9
+ schemez/schemadef/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
+ schemez/schemadef/schemadef.py,sha256=43GQ8puUBByiSMaDbR6sJ0B-AjRSYQhEvX2Rx4gmjHI,8609
11
+ schemez-0.2.3.dist-info/METADATA,sha256=hI62AloXcRv4SKKeiSmdycBJOuIZWdWfLGeIueu8ss0,5891
12
+ schemez-0.2.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
13
+ schemez-0.2.3.dist-info/licenses/LICENSE,sha256=AteGCH9r177TxxrOFEiOARrastASsf7yW6MQxlAHdwA,1078
14
+ schemez-0.2.3.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- schemez/__init__.py,sha256=R1tqWI3CF06HlDwunmw4TB-egVZ8sr1QmL9cr1eJ75k,565
2
- schemez/code.py,sha256=usZLov9i5KpK1W2VJxngUzeetgrINtodiooG_AxN-y4,2072
3
- schemez/convert.py,sha256=b6Sz11lq0HvpXfMREOqnnw8rcVg2XzTKhjjPNc4YIoE,4403
4
- schemez/docstrings.py,sha256=kmd660wcomXzKac0SSNYxPRNbVCUovrpmE9jwnVRS6c,4115
5
- schemez/helpers.py,sha256=Ee3wvFbt65ljhWDFdb6ACVUJK4KLjJFVzl4Le75pOBQ,5159
6
- schemez/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- schemez/pydantic_types.py,sha256=kQRR9jVZ4vyLPPqxZSGcbP2gtcHUPUWsOR3tcPNM4X0,1197
8
- schemez/schema.py,sha256=8nwLYW6J-RIMbKjt0BZK3zlktZZzBYXabGFlaQsecCQ,8538
9
- schemez/schemadef/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
- schemez/schemadef/schemadef.py,sha256=TLfcmCxPLZEvScxuIMlss0QDRWtQNhxLQ8z2i0Linoc,3794
11
- schemez-0.2.2.dist-info/METADATA,sha256=mTyUilTrGhabvoQXB3roUwSWJwnNTV7CrSXAlTKmy90,5891
12
- schemez-0.2.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
13
- schemez-0.2.2.dist-info/licenses/LICENSE,sha256=AteGCH9r177TxxrOFEiOARrastASsf7yW6MQxlAHdwA,1078
14
- schemez-0.2.2.dist-info/RECORD,,