structtype 0.6.0__tar.gz → 0.7.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 (56) hide show
  1. {structtype-0.6.0/src/structtype.egg-info → structtype-0.7.0}/PKG-INFO +1 -1
  2. {structtype-0.6.0 → structtype-0.7.0}/src/structtype/__init__.py +14 -0
  3. {structtype-0.6.0 → structtype-0.7.0}/src/structtype/__init__.pyi +55 -67
  4. {structtype-0.6.0 → structtype-0.7.0}/src/structtype/_adapter.py +15 -14
  5. {structtype-0.6.0 → structtype-0.7.0}/src/structtype/_core.c +2771 -577
  6. {structtype-0.6.0 → structtype-0.7.0}/src/structtype/_inspect.py +32 -23
  7. {structtype-0.6.0 → structtype-0.7.0}/src/structtype/_json_schema.py +3 -1
  8. {structtype-0.6.0 → structtype-0.7.0}/src/structtype/_version.py +2 -2
  9. {structtype-0.6.0 → structtype-0.7.0/src/structtype.egg-info}/PKG-INFO +1 -1
  10. {structtype-0.6.0 → structtype-0.7.0}/src/structtype.egg-info/SOURCES.txt +1 -0
  11. {structtype-0.6.0 → structtype-0.7.0}/tests/test_adapter.py +18 -11
  12. structtype-0.7.0/tests/test_annotations.py +1627 -0
  13. {structtype-0.6.0 → structtype-0.7.0}/tests/test_check.py +91 -5
  14. {structtype-0.6.0 → structtype-0.7.0}/tests/test_constraints.py +220 -146
  15. {structtype-0.6.0 → structtype-0.7.0}/tests/test_inspect.py +17 -23
  16. {structtype-0.6.0 → structtype-0.7.0}/tests/test_json.py +61 -61
  17. {structtype-0.6.0 → structtype-0.7.0}/tests/test_schema.py +20 -15
  18. {structtype-0.6.0 → structtype-0.7.0}/tests/test_struct.py +3 -3
  19. {structtype-0.6.0 → structtype-0.7.0}/tests/test_struct_meta.py +1 -1
  20. {structtype-0.6.0 → structtype-0.7.0}/tests/typecheck/fields.py +17 -8
  21. {structtype-0.6.0 → structtype-0.7.0}/.opencode/opencode.json +0 -0
  22. {structtype-0.6.0 → structtype-0.7.0}/.opencode/plugins/graphify.js +0 -0
  23. {structtype-0.6.0 → structtype-0.7.0}/AGENTS.md +0 -0
  24. {structtype-0.6.0 → structtype-0.7.0}/LICENSE +0 -0
  25. {structtype-0.6.0 → structtype-0.7.0}/MANIFEST.in +0 -0
  26. {structtype-0.6.0 → structtype-0.7.0}/Makefile +0 -0
  27. {structtype-0.6.0 → structtype-0.7.0}/README.md +0 -0
  28. {structtype-0.6.0 → structtype-0.7.0}/pyproject.toml +0 -0
  29. {structtype-0.6.0 → structtype-0.7.0}/setup.cfg +0 -0
  30. {structtype-0.6.0 → structtype-0.7.0}/setup.py +0 -0
  31. {structtype-0.6.0 → structtype-0.7.0}/src/structtype/_utils.py +0 -0
  32. {structtype-0.6.0 → structtype-0.7.0}/src/structtype/atof.h +0 -0
  33. {structtype-0.6.0 → structtype-0.7.0}/src/structtype/atof_consts.h +0 -0
  34. {structtype-0.6.0 → structtype-0.7.0}/src/structtype/common.h +0 -0
  35. {structtype-0.6.0 → structtype-0.7.0}/src/structtype/itoa.h +0 -0
  36. {structtype-0.6.0 → structtype-0.7.0}/src/structtype/py.typed +0 -0
  37. {structtype-0.6.0 → structtype-0.7.0}/src/structtype/ryu.h +0 -0
  38. {structtype-0.6.0 → structtype-0.7.0}/src/structtype.egg-info/dependency_links.txt +0 -0
  39. {structtype-0.6.0 → structtype-0.7.0}/src/structtype.egg-info/top_level.txt +0 -0
  40. {structtype-0.6.0 → structtype-0.7.0}/tests/__init__.py +0 -0
  41. {structtype-0.6.0 → structtype-0.7.0}/tests/conftest.py +0 -0
  42. {structtype-0.6.0 → structtype-0.7.0}/tests/test_JSONTestSuite.py +0 -0
  43. {structtype-0.6.0 → structtype-0.7.0}/tests/test_attrs.py +0 -0
  44. {structtype-0.6.0 → structtype-0.7.0}/tests/test_cpylint.py +0 -0
  45. {structtype-0.6.0 → structtype-0.7.0}/tests/test_free_threading.py +0 -0
  46. {structtype-0.6.0 → structtype-0.7.0}/tests/test_memory.py +0 -0
  47. {structtype-0.6.0 → structtype-0.7.0}/tests/test_msgspec.py +0 -0
  48. {structtype-0.6.0 → structtype-0.7.0}/tests/test_pydantic.py +0 -0
  49. {structtype-0.6.0 → structtype-0.7.0}/tests/test_raw.py +0 -0
  50. {structtype-0.6.0 → structtype-0.7.0}/tests/test_typecheck.py +0 -0
  51. {structtype-0.6.0 → structtype-0.7.0}/tests/test_utils.py +0 -0
  52. {structtype-0.6.0 → structtype-0.7.0}/tests/typecheck/api.py +0 -0
  53. {structtype-0.6.0 → structtype-0.7.0}/tests/typecheck/basic.py +0 -0
  54. {structtype-0.6.0 → structtype-0.7.0}/tests/typecheck/types.py +0 -0
  55. {structtype-0.6.0 → structtype-0.7.0}/tests/utils.py +0 -0
  56. {structtype-0.6.0 → structtype-0.7.0}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: structtype
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: Fast Struct type with validation and JSON serialization for Python.
5
5
  Maintainer-email: Wolfgang Langner <tds333@mailbox.org>
6
6
  License-Expression: BSD-3-Clause
@@ -3,16 +3,23 @@ from ._core import ( # type: ignore
3
3
  ALL_BUILTIN_TYPES,
4
4
  NODEFAULT,
5
5
  UNSET,
6
+ BytesValidator,
7
+ CollectionValidator,
6
8
  DecodeError,
7
9
  EncodeError,
8
10
  Factory,
9
11
  Field,
12
+ NumericValidator,
10
13
  Raw,
14
+ Serializer,
11
15
  Struct,
12
16
  StructConfig,
13
17
  StructMeta,
18
+ StrValidator,
19
+ TimezoneValidator,
14
20
  UnsetType,
15
21
  ValidationError,
22
+ Validator,
16
23
  )
17
24
  from ._inspect import FieldInfo, fields
18
25
  from ._json_schema import json_schema, json_schema_components, json_schema_dump
@@ -22,18 +29,25 @@ __all__ = [
22
29
  "ALL_BUILTIN_TYPES",
23
30
  "NODEFAULT",
24
31
  "UNSET",
32
+ "BytesValidator",
33
+ "CollectionValidator",
25
34
  "DecodeError",
26
35
  "EncodeError",
27
36
  "Factory",
28
37
  "Field",
29
38
  "FieldInfo",
39
+ "NumericValidator",
30
40
  "Raw",
41
+ "Serializer",
42
+ "StrValidator",
31
43
  "Struct",
32
44
  "StructAdapter",
33
45
  "StructConfig",
34
46
  "StructMeta",
47
+ "TimezoneValidator",
35
48
  "UnsetType",
36
49
  "ValidationError",
50
+ "Validator",
37
51
  "__version__",
38
52
  "fields",
39
53
  "json_schema",
@@ -179,107 +179,95 @@ class Factory:
179
179
 
180
180
  @final
181
181
  class Field:
182
- # Numeric:
183
- @overload
184
182
  def __init__(
185
183
  self,
186
184
  *,
187
- gt: int | float | None = None,
188
- lt: int | float | None = None,
189
- multiple_of: int | float | None = None,
190
185
  alias: str | None = None,
191
186
  title: str | None = None,
192
187
  description: str | None = None,
193
188
  json_schema_extra: dict[str, Any] | None = None,
194
189
  examples: list[Any] | None = None,
195
190
  deprecated: bool | None = None,
196
- dump: Callable[[Any], Any] | None = None,
197
- validate: Callable[[Any], Any] | None = None,
198
191
  ) -> None: ...
199
- @overload
192
+ alias: Final[str | None]
193
+ title: Final[str | None]
194
+ description: Final[str | None]
195
+ examples: Final[list[Any] | None]
196
+ deprecated: Final[bool | None]
197
+ json_schema_extra: Final[dict[str, Any] | None]
198
+ def __rich_repr__(self) -> list[tuple[str, Any]]: ...
199
+
200
+ @final
201
+ class Serializer:
200
202
  def __init__(
201
203
  self,
202
204
  *,
203
- gt: int | float | None = None,
204
- le: int | float | None = None,
205
- multiple_of: int | float | None = None,
206
- alias: str | None = None,
207
- title: str | None = None,
208
- description: str | None = None,
209
- json_schema_extra: dict[str, Any] | None = None,
210
- examples: list[Any] | None = None,
211
- deprecated: bool | None = None,
205
+ load: Callable[[Any], Any] | None = None,
212
206
  dump: Callable[[Any], Any] | None = None,
213
- validate: Callable[[Any], Any] | None = None,
214
207
  ) -> None: ...
215
- @overload
208
+ load: Final[Callable[[Any], Any] | None]
209
+ dump: Final[Callable[[Any], Any] | None]
210
+
211
+ class Validator:
212
+ def __init__(self, fn: Callable[[Any], Any] | None = None) -> None: ...
213
+ def __call__(self, value: Any) -> None: ...
214
+
215
+ @final
216
+ class NumericValidator(Validator):
216
217
  def __init__(
217
218
  self,
218
219
  *,
220
+ gt: int | float | None = None,
219
221
  ge: int | float | None = None,
220
222
  lt: int | float | None = None,
223
+ le: int | float | None = None,
221
224
  multiple_of: int | float | None = None,
222
- alias: str | None = None,
223
- title: str | None = None,
224
- description: str | None = None,
225
- json_schema_extra: dict[str, Any] | None = None,
226
- examples: list[Any] | None = None,
227
- deprecated: bool | None = None,
228
- dump: Callable[[Any], Any] | None = None,
229
- validate: Callable[[Any], Any] | None = None,
230
225
  ) -> None: ...
231
- @overload
226
+ gt: Final[int | float | None]
227
+ ge: Final[int | float | None]
228
+ lt: Final[int | float | None]
229
+ le: Final[int | float | None]
230
+ multiple_of: Final[int | float | None]
231
+
232
+ @final
233
+ class StrValidator(Validator):
232
234
  def __init__(
233
235
  self,
234
236
  *,
235
- ge: int | float | None = None,
236
- le: int | float | None = None,
237
- multiple_of: int | float | None = None,
238
- alias: str | None = None,
239
- title: str | None = None,
240
- description: str | None = None,
241
- json_schema_extra: dict[str, Any] | None = None,
242
- examples: list[Any] | None = None,
243
- deprecated: bool | None = None,
244
- dump: Callable[[Any], Any] | None = None,
245
- validate: Callable[[Any], Any] | None = None,
237
+ pattern: str | None = None,
238
+ min_length: _NonNegativeInt | None = None,
239
+ max_length: _NonNegativeInt | None = None,
246
240
  ) -> None: ...
247
- # Other (string/datetime):
248
- @overload
241
+ pattern: Final[str | None]
242
+ min_length: Final[int | None]
243
+ max_length: Final[int | None]
244
+
245
+ @final
246
+ class BytesValidator(Validator):
249
247
  def __init__(
250
248
  self,
251
249
  *,
252
- pattern: str | None = None,
253
250
  min_length: _NonNegativeInt | None = None,
254
251
  max_length: _NonNegativeInt | None = None,
255
- tz: bool | None = None,
256
- alias: str | None = None,
257
- title: str | None = None,
258
- description: str | None = None,
259
- json_schema_extra: dict[str, Any] | None = None,
260
- examples: list[Any] | None = None,
261
- deprecated: bool | None = None,
262
- dump: Callable[[Any], Any] | None = None,
263
- validate: Callable[[Any], Any] | None = None,
264
252
  ) -> None: ...
265
- alias: Final[str | None]
266
- gt: Final[int | float | None]
267
- ge: Final[int | float | None]
268
- lt: Final[int | float | None]
269
- le: Final[int | float | None]
270
- multiple_of: Final[int | float | None]
271
- pattern: Final[str | None]
272
253
  min_length: Final[int | None]
273
254
  max_length: Final[int | None]
274
- tz: Final[int | None]
275
- title: Final[str | None]
276
- description: Final[str | None]
277
- examples: Final[list[Any] | None]
278
- deprecated: Final[bool | None]
279
- json_schema_extra: Final[dict[str, Any] | None]
280
- dump: Final[Callable[[Any], Any] | None]
281
- validate: Final[Callable[[Any], Any] | None]
282
- def __rich_repr__(self) -> list[tuple[str, Any]]: ...
255
+
256
+ @final
257
+ class CollectionValidator(Validator):
258
+ def __init__(
259
+ self,
260
+ *,
261
+ min_length: _NonNegativeInt | None = None,
262
+ max_length: _NonNegativeInt | None = None,
263
+ ) -> None: ...
264
+ min_length: Final[int | None]
265
+ max_length: Final[int | None]
266
+
267
+ @final
268
+ class TimezoneValidator(Validator):
269
+ def __init__(self, *, tz: bool) -> None: ...
270
+ tz: Final[bool]
283
271
 
284
272
  class FieldInfo(Struct):
285
273
  name: str
@@ -1,7 +1,7 @@
1
1
  from typing import Any, get_args
2
2
 
3
3
  from ._core import ( # type: ignore
4
- Field as _Field,
4
+ Serializer as _Serializer,
5
5
  )
6
6
  from ._core import ( # type: ignore
7
7
  _dump,
@@ -11,22 +11,22 @@ from ._core import ( # type: ignore
11
11
  )
12
12
 
13
13
 
14
- def _has_codec(ann):
15
- """True if the annotation carries a ``Field`` with ``dump``/``validate``."""
14
+ def _has_serializer(ann):
15
+ """True if the annotation carries a ``Serializer`` with ``load``/``dump``."""
16
16
  metadata = getattr(ann, "__metadata__", None)
17
17
  if metadata is not None:
18
18
  for meta in metadata:
19
- if isinstance(meta, _Field) and (
20
- meta.dump is not None or meta.validate is not None
19
+ if isinstance(meta, _Serializer) and (
20
+ meta.load is not None or meta.dump is not None
21
21
  ):
22
22
  return True
23
23
  supertype = getattr(ann, "__supertype__", None) # NewType
24
- if supertype is not None and _has_codec(supertype):
24
+ if supertype is not None and _has_serializer(supertype):
25
25
  return True
26
26
  value = getattr(ann, "__value__", None) # PEP 695 type alias
27
- if value is not None and _has_codec(value):
27
+ if value is not None and _has_serializer(value):
28
28
  return True
29
- return any(_has_codec(arg) for arg in get_args(ann))
29
+ return any(_has_serializer(arg) for arg in get_args(ann))
30
30
 
31
31
 
32
32
  class StructAdapter:
@@ -35,8 +35,8 @@ class StructAdapter:
35
35
  Useful when you want to validate or serialize plain Python types
36
36
  (e.g. ``list[int]``) without defining a full ``Struct`` subclass.
37
37
 
38
- ``Field(dump=...)`` / ``Field(validate=...)`` codecs are not supported on
39
- ``StructAdapter`` — annotations carrying one are rejected. Implement the
38
+ ``Serializer(load=...)`` / ``Serializer(dump=...)`` codecs are not supported
39
+ on ``StructAdapter`` — annotations carrying one are rejected. Implement the
40
40
  ``struct_dump`` / ``struct_validate`` protocol methods on the custom type,
41
41
  or use a ``Struct``.
42
42
 
@@ -49,11 +49,12 @@ class StructAdapter:
49
49
  __slots__ = ("_type",)
50
50
 
51
51
  def __init__(self, type: Any):
52
- if _has_codec(type):
52
+ if _has_serializer(type):
53
53
  raise TypeError(
54
- "`Field(dump=...)`/`Field(validate=...)` codecs are not supported "
55
- "on StructAdapter; define `struct_dump`/`struct_validate` methods "
56
- "on the custom type, or use a `Struct` instead"
54
+ "`Serializer(load=...)`/`Serializer(dump=...)` codecs are not "
55
+ "supported on StructAdapter; define `struct_dump`/"
56
+ "`struct_validate` methods on the custom type, or use a "
57
+ "`Struct` instead"
57
58
  )
58
59
  self._type = type
59
60