zodish 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.
- zodish-0.3.0/.github/workflows/publish.yml +142 -0
- zodish-0.3.0/.github/workflows/tests.yml +83 -0
- zodish-0.3.0/.gitignore +21 -0
- zodish-0.3.0/CHANGELOG.md +125 -0
- zodish-0.3.0/Cargo.lock +193 -0
- zodish-0.3.0/Cargo.toml +23 -0
- zodish-0.3.0/LICENSE +21 -0
- zodish-0.3.0/PKG-INFO +662 -0
- zodish-0.3.0/README.md +643 -0
- zodish-0.3.0/benchmarks/README.md +142 -0
- zodish-0.3.0/benchmarks/bench_compare.py +459 -0
- zodish-0.3.0/benchmarks/bench_parse.py +209 -0
- zodish-0.3.0/benchmarks/requirements.lock +23 -0
- zodish-0.3.0/benchmarks/results/2026-10-20-macos-arm64-rerun.json +1 -0
- zodish-0.3.0/benchmarks/results/2026-10-20-macos-arm64-rerun.md +72 -0
- zodish-0.3.0/benchmarks/results/2026-10-20-macos-arm64.json +1 -0
- zodish-0.3.0/benchmarks/results/2026-10-20-macos-arm64.md +68 -0
- zodish-0.3.0/benchmarks/results/README.md +115 -0
- zodish-0.3.0/benchmarks/summarize.py +115 -0
- zodish-0.3.0/docs/README.md +50 -0
- zodish-0.3.0/docs/explanation/architecture.md +131 -0
- zodish-0.3.0/docs/explanation/async-support.md +90 -0
- zodish-0.3.0/docs/explanation/missing-none-defaults.md +90 -0
- zodish-0.3.0/docs/explanation/type-semantics.md +160 -0
- zodish-0.3.0/docs/how-to/build-distributions.md +79 -0
- zodish-0.3.0/docs/how-to/contribute.md +91 -0
- zodish-0.3.0/docs/how-to/export-json-schema.md +114 -0
- zodish-0.3.0/docs/how-to/handle-errors.md +136 -0
- zodish-0.3.0/docs/how-to/handle-missing-values.md +108 -0
- zodish-0.3.0/docs/how-to/transform-and-refine.md +151 -0
- zodish-0.3.0/docs/how-to/use-codecs.md +180 -0
- zodish-0.3.0/docs/how-to/validate-data.md +173 -0
- zodish-0.3.0/docs/reference/api.md +219 -0
- zodish-0.3.0/docs/reference/errors.md +96 -0
- zodish-0.3.0/docs/reference/json-schema.md +135 -0
- zodish-0.3.0/docs/tutorials/get-started.md +188 -0
- zodish-0.3.0/examples/quickstart.py +38 -0
- zodish-0.3.0/examples/typing_checks.py +335 -0
- zodish-0.3.0/examples/verify_native.py +20 -0
- zodish-0.3.0/justfile +64 -0
- zodish-0.3.0/pyproject.toml +75 -0
- zodish-0.3.0/rust/lib.rs +2476 -0
- zodish-0.3.0/scripts/verify_dist.py +132 -0
- zodish-0.3.0/src/zodish/__init__.py +28 -0
- zodish-0.3.0/src/zodish/_native.pyi +20 -0
- zodish-0.3.0/src/zodish/py.typed +0 -0
- zodish-0.3.0/src/zodish/schemas.py +3183 -0
- zodish-0.3.0/tests/test_native.py +551 -0
- zodish-0.3.0/tests/test_schemas.py +2812 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
verify-version:
|
|
13
|
+
name: Verify version metadata
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: '3.14'
|
|
20
|
+
- name: Check manifest and release tag versions
|
|
21
|
+
env:
|
|
22
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
23
|
+
REF_NAME: ${{ github.ref_name }}
|
|
24
|
+
run: |
|
|
25
|
+
python - <<'PY'
|
|
26
|
+
import os
|
|
27
|
+
import tomllib
|
|
28
|
+
from pathlib import Path
|
|
29
|
+
|
|
30
|
+
pyproject = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8"))
|
|
31
|
+
cargo = tomllib.loads(Path("Cargo.toml").read_text(encoding="utf-8"))
|
|
32
|
+
project_version = pyproject["project"]["version"]
|
|
33
|
+
cargo_version = cargo["package"]["version"]
|
|
34
|
+
if project_version != cargo_version:
|
|
35
|
+
raise SystemExit(
|
|
36
|
+
f"version mismatch: pyproject.toml {project_version}, "
|
|
37
|
+
f"Cargo.toml {cargo_version}"
|
|
38
|
+
)
|
|
39
|
+
if os.environ["EVENT_NAME"] == "release":
|
|
40
|
+
tag_version = os.environ["REF_NAME"].removeprefix("v")
|
|
41
|
+
if tag_version != project_version:
|
|
42
|
+
raise SystemExit(
|
|
43
|
+
f"release tag {os.environ['REF_NAME']} does not match "
|
|
44
|
+
f"package version {project_version}"
|
|
45
|
+
)
|
|
46
|
+
print(f"version ok: {project_version}")
|
|
47
|
+
PY
|
|
48
|
+
|
|
49
|
+
build-sdist:
|
|
50
|
+
name: Build sdist
|
|
51
|
+
needs: verify-version
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@v4
|
|
55
|
+
- uses: actions/setup-python@v5
|
|
56
|
+
with:
|
|
57
|
+
python-version: '3.14'
|
|
58
|
+
- run: python -m pip install 'maturin>=1.15,<2'
|
|
59
|
+
- run: maturin sdist --out dist
|
|
60
|
+
- uses: actions/upload-artifact@v4
|
|
61
|
+
with:
|
|
62
|
+
name: dist-sdist
|
|
63
|
+
path: dist/*.tar.gz
|
|
64
|
+
|
|
65
|
+
build-wheels:
|
|
66
|
+
name: Build wheels (${{ matrix.os }} / ${{ matrix.target }} / ${{ matrix.manylinux }})
|
|
67
|
+
needs: verify-version
|
|
68
|
+
runs-on: ${{ matrix.os }}
|
|
69
|
+
strategy:
|
|
70
|
+
fail-fast: false
|
|
71
|
+
matrix:
|
|
72
|
+
include:
|
|
73
|
+
# manylinux (glibc)
|
|
74
|
+
- os: ubuntu-latest
|
|
75
|
+
target: x86_64
|
|
76
|
+
manylinux: auto
|
|
77
|
+
interpreter: python3.14
|
|
78
|
+
- os: ubuntu-latest
|
|
79
|
+
target: aarch64
|
|
80
|
+
manylinux: auto
|
|
81
|
+
interpreter: python3.14
|
|
82
|
+
# musllinux (Alpine / musl libc)
|
|
83
|
+
- os: ubuntu-latest
|
|
84
|
+
target: x86_64
|
|
85
|
+
manylinux: musllinux_1_2
|
|
86
|
+
interpreter: python3.14
|
|
87
|
+
- os: ubuntu-latest
|
|
88
|
+
target: aarch64
|
|
89
|
+
manylinux: musllinux_1_2
|
|
90
|
+
interpreter: python3.14
|
|
91
|
+
# macOS
|
|
92
|
+
- os: macos-latest
|
|
93
|
+
target: x86_64
|
|
94
|
+
manylinux: auto
|
|
95
|
+
interpreter: python3.14
|
|
96
|
+
- os: macos-latest
|
|
97
|
+
target: aarch64
|
|
98
|
+
manylinux: auto
|
|
99
|
+
interpreter: python3.14
|
|
100
|
+
# Windows
|
|
101
|
+
- os: windows-latest
|
|
102
|
+
target: x64
|
|
103
|
+
manylinux: auto
|
|
104
|
+
interpreter: python
|
|
105
|
+
steps:
|
|
106
|
+
- uses: actions/checkout@v4
|
|
107
|
+
- uses: actions/setup-python@v5
|
|
108
|
+
with:
|
|
109
|
+
python-version: '3.14'
|
|
110
|
+
- name: Build wheels
|
|
111
|
+
uses: PyO3/maturin-action@v1
|
|
112
|
+
with:
|
|
113
|
+
target: ${{ matrix.target }}
|
|
114
|
+
# abi3-py314: one stable-ABI wheel per platform covers Python 3.14+.
|
|
115
|
+
args: --release --locked --interpreter ${{ matrix.interpreter }} --out dist
|
|
116
|
+
manylinux: ${{ matrix.manylinux }}
|
|
117
|
+
- uses: actions/upload-artifact@v4
|
|
118
|
+
with:
|
|
119
|
+
name: dist-${{ matrix.os }}-${{ matrix.target }}-${{ matrix.manylinux }}
|
|
120
|
+
path: dist/*.whl
|
|
121
|
+
|
|
122
|
+
publish:
|
|
123
|
+
name: Publish to PyPI
|
|
124
|
+
needs: [build-sdist, build-wheels]
|
|
125
|
+
runs-on: ubuntu-latest
|
|
126
|
+
environment: pypi
|
|
127
|
+
permissions:
|
|
128
|
+
contents: read
|
|
129
|
+
id-token: write
|
|
130
|
+
steps:
|
|
131
|
+
- uses: actions/checkout@v4
|
|
132
|
+
- uses: actions/download-artifact@v4
|
|
133
|
+
with:
|
|
134
|
+
pattern: dist-*
|
|
135
|
+
merge-multiple: true
|
|
136
|
+
path: dist
|
|
137
|
+
- uses: actions/setup-python@v5
|
|
138
|
+
with:
|
|
139
|
+
python-version: '3.14'
|
|
140
|
+
- name: Verify distribution artifacts
|
|
141
|
+
run: python scripts/verify_dist.py dist
|
|
142
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
name: tests
|
|
2
|
+
on: [push, pull_request]
|
|
3
|
+
jobs:
|
|
4
|
+
lint:
|
|
5
|
+
runs-on: ubuntu-latest
|
|
6
|
+
steps:
|
|
7
|
+
- uses: actions/checkout@v4
|
|
8
|
+
- uses: actions/setup-python@v5
|
|
9
|
+
with:
|
|
10
|
+
python-version: '3.14'
|
|
11
|
+
- run: python -m pip install --group dev --group benchmark
|
|
12
|
+
- run: ruff check .
|
|
13
|
+
- run: mypy
|
|
14
|
+
test:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
strategy:
|
|
17
|
+
matrix:
|
|
18
|
+
python: ['3.14', '3.15']
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: ${{ matrix.python }}
|
|
24
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
25
|
+
with:
|
|
26
|
+
components: rustfmt, clippy
|
|
27
|
+
- run: cargo fmt --check
|
|
28
|
+
- run: cargo clippy --locked -- -D warnings
|
|
29
|
+
- run: python -m pip install .
|
|
30
|
+
- run: python -m unittest discover -s tests -v
|
|
31
|
+
- run: python examples/quickstart.py
|
|
32
|
+
- run: python benchmarks/bench_parse.py --smoke
|
|
33
|
+
- run: python -m pip install --group benchmark
|
|
34
|
+
- run: python benchmarks/bench_compare.py --check-only
|
|
35
|
+
- name: Exercise benchmark worker argument forwarding
|
|
36
|
+
run: >-
|
|
37
|
+
python benchmarks/bench_compare.py --library pydantic
|
|
38
|
+
--scenario object_success --processes 1 --values 1
|
|
39
|
+
--warmups 1 --min-time 0.001
|
|
40
|
+
package:
|
|
41
|
+
name: package (${{ matrix.os }})
|
|
42
|
+
runs-on: ${{ matrix.os }}
|
|
43
|
+
strategy:
|
|
44
|
+
fail-fast: false
|
|
45
|
+
matrix:
|
|
46
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
47
|
+
defaults:
|
|
48
|
+
run:
|
|
49
|
+
shell: bash
|
|
50
|
+
steps:
|
|
51
|
+
- uses: actions/checkout@v4
|
|
52
|
+
- uses: actions/setup-python@v5
|
|
53
|
+
with:
|
|
54
|
+
python-version: '3.14'
|
|
55
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
56
|
+
- run: python -m pip install 'maturin>=1.15,<2'
|
|
57
|
+
- run: maturin build --release --locked --interpreter python --out dist
|
|
58
|
+
- run: maturin sdist --out dist
|
|
59
|
+
- run: python scripts/verify_dist.py dist
|
|
60
|
+
- name: Smoke-test the wheel
|
|
61
|
+
run: |
|
|
62
|
+
python -m pip install --no-index --no-deps --force-reinstall dist/*.whl
|
|
63
|
+
python examples/verify_native.py
|
|
64
|
+
python -m unittest discover -s tests -v
|
|
65
|
+
python examples/quickstart.py
|
|
66
|
+
- name: Smoke-test the sdist
|
|
67
|
+
run: |
|
|
68
|
+
python -m pip uninstall -y zodish
|
|
69
|
+
python -m pip install --no-index --no-deps --no-cache-dir --no-build-isolation --force-reinstall dist/*.tar.gz
|
|
70
|
+
python examples/verify_native.py
|
|
71
|
+
python -m unittest discover -s tests -v
|
|
72
|
+
python examples/quickstart.py
|
|
73
|
+
- uses: actions/setup-python@v5
|
|
74
|
+
if: runner.os == 'Linux'
|
|
75
|
+
with:
|
|
76
|
+
python-version: '3.15'
|
|
77
|
+
- name: Smoke-test the abi3 wheel on Python 3.15
|
|
78
|
+
if: runner.os == 'Linux'
|
|
79
|
+
run: |
|
|
80
|
+
python -m pip install --no-index --no-deps --force-reinstall dist/*.whl
|
|
81
|
+
python examples/verify_native.py
|
|
82
|
+
python -m unittest discover -s tests -v
|
|
83
|
+
python examples/quickstart.py
|
zodish-0.3.0/.gitignore
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*.egg-info/
|
|
4
|
+
.venv/
|
|
5
|
+
.mypy_cache/
|
|
6
|
+
.ruff_cache/
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
target/
|
|
10
|
+
*.so
|
|
11
|
+
*.pyd
|
|
12
|
+
*.dylib
|
|
13
|
+
|
|
14
|
+
/.idea/
|
|
15
|
+
/.agents/
|
|
16
|
+
/.claude/
|
|
17
|
+
/.codex/
|
|
18
|
+
ai-agents-standards-v*
|
|
19
|
+
.mcp.json
|
|
20
|
+
AGENTS.md
|
|
21
|
+
CLAUDE.md
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.3.0] - 2026-10-21
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Arrays whose item schema is a primitive validator (string, integer, number,
|
|
15
|
+
boolean, none, or unknown) use a native fast path, and exact lists snapshot
|
|
16
|
+
through direct list iteration. A 1,000-integer parse improved from roughly
|
|
17
|
+
31 µs to 5.8 µs in the local release benchmark.
|
|
18
|
+
- Lazy schema factories resolve once per lazy node per parse instead of once
|
|
19
|
+
per visit, using a compact per-parse cache. Factories are still invoked again
|
|
20
|
+
on subsequent parses.
|
|
21
|
+
- Object traversal pre-reads declared field values without copying exact-shape
|
|
22
|
+
inputs, caches the unknown-key policy, and validates primitive fields without
|
|
23
|
+
constructing a path. Recursive trees improved from 18.8 µs to 9.0 µs in the
|
|
24
|
+
local release benchmark.
|
|
25
|
+
- Failure construction is cheaper: `ValidationError` formats its combined
|
|
26
|
+
message lazily, and native failures retain a GC-aware native issue bundle
|
|
27
|
+
until `.issues` is read. The first access materializes and caches the public
|
|
28
|
+
`Issue` objects without copying params or running dataclass initialization.
|
|
29
|
+
Checks that only need success or failure, including `validate()`, avoid both
|
|
30
|
+
raw and Python issue conversion. Object failure improved from 2.77 µs to
|
|
31
|
+
1.05 µs in the local release benchmark; inspecting the materialized issues
|
|
32
|
+
takes 2.29 µs.
|
|
33
|
+
- Constraint, literal, enum, and primitive type failures reuse native error
|
|
34
|
+
templates instead of rebuilding parameter dictionaries and messages. The
|
|
35
|
+
last-union branch improved from 1.17 µs to 0.69 µs locally.
|
|
36
|
+
- Callback async guards fast-path common exact synchronous result types before
|
|
37
|
+
falling back to `inspect.isawaitable` and `inspect.isasyncgen`. Refinement
|
|
38
|
+
callbacks improved from 0.32 µs to 0.14 µs in the local benchmark.
|
|
39
|
+
- Small array and tuple snapshots use inline storage for up to four items, and
|
|
40
|
+
lazy nodes check a last-resolved entry before scanning the per-parse cache.
|
|
41
|
+
Recursive trees improved from 9.2 µs to 9.0 µs locally.
|
|
42
|
+
- Object parsing skips the unknown-key scan and temporary known-key map when
|
|
43
|
+
the input contains no keys outside the shape, including when optional fields
|
|
44
|
+
are absent. Object success improved from 0.53 µs to 0.38 µs in the local
|
|
45
|
+
release benchmark.
|
|
46
|
+
|
|
47
|
+
### Added
|
|
48
|
+
|
|
49
|
+
- `Schema.parse_json()`, `.safe_parse_json()`, and `.validate_json()` accept
|
|
50
|
+
`str`, `bytes`, or `bytearray` JSON input. A native fast path validates
|
|
51
|
+
JSON-compatible objects and arrays with primitive leaves, numeric bounds and
|
|
52
|
+
multiples, literals and enums, nullable/optional wrappers, optional object
|
|
53
|
+
fields, and string/array length constraints. Other schemas fall back to
|
|
54
|
+
standard JSON decoding and normal validation. Invalid JSON reports
|
|
55
|
+
`invalid_format` with a `position`.
|
|
56
|
+
- CPython 3.15 support: the `abi3-py314` wheel runs on 3.15, CI covers 3.14 and
|
|
57
|
+
3.15, and the package metadata declares both versions.
|
|
58
|
+
- Bidirectional codecs through `z.codec(input_schema, output_schema, *,
|
|
59
|
+
decode=..., encode=...)`, with `.decode()`/`.encode()`,
|
|
60
|
+
`.safe_decode()`/`.safe_encode()`, reverse validation through containers, and
|
|
61
|
+
JSON Schema input/output selection. One-way operations such as transforms,
|
|
62
|
+
refinements, coercions, defaults, catches, pipes, preprocessors, and lazy
|
|
63
|
+
schemas make encoding unavailable.
|
|
64
|
+
- Built-in codecs: `z.codecs.iso_date()`, `iso_time()`, `iso_datetime()`,
|
|
65
|
+
`decimal()`, `json_text()`, `path()`, and `bytes_base64()` with standard or
|
|
66
|
+
URL-safe base64.
|
|
67
|
+
- Dataclass codecs through `z.codecs.dataclass(Cls, fields=None)`, mapping
|
|
68
|
+
encoded dictionaries to dataclass instances. Field schemas are inferred from
|
|
69
|
+
common type annotations, including nested dataclasses, lists, records, fixed
|
|
70
|
+
tuples, optional fields, and unions, and may be overridden per field.
|
|
71
|
+
Recursive dataclass cycles are rejected. Dataclass defaults may be omitted
|
|
72
|
+
from input, and input/output-mode JSON Schema describe the encoded and decoded
|
|
73
|
+
object shapes respectively.
|
|
74
|
+
- Public codec combinators: `z.codecs.array()`, `z.codecs.union()`,
|
|
75
|
+
`z.codecs.tuple()`, and codec `.record()`, `.optional()`, `.nullable()`,
|
|
76
|
+
`.nonoptional()`, `.nullish()` methods. Compound codecs now retain
|
|
77
|
+
output-side JSON Schema across nested dataclasses and containers.
|
|
78
|
+
- Exclusive numeric comparisons (`.gt()`, `.gte()`, `.lt()`, `.lte()`), exact
|
|
79
|
+
integer and tolerant float `.multiple_of()` checks, string
|
|
80
|
+
`.starts_with()`/`.ends_with()`/`.includes()` predicates, and `.ipv6()`.
|
|
81
|
+
- JSON Schema export for exclusive bounds, `multipleOf`, string predicate
|
|
82
|
+
patterns, and IPv6 formats, with multiple checks emitted through `allOf`.
|
|
83
|
+
- Fixed-length tuple typing: `z.tuple()` infers precise output tuples for up to
|
|
84
|
+
four items; larger tuples and tuples with a rest schema return
|
|
85
|
+
`tuple[Any, ...]`.
|
|
86
|
+
- Parse benchmarks covering successful and failing parses, a 1,000-element
|
|
87
|
+
array, union branch position, recursive schemas, and a refinement callback.
|
|
88
|
+
- Packaging CI that builds the wheel and sdist on Ubuntu, macOS, and Windows,
|
|
89
|
+
verifies artifact contents and version agreement, and installs and smoke-tests
|
|
90
|
+
each artifact.
|
|
91
|
+
|
|
92
|
+
## [0.2.0] - 2026-10-20
|
|
93
|
+
|
|
94
|
+
### Added
|
|
95
|
+
|
|
96
|
+
- Immutable, composable schemas for CPython 3.14+, with a Rust validation core
|
|
97
|
+
and a typed Python API.
|
|
98
|
+
- Primitive schemas: `z.string()`, `z.number()`, `z.integer()`, `z.boolean()`,
|
|
99
|
+
`z.none()`, `z.unknown()`, and `z.instance_of()`.
|
|
100
|
+
- String constraints and transforms (`.min()`, `.max()`, `.regex()`, `.email()`,
|
|
101
|
+
`.trim()`, `.lower()`, `.upper()`) and numeric constraints (`.min()`, `.max()`,
|
|
102
|
+
`.positive()`, `.nonnegative()`, `.int()`).
|
|
103
|
+
- Object schemas with `.strict()`, `.strip()`, `.passthrough()`, `.extend()`,
|
|
104
|
+
`.pick()`, `.omit()`, and `.partial()`, plus array, tuple, and record schemas.
|
|
105
|
+
- Choice schemas: `z.literal()`, `z.enum()`, `z.union()`, and `schema.or_()`.
|
|
106
|
+
- Composition through `.optional()`, `.nullable()`, `.nullish()`, `.default()`,
|
|
107
|
+
`.default_factory()`, `.refine()`, `.transform()`, `.pipe()`,
|
|
108
|
+
`z.preprocess()`, and `z.lazy()` for recursive schemas.
|
|
109
|
+
- `parse()` and `safe_parse()` with native-only evaluation, aggregated issues,
|
|
110
|
+
nested error paths, union branch details, and JSON-serializable
|
|
111
|
+
`ValidationError.to_dict()` output.
|
|
112
|
+
- Arbitrary-precision integer comparisons for bounds and literals, with
|
|
113
|
+
type-exact literals and no implicit coercion.
|
|
114
|
+
- `Schema[Out, In]` typing, a `py.typed` marker, and strict mypy coverage.
|
|
115
|
+
- Maturin wheel and sdist builds for the CPython 3.14+ stable ABI, with no
|
|
116
|
+
third-party runtime dependencies.
|
|
117
|
+
|
|
118
|
+
### Fixed
|
|
119
|
+
|
|
120
|
+
- Async callbacks, and callbacks returning awaitables, now raise `TypeError`
|
|
121
|
+
instead of being accepted as valid refinement results.
|
|
122
|
+
- Defaults are typed and validated as input values, matching runtime behavior
|
|
123
|
+
after a transform.
|
|
124
|
+
- A callback raising `ValidationError([])` now produces a `custom` issue
|
|
125
|
+
instead of being treated as success.
|
zodish-0.3.0/Cargo.lock
ADDED
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 4
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "heck"
|
|
7
|
+
version = "0.5.0"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "itoa"
|
|
13
|
+
version = "1.0.18"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
|
16
|
+
|
|
17
|
+
[[package]]
|
|
18
|
+
name = "libc"
|
|
19
|
+
version = "0.2.191"
|
|
20
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
21
|
+
checksum = "65cd87c9a6d60536580b316ad985726104730a5151c99845f2490428ef91240a"
|
|
22
|
+
|
|
23
|
+
[[package]]
|
|
24
|
+
name = "memchr"
|
|
25
|
+
version = "2.8.3"
|
|
26
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
27
|
+
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
|
28
|
+
|
|
29
|
+
[[package]]
|
|
30
|
+
name = "once_cell"
|
|
31
|
+
version = "1.21.4"
|
|
32
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
33
|
+
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
|
34
|
+
|
|
35
|
+
[[package]]
|
|
36
|
+
name = "portable-atomic"
|
|
37
|
+
version = "1.15.0"
|
|
38
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
39
|
+
checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85"
|
|
40
|
+
|
|
41
|
+
[[package]]
|
|
42
|
+
name = "proc-macro2"
|
|
43
|
+
version = "1.0.107"
|
|
44
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
45
|
+
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
|
|
46
|
+
dependencies = [
|
|
47
|
+
"unicode-ident",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[[package]]
|
|
51
|
+
name = "pyo3"
|
|
52
|
+
version = "0.30.1"
|
|
53
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
54
|
+
checksum = "229ca13b8a15bb0d1487b81ab975bfcd97513416499a8312011b6036e42e0de4"
|
|
55
|
+
dependencies = [
|
|
56
|
+
"libc",
|
|
57
|
+
"once_cell",
|
|
58
|
+
"portable-atomic",
|
|
59
|
+
"pyo3-build-config",
|
|
60
|
+
"pyo3-ffi",
|
|
61
|
+
"pyo3-macros",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
[[package]]
|
|
65
|
+
name = "pyo3-build-config"
|
|
66
|
+
version = "0.30.1"
|
|
67
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
68
|
+
checksum = "70130e2b6dd1ee589a8788026a429561ca5c40fa7a2fa7914c2282eddae24700"
|
|
69
|
+
dependencies = [
|
|
70
|
+
"target-lexicon",
|
|
71
|
+
]
|
|
72
|
+
|
|
73
|
+
[[package]]
|
|
74
|
+
name = "pyo3-ffi"
|
|
75
|
+
version = "0.30.1"
|
|
76
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
77
|
+
checksum = "5e7ff73c555c286d212d4ce7e5fbda845a973c4f61bd5f160f5f2c3c2a04d1c4"
|
|
78
|
+
dependencies = [
|
|
79
|
+
"libc",
|
|
80
|
+
"pyo3-build-config",
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
[[package]]
|
|
84
|
+
name = "pyo3-macros"
|
|
85
|
+
version = "0.30.1"
|
|
86
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
87
|
+
checksum = "c46d2e5862c7bb8207e3b639f713dda3c499933444784154c11d013c5a691b60"
|
|
88
|
+
dependencies = [
|
|
89
|
+
"proc-macro2",
|
|
90
|
+
"pyo3-macros-backend",
|
|
91
|
+
"quote",
|
|
92
|
+
"syn",
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
[[package]]
|
|
96
|
+
name = "pyo3-macros-backend"
|
|
97
|
+
version = "0.30.1"
|
|
98
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
99
|
+
checksum = "38b89f066f2ae72a2aef52d1537ca2fcd104440ebfadee06e97aa90738a25b9b"
|
|
100
|
+
dependencies = [
|
|
101
|
+
"heck",
|
|
102
|
+
"proc-macro2",
|
|
103
|
+
"quote",
|
|
104
|
+
"syn",
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
[[package]]
|
|
108
|
+
name = "quote"
|
|
109
|
+
version = "1.0.47"
|
|
110
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
111
|
+
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
|
|
112
|
+
dependencies = [
|
|
113
|
+
"proc-macro2",
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
[[package]]
|
|
117
|
+
name = "serde"
|
|
118
|
+
version = "1.0.229"
|
|
119
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
120
|
+
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
|
|
121
|
+
dependencies = [
|
|
122
|
+
"serde_core",
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
[[package]]
|
|
126
|
+
name = "serde_core"
|
|
127
|
+
version = "1.0.229"
|
|
128
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
129
|
+
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
|
|
130
|
+
dependencies = [
|
|
131
|
+
"serde_derive",
|
|
132
|
+
]
|
|
133
|
+
|
|
134
|
+
[[package]]
|
|
135
|
+
name = "serde_derive"
|
|
136
|
+
version = "1.0.229"
|
|
137
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
138
|
+
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
|
139
|
+
dependencies = [
|
|
140
|
+
"proc-macro2",
|
|
141
|
+
"quote",
|
|
142
|
+
"syn",
|
|
143
|
+
]
|
|
144
|
+
|
|
145
|
+
[[package]]
|
|
146
|
+
name = "serde_json"
|
|
147
|
+
version = "1.0.154"
|
|
148
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
149
|
+
checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6"
|
|
150
|
+
dependencies = [
|
|
151
|
+
"itoa",
|
|
152
|
+
"memchr",
|
|
153
|
+
"serde",
|
|
154
|
+
"serde_core",
|
|
155
|
+
"zmij",
|
|
156
|
+
]
|
|
157
|
+
|
|
158
|
+
[[package]]
|
|
159
|
+
name = "syn"
|
|
160
|
+
version = "3.0.9"
|
|
161
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
162
|
+
checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b"
|
|
163
|
+
dependencies = [
|
|
164
|
+
"proc-macro2",
|
|
165
|
+
"quote",
|
|
166
|
+
"unicode-ident",
|
|
167
|
+
]
|
|
168
|
+
|
|
169
|
+
[[package]]
|
|
170
|
+
name = "target-lexicon"
|
|
171
|
+
version = "0.13.5"
|
|
172
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
173
|
+
checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
|
174
|
+
|
|
175
|
+
[[package]]
|
|
176
|
+
name = "unicode-ident"
|
|
177
|
+
version = "1.0.27"
|
|
178
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
179
|
+
checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563"
|
|
180
|
+
|
|
181
|
+
[[package]]
|
|
182
|
+
name = "zmij"
|
|
183
|
+
version = "1.0.23"
|
|
184
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
185
|
+
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
|
186
|
+
|
|
187
|
+
[[package]]
|
|
188
|
+
name = "zodish-core"
|
|
189
|
+
version = "0.3.0"
|
|
190
|
+
dependencies = [
|
|
191
|
+
"pyo3",
|
|
192
|
+
"serde_json",
|
|
193
|
+
]
|
zodish-0.3.0/Cargo.toml
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "zodish-core"
|
|
3
|
+
version = "0.3.0"
|
|
4
|
+
edition = "2024"
|
|
5
|
+
rust-version = "1.85"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
description = "Rust validation engine for the Zodish Python package"
|
|
8
|
+
authors = ["Aleksandr Pavlov <ckidoz@gmail.com>"]
|
|
9
|
+
repository = "https://github.com/kidoz/zodish"
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
|
|
12
|
+
[lib]
|
|
13
|
+
name = "_native"
|
|
14
|
+
crate-type = ["cdylib"]
|
|
15
|
+
path = "rust/lib.rs"
|
|
16
|
+
|
|
17
|
+
[dependencies]
|
|
18
|
+
pyo3 = { version = "=0.30.1", features = ["abi3-py314"] }
|
|
19
|
+
serde_json = "1.0"
|
|
20
|
+
|
|
21
|
+
[profile.release]
|
|
22
|
+
lto = "thin"
|
|
23
|
+
codegen-units = 1
|
zodish-0.3.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Aleksandr Pavlov <ckidoz@gmail.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|