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.
- {structtype-0.2.0 → structtype-0.3.0}/AGENTS.md +1 -1
- {structtype-0.2.0 → structtype-0.3.0}/MANIFEST.in +0 -1
- {structtype-0.2.0 → structtype-0.3.0}/Makefile +4 -0
- {structtype-0.2.0/src/structtype.egg-info → structtype-0.3.0}/PKG-INFO +1 -1
- {structtype-0.2.0 → structtype-0.3.0}/pyproject.toml +9 -0
- {structtype-0.2.0 → structtype-0.3.0}/setup.py +15 -9
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype/__init__.py +2 -2
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype/__init__.pyi +30 -25
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype/_adapter.py +31 -15
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype/_core.c +562 -741
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype/_inspect.py +57 -4
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype/_json_schema.py +12 -7
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype/_utils.py +29 -1
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype/_version.py +2 -2
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype/common.h +2 -0
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype/ryu.h +1 -1
- {structtype-0.2.0 → structtype-0.3.0/src/structtype.egg-info}/PKG-INFO +1 -1
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype.egg-info/SOURCES.txt +1 -1
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_JSONTestSuite.py +3 -3
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_check.py +3 -40
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_constraints.py +3 -3
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_inspect.py +19 -0
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_json.py +252 -252
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_msgspec.py +1 -2
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_schema.py +123 -0
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_struct.py +7 -2
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_struct_meta.py +13 -13
- structtype-0.3.0/uv.lock +1490 -0
- structtype-0.2.0/.cibuildwheel.toml +0 -4
- {structtype-0.2.0 → structtype-0.3.0}/LICENSE +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/README.md +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/setup.cfg +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype/atof.h +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype/atof_consts.h +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype/itoa.h +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype/py.typed +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype.egg-info/dependency_links.txt +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/src/structtype.egg-info/top_level.txt +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/tests/__init__.py +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/__init__.py +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/conftest.py +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_adapter.py +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_cpylint.py +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_free_threading.py +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_pydantic.py +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_raw.py +0 -0
- {structtype-0.2.0 → structtype-0.3.0}/tests/unit/test_utils.py +0 -0
- {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(
|
|
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
|
|
|
@@ -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
|
|
@@ -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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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,
|
|
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,
|
|
6
|
+
from typing_extensions import Buffer, Self, dataclass_transform
|
|
19
7
|
|
|
20
|
-
from . import
|
|
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) ->
|
|
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"]
|
|
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(
|
|
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
|
-
|
|
133
|
-
|
|
134
|
-
|
|
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"]
|
|
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(
|
|
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
|
|
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
|
|
35
|
+
return _json_decode(buf, type=self._type, strict=strict, dec_hook=dec_hook)
|
|
36
36
|
|
|
37
|
-
def struct_dump_json(
|
|
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
|
|
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
|
|
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(
|
|
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
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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(
|
|
110
|
-
"
|
|
111
|
-
|
|
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
|
+
)
|