structtype 0.2.0__tar.gz → 0.3.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 (48) hide show
  1. {structtype-0.2.0 → structtype-0.3.0}/AGENTS.md +1 -1
  2. {structtype-0.2.0 → structtype-0.3.0}/MANIFEST.in +0 -1
  3. {structtype-0.2.0 → structtype-0.3.0}/Makefile +4 -0
  4. {structtype-0.2.0/src/structtype.egg-info → structtype-0.3.0}/PKG-INFO +1 -1
  5. {structtype-0.2.0 → structtype-0.3.0}/pyproject.toml +9 -0
  6. {structtype-0.2.0 → structtype-0.3.0}/setup.py +15 -9
  7. {structtype-0.2.0 → structtype-0.3.0}/src/structtype/__init__.py +2 -2
  8. {structtype-0.2.0 → structtype-0.3.0}/src/structtype/__init__.pyi +30 -25
  9. {structtype-0.2.0 → structtype-0.3.0}/src/structtype/_adapter.py +31 -15
  10. {structtype-0.2.0 → structtype-0.3.0}/src/structtype/_core.c +562 -741
  11. {structtype-0.2.0 → structtype-0.3.0}/src/structtype/_inspect.py +57 -4
  12. {structtype-0.2.0 → structtype-0.3.0}/src/structtype/_json_schema.py +12 -7
  13. {structtype-0.2.0 → structtype-0.3.0}/src/structtype/_utils.py +29 -1
  14. {structtype-0.2.0 → structtype-0.3.0}/src/structtype/_version.py +2 -2
  15. {structtype-0.2.0 → structtype-0.3.0}/src/structtype/common.h +2 -0
  16. {structtype-0.2.0 → structtype-0.3.0}/src/structtype/ryu.h +1 -1
  17. {structtype-0.2.0 → structtype-0.3.0/src/structtype.egg-info}/PKG-INFO +1 -1
  18. {structtype-0.2.0 → structtype-0.3.0}/src/structtype.egg-info/SOURCES.txt +1 -1
  19. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_JSONTestSuite.py +3 -3
  20. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_check.py +3 -40
  21. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_constraints.py +3 -3
  22. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_inspect.py +19 -0
  23. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_json.py +252 -252
  24. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_msgspec.py +1 -2
  25. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_schema.py +123 -0
  26. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_struct.py +7 -2
  27. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_struct_meta.py +13 -13
  28. structtype-0.3.0/uv.lock +1490 -0
  29. structtype-0.2.0/.cibuildwheel.toml +0 -4
  30. {structtype-0.2.0 → structtype-0.3.0}/LICENSE +0 -0
  31. {structtype-0.2.0 → structtype-0.3.0}/README.md +0 -0
  32. {structtype-0.2.0 → structtype-0.3.0}/setup.cfg +0 -0
  33. {structtype-0.2.0 → structtype-0.3.0}/src/structtype/atof.h +0 -0
  34. {structtype-0.2.0 → structtype-0.3.0}/src/structtype/atof_consts.h +0 -0
  35. {structtype-0.2.0 → structtype-0.3.0}/src/structtype/itoa.h +0 -0
  36. {structtype-0.2.0 → structtype-0.3.0}/src/structtype/py.typed +0 -0
  37. {structtype-0.2.0 → structtype-0.3.0}/src/structtype.egg-info/dependency_links.txt +0 -0
  38. {structtype-0.2.0 → structtype-0.3.0}/src/structtype.egg-info/top_level.txt +0 -0
  39. {structtype-0.2.0 → structtype-0.3.0}/tests/__init__.py +0 -0
  40. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/__init__.py +0 -0
  41. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/conftest.py +0 -0
  42. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_adapter.py +0 -0
  43. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_cpylint.py +0 -0
  44. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_free_threading.py +0 -0
  45. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_pydantic.py +0 -0
  46. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_raw.py +0 -0
  47. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_utils.py +0 -0
  48. {structtype-0.2.0 → structtype-0.3.0}/tests/unit/utils.py +0 -0
@@ -49,7 +49,7 @@ All commands go through `make`.
49
49
  - `obj.struct_dump_json(*, enc_hook=None, decimal_format=None, uuid_format=None, order=None)` — serialize to JSON bytes
50
50
  - `obj.struct_dump()` — convert to built-in Python types (uses `encode_name` for keys)
51
51
  - `obj.struct_force_setattr(name, value)` — set attr on frozen struct
52
- - `obj.struct_validate_self(*, strict=True, dec_hook=None)` — validate field values against types + constraints
52
+ - `obj.struct_validate_self()` — validate field values against types + constraints
53
53
  - `cls.struct_validate_json(buf, *, strict=True, dec_hook=None)` — deserialize from JSON
54
54
  - `cls.struct_validate(obj, *, strict=True, from_attributes=False, dec_hook=None)` — convert built-in types to struct
55
55
 
@@ -5,4 +5,3 @@ prune docs
5
5
  prune examples
6
6
  prune scripts
7
7
  exclude .*
8
- include .cibuildwheel.toml
@@ -13,6 +13,10 @@ docs: ## build docs
13
13
  rm -rf .doctrees site
14
14
  uv run --group docs sphinx-build -d .doctrees -b html docs site --fail-on-warning
15
15
 
16
+ .PHONY: wheels
17
+ wheels: ## build wheels
18
+ uvx --from cibuildwheel==4.1.1 cibuildwheel
19
+
16
20
  ##@ Quality
17
21
  .PHONY: test-cov
18
22
  test-cov: ## Run tests with coverage
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: structtype
3
- Version: 0.2.0
3
+ Version: 0.3.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
@@ -80,3 +80,12 @@ parentdir_prefix_version = "structtype-"
80
80
 
81
81
  [tool.uv.config-settings]
82
82
  editable_mode = "compat"
83
+
84
+ [tool.cibuildwheel]
85
+ build = "cp3*"
86
+ skip = ["pp*", "*-manylinux_i686", "*-musllinux*", "*-win32"]
87
+ enable = ["cpython-prerelease"]
88
+ test-command = "pip install pytest>=9 && pytest {project}/tests"
89
+
90
+ [tool.ruff]
91
+ target-version = "py310"
@@ -36,6 +36,12 @@ if DEBUG:
36
36
  extra_compile_args.extend(["-O0", "-g", "-UNDEBUG"])
37
37
  elif sys.platform != "win32":
38
38
  extra_compile_args.extend(["-g0"])
39
+ extra_compile_args.extend([
40
+ "-Wextra",
41
+ "-Wno-unused-parameter",
42
+ "-Wno-missing-field-initializers",
43
+ "-Wno-cast-function-type",
44
+ ])
39
45
  if sys.platform == "darwin" and platform.machine().lower() == "arm64":
40
46
  extra_compile_args.extend(["-flto=thin"])
41
47
  extra_link_args.extend(["-flto=thin"])
@@ -53,15 +59,15 @@ libraries = []
53
59
  if sys.platform != "win32":
54
60
  libraries.append("m")
55
61
 
56
- ext_modules = [
57
- Extension(
58
- "structtype._core",
59
- [os.path.join("src", "structtype", "_core.c")],
60
- libraries=libraries,
61
- extra_compile_args=extra_compile_args,
62
- extra_link_args=extra_link_args,
63
- )
64
- ]
62
+ ext_modules = [
63
+ Extension(
64
+ "structtype._core",
65
+ [os.path.join("src", "structtype", "_core.c")],
66
+ libraries=libraries,
67
+ extra_compile_args=extra_compile_args,
68
+ extra_link_args=extra_link_args,
69
+ )
70
+ ]
65
71
 
66
72
  setup(
67
73
  ext_modules=ext_modules,
@@ -1,3 +1,4 @@
1
+ from ._adapter import StrAdapter, StructAdapter
1
2
  from ._core import (
2
3
  NODEFAULT,
3
4
  UNSET,
@@ -11,7 +12,6 @@ from ._core import (
11
12
  UnsetType,
12
13
  ValidationError,
13
14
  )
14
- from ._adapter import StrAdapter, StructAdapter
15
15
  from ._inspect import FieldInfo, fields
16
- from ._json_schema import json_schema, json_schema_dump, json_schema_components
16
+ from ._json_schema import json_schema, json_schema_components, json_schema_dump
17
17
  from ._version import __version__
@@ -1,23 +1,11 @@
1
1
  import enum
2
2
  from collections.abc import Callable, Iterable, Iterator, Mapping
3
3
  from inspect import Signature
4
- from typing import (
5
- Any,
6
- ClassVar,
7
- Final,
8
- Literal,
9
- Optional,
10
- Tuple,
11
- Type,
12
- TypeVar,
13
- Union,
14
- final,
15
- overload,
16
- )
4
+ from typing import Any, ClassVar, Final, Literal, TypeAlias, TypeVar, final, overload
17
5
 
18
- from typing_extensions import Buffer, Self, TypeAlias, dataclass_transform
6
+ from typing_extensions import Buffer, Self, dataclass_transform
19
7
 
20
- from . import _inspect
8
+ from . import StructConfig
21
9
 
22
10
  # PEP 673 explicitly rejects using Self in metaclass definitions:
23
11
  # https://peps.python.org/pep-0673/#valid-locations-for-self
@@ -34,7 +22,7 @@ class StructMeta(type):
34
22
  @property
35
23
  def __signature__(self) -> Signature: ...
36
24
  @property
37
- def __struct_config__(self) -> structs.StructConfig: ...
25
+ def __struct_config__(self) -> StructConfig: ...
38
26
  def __new__(
39
27
  mcls: type[_SM],
40
28
  name: str,
@@ -85,6 +73,7 @@ class Struct(metaclass=StructMeta):
85
73
  __struct_fields__: ClassVar[tuple[str, ...]]
86
74
  __struct_config__: ClassVar[StructConfig]
87
75
  __struct_encode_fields__: ClassVar[tuple[str, ...]]
76
+ __struct_defaults__: ClassVar[tuple[Any, ...]]
88
77
  __match_args__: ClassVar[tuple[str, ...]]
89
78
  # A default __init__ so that Structs with unknown field types
90
79
  # won't error on every call to `__init__`
@@ -114,24 +103,30 @@ class Struct(metaclass=StructMeta):
114
103
  validate_on_init: bool = False,
115
104
  ) -> None: ...
116
105
  def __rich_repr__(self) -> list[tuple[str, Any]]: ...
106
+ def __copy__(self) -> Self: ...
107
+ def __reduce__(self) -> tuple: ...
117
108
  def __replace__(self, **changes: Any) -> Self: ...
118
109
  def __iter__(self) -> Iterator[tuple[str, Any]]: ...
119
110
  def struct_dump_json(
120
111
  self,
121
112
  *,
122
113
  enc_hook: Callable[[Any], Any] | None = None,
123
- decimal_format: Literal["string", "number"] | Callable[[Any], Any] | None = None,
114
+ decimal_format: Literal["string", "number"]
115
+ | Callable[[Any], Any]
116
+ | None = None,
124
117
  uuid_format: Literal["canonical", "hex"] | None = None,
125
118
  order: Literal["deterministic", "sorted"] | None = None,
126
119
  ) -> bytes: ...
127
- def struct_dump(self) -> dict[str, Any]: ...
128
- def struct_force_setattr(self, name: str, value: Any) -> None: ...
129
- def struct_validate_self(
120
+ def struct_dump(
130
121
  self,
131
122
  *,
132
- strict: bool = True,
133
- dec_hook: Callable[[type[Any], Any], Any] | None = None,
134
- ) -> None: ...
123
+ enc_hook: Callable[[Any], Any] | None = None,
124
+ order: Literal["deterministic", "sorted"] | None = None,
125
+ str_keys: bool = False,
126
+ builtin_types: Iterable[type] | None = None,
127
+ ) -> dict[str, Any] | list[Any]: ...
128
+ def struct_force_setattr(self, name: str, value: Any) -> None: ...
129
+ def struct_validate_self(self) -> None: ...
135
130
  @classmethod
136
131
  def struct_validate_json(
137
132
  cls: type[_T],
@@ -321,7 +316,9 @@ class StructAdapter:
321
316
  obj: Any,
322
317
  *,
323
318
  enc_hook: Callable[[Any], Any] | None = None,
324
- decimal_format: Literal["string", "number"] | Callable[[Any], Any] | None = None,
319
+ decimal_format: Literal["string", "number"]
320
+ | Callable[[Any], Any]
321
+ | None = None,
325
322
  uuid_format: Literal["canonical", "hex"] | None = None,
326
323
  order: Literal["deterministic", "sorted"] | None = None,
327
324
  ) -> bytes: ...
@@ -333,7 +330,15 @@ class StructAdapter:
333
330
  dec_hook: Callable[[type[Any], Any], Any] | None = None,
334
331
  from_attributes: bool = False,
335
332
  ) -> Any: ...
336
- def struct_dump(self, obj: Any) -> Any: ...
333
+ def struct_dump(
334
+ self,
335
+ obj: Any,
336
+ *,
337
+ enc_hook: Callable[[Any], Any] | None = None,
338
+ order: Literal["deterministic", "sorted"] | None = None,
339
+ str_keys: bool = False,
340
+ builtin_types: Iterable[type] | None = None,
341
+ ) -> Any: ...
337
342
 
338
343
  class StrAdapter:
339
344
  def __new__(cls, type: type[Any]) -> type[str]: ...
@@ -1,6 +1,6 @@
1
1
  from typing import Any
2
2
 
3
- from ._core import _convert, json_decode, json_encode
3
+ from ._core import _dump, _json_decode, _json_encode, _validate
4
4
 
5
5
 
6
6
  class StructAdapter:
@@ -32,9 +32,11 @@ class StructAdapter:
32
32
  dec_hook : callable, optional
33
33
  A callback for customizing decoding of specific types.
34
34
  """
35
- return json_decode(buf, type=self._type, strict=strict, dec_hook=dec_hook)
35
+ return _json_decode(buf, type=self._type, strict=strict, dec_hook=dec_hook)
36
36
 
37
- def struct_dump_json(self, obj, *, enc_hook=None, decimal_format=None, uuid_format=None, order=None):
37
+ def struct_dump_json(
38
+ self, obj, *, enc_hook=None, decimal_format=None, uuid_format=None, order=None
39
+ ):
38
40
  """Encode a validated object to JSON bytes.
39
41
 
40
42
  Parameters
@@ -50,7 +52,13 @@ class StructAdapter:
50
52
  order : str, optional
51
53
  Determines key ordering in JSON objects.
52
54
  """
53
- return json_encode(obj, enc_hook=enc_hook, decimal_format=decimal_format, uuid_format=uuid_format, order=order)
55
+ return _json_encode(
56
+ obj,
57
+ enc_hook=enc_hook,
58
+ decimal_format=decimal_format,
59
+ uuid_format=uuid_format,
60
+ order=order,
61
+ )
54
62
 
55
63
  def struct_validate(
56
64
  self, obj, *, strict=True, dec_hook=None, from_attributes=False
@@ -68,7 +76,7 @@ class StructAdapter:
68
76
  from_attributes : bool, optional
69
77
  If True, accept objects with attributes instead of dict keys.
70
78
  """
71
- return _convert(
79
+ return _validate(
72
80
  obj,
73
81
  self._type,
74
82
  strict=strict,
@@ -76,13 +84,17 @@ class StructAdapter:
76
84
  from_attributes=from_attributes,
77
85
  )
78
86
 
79
- def struct_dump(self, obj):
87
+ def struct_dump(
88
+ self, obj, *, enc_hook=None, order=None, str_keys=False, builtin_types=None
89
+ ):
80
90
  """Convert a validated object to built-in Python types (``dict``, ``list``, etc.)."""
81
- if hasattr(obj, "struct_dump"):
82
- return obj.struct_dump()
83
- if hasattr(obj, "model_dump"):
84
- return obj.model_dump()
85
- return obj
91
+ return _dump(
92
+ obj,
93
+ builtin_types=builtin_types,
94
+ str_keys=str_keys,
95
+ enc_hook=enc_hook,
96
+ order=order,
97
+ )
86
98
 
87
99
 
88
100
  class StrAdapter:
@@ -106,7 +118,11 @@ class StrAdapter:
106
118
  __slots__ = ()
107
119
 
108
120
  def __new__(cls, typ):
109
- return type(f"_Wrapped_{typ.__name__}", (str,), {
110
- "__slots__": (),
111
- "__new__": lambda self, v: str.__new__(self, str(typ(v))),
112
- })
121
+ return type(
122
+ f"_Wrapped_{typ.__name__}",
123
+ (str,),
124
+ {
125
+ "__slots__": (),
126
+ "__new__": lambda self, v: str.__new__(self, str(typ(v))),
127
+ },
128
+ )