diff --git a/.github/actions/build-pgo-wheel/action.yml b/.github/actions/build-pgo-wheel/action.yml index 0e0ee4e99..ca910b298 100644 --- a/.github/actions/build-pgo-wheel/action.yml +++ b/.github/actions/build-pgo-wheel/action.yml @@ -14,11 +14,6 @@ outputs: runs: using: "composite" steps: - - name: prepare self schema - shell: bash - # generate up front so that we don't have to do this inside the docker container - run: uv run python generate_self_schema.py - - name: prepare profiling directory shell: bash # making this ahead of the compile ensures that the local user can write to this diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7ba7247a2..8d33e7dfe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,49 +14,49 @@ env: jobs: coverage: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: install rust nightly - uses: dtolnay/rust-toolchain@nightly - - - id: cache-rust - name: cache rust - uses: Swatinem/rust-cache@v2 - - - run: cargo install rustfilt coverage-prepare - if: steps.cache-rust.outputs.cache-hit != 'true' - - - run: rustup component add llvm-tools-preview + # rust-nightly used for `#[coverage(off)]` + - uses: dtolnay/rust-toolchain@nightly + - uses: Swatinem/rust-cache@v2 + - uses: taiki-e/install-action@cargo-llvm-cov - name: install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 - name: install deps run: uv sync --group testing - run: rustc --version --verbose - - run: make build-dev + - run: | + source <(cargo llvm-cov show-env --export-prefix) + cargo llvm-cov clean --workspace --profraw-only + make build-dev env: RUST_BACKTRACE: 1 RUSTFLAGS: '-C instrument-coverage' - run: uv pip freeze - - run: uv run coverage run -m pytest + - run: uv run coverage run -m pytest --junitxml=junit.xml -o junit_family=legacy - run: ls -lha - run: uv run coverage xml - - run: coverage-prepare lcov python/pydantic_core/*.so + - run: | + source <(cargo llvm-cov show-env --export-prefix) + cargo llvm-cov --codecov --output-path=codecov.json - uses: codecov/codecov-action@v5 + with: + files: codecov.json + + - uses: codecov/test-results-action@v1 - # See https://github.com/PyO3/pyo3/discussions/2781 - # tests intermittently segfault with pypy and cpython 3.7 when using `coverage run ...`, hence separate job test-python: name: test ${{ matrix.python-version }} strategy: @@ -68,9 +68,10 @@ jobs: - '3.11' - '3.12' - '3.13' - - '3.13t' - - 'pypy3.9' + - '3.14' + - '3.14t' - 'pypy3.10' + - 'pypy3.11' runs-on: ubuntu-latest @@ -89,7 +90,7 @@ jobs: key: test-v3 - name: install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: python-version: ${{ matrix.python-version }} @@ -127,7 +128,7 @@ jobs: uses: Swatinem/rust-cache@v2 - name: install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 - name: install deps run: uv sync --group testing @@ -150,7 +151,7 @@ jobs: - uses: actions/checkout@v4 - name: install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 - name: install deps run: uv sync --group testing @@ -193,7 +194,7 @@ jobs: - uses: actions/checkout@v4 - name: install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: python-version: ${{ matrix.python-version }} @@ -232,7 +233,7 @@ jobs: uses: Swatinem/rust-cache@v2 - name: install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 - name: install deps run: | @@ -274,7 +275,7 @@ jobs: node-version: '18' - name: install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 - name: install deps run: | @@ -334,7 +335,7 @@ jobs: actions-cache-folder: emsdk-cache - name: install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 - name: install deps run: uv sync --group wasm @@ -410,19 +411,19 @@ jobs: - os: linux manylinux: auto target: armv7 - interpreter: 3.9 3.10 3.11 3.12 3.13 + interpreter: 3.9 3.10 3.11 3.12 3.13 3.14 - os: linux manylinux: auto target: ppc64le - interpreter: 3.9 3.10 3.11 3.12 3.13 + interpreter: 3.9 3.10 3.11 3.12 3.13 3.14 - os: linux manylinux: auto target: s390x - interpreter: 3.9 3.10 3.11 3.12 3.13 + interpreter: 3.9 3.10 3.11 3.12 3.13 3.14 - os: linux manylinux: auto target: x86_64 - interpreter: pypy3.9 pypy3.10 pypy3.11 + interpreter: pypy3.10 pypy3.11 # musllinux - os: linux @@ -442,7 +443,7 @@ jobs: target: x86_64 - os: macos target: aarch64 - interpreter: 3.9 pypy3.9 pypy3.10 pypy3.11 + interpreter: 3.9 pypy3.10 pypy3.11 # windows; # x86_64 pypy builds are not PGO optimized @@ -450,14 +451,14 @@ jobs: # aarch64 only 3.11 and up, also not PGO optimized - os: windows target: x86_64 - interpreter: pypy3.9 pypy3.10 pypy3.11 + interpreter: pypy3.10 pypy3.11 - os: windows target: i686 python-architecture: x86 - interpreter: 3.9 3.10 3.11 3.12 3.13 + interpreter: 3.9 3.10 3.11 3.12 3.13 3.14 - os: windows target: aarch64 - interpreter: 3.11 3.12 3.13 + interpreter: 3.11 3.12 3.13 3.14 exclude: # See above; disabled for now. @@ -476,15 +477,12 @@ jobs: - run: pip install -U twine 'ruff==0.5.0' typing_extensions - # generate self-schema now, so we don't have to do so inside docker in maturin build - - run: python generate_self_schema.py - - name: build wheels uses: PyO3/maturin-action@v1 with: target: ${{ matrix.target }} manylinux: ${{ matrix.manylinux }} - args: --release --out dist --interpreter ${{ matrix.interpreter || '3.9 3.10 3.11 3.12 3.13 pypy3.9 pypy3.10 pypy3.11' }} + args: --release --out dist --interpreter ${{ matrix.interpreter || '3.9 3.10 3.11 3.12 3.13 3.14 pypy3.10 pypy3.11' }} rust-toolchain: stable docker-options: -e CI @@ -505,7 +503,7 @@ jobs: fail-fast: false matrix: os: [linux, windows, macos] - interpreter: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.13t'] + interpreter: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.13t', '3.14', '3.14t'] include: # standard runners with override for macos arm - os: linux @@ -525,7 +523,7 @@ jobs: - uses: actions/checkout@v4 - name: install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: python-version: ${{ matrix.interpreter }} @@ -605,7 +603,7 @@ jobs: merge-multiple: true path: dist - - uses: uraimo/run-on-arch-action@v3.0.0 + - uses: uraimo/run-on-arch-action@v3.0.1 name: install & test with: arch: ${{ matrix.target }} @@ -645,7 +643,7 @@ jobs: - uses: actions/checkout@v4 - name: install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 - name: get dist artifacts uses: actions/download-artifact@v4 @@ -660,21 +658,22 @@ jobs: release: needs: [test-builds-arch, test-builds-os, build-sdist, check] - if: success() && startsWith(github.ref, 'refs/tags/') + if: always() && startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest + environment: + name: release + + permissions: + id-token: write + steps: - uses: actions/checkout@v4 - - name: set up python - uses: actions/setup-python@v5 - with: - python-version: '3.13' - - - run: pip install -U twine + - uses: astral-sh/setup-uv@v6 - name: check package version - run: python .github/check_version.py + run: uv run .github/check_version.py - name: get dist artifacts uses: actions/download-artifact@v4 @@ -683,13 +682,7 @@ jobs: merge-multiple: true path: dist - - run: twine check --strict dist/* - - - name: upload to pypi - run: twine upload dist/* - env: - TWINE_USERNAME: __token__ - TWINE_PASSWORD: ${{ secrets.pypi_token }} + - run: uv publish --trusted-publishing always - name: get wasm dist artifacts uses: actions/download-artifact@v4 diff --git a/.github/workflows/codspeed.yml b/.github/workflows/codspeed.yml index 3a4f2302a..03ba7a657 100644 --- a/.github/workflows/codspeed.yml +++ b/.github/workflows/codspeed.yml @@ -26,7 +26,7 @@ jobs: python-version: ${{ env.UV_PYTHON}} - name: install uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v6 with: enable-cache: true diff --git a/.gitignore b/.gitignore index 103281879..03ef0dcba 100644 --- a/.gitignore +++ b/.gitignore @@ -34,7 +34,6 @@ node_modules/ /*.profraw /foobar.py /python/pydantic_core/*.so -/src/self_schema.py # samply /profile.json diff --git a/Cargo.lock b/Cargo.lock index 870459ac1..22bbe71f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "ahash" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", "getrandom", @@ -36,6 +36,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + [[package]] name = "bitvec" version = "1.0.1" @@ -48,6 +54,12 @@ dependencies = [ "wyz", ] +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + [[package]] name = "cc" version = "1.0.101" @@ -83,12 +95,6 @@ dependencies = [ "syn", ] -[[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -106,21 +112,16 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "getrandom" -version = "0.2.15" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" dependencies = [ "cfg-if", "libc", + "r-efi", "wasi", ] -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" - [[package]] name = "heck" version = "0.5.0" @@ -272,16 +273,6 @@ dependencies = [ "icu_properties", ] -[[package]] -name = "indexmap" -version = "2.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" -dependencies = [ - "equivalent", - "hashbrown", -] - [[package]] name = "indoc" version = "2.0.5" @@ -296,9 +287,9 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jiter" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c024ccb0ed468a474efa325edea34d4198fb601d290c4d1bc24fe31ed11902fc" +checksum = "1bcfb1e43bda3ba59889499ff494c5f5b6b10864b74aa0bd4593ce4d16838aa6" dependencies = [ "ahash", "bitvec", @@ -310,6 +301,16 @@ dependencies = [ "smallvec", ] +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "lexical-parse-float" version = "1.0.5" @@ -352,6 +353,12 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + [[package]] name = "memchr" version = "2.7.4" @@ -424,7 +431,7 @@ dependencies = [ [[package]] name = "pydantic-core" -version = "2.33.1" +version = "2.35.2" dependencies = [ "ahash", "base64", @@ -433,6 +440,7 @@ dependencies = [ "idna", "jiter", "num-bigint", + "num-traits", "pyo3", "pyo3-build-config", "regex", @@ -449,11 +457,10 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.24.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f1c6c3591120564d64db2261bec5f910ae454f01def849b9c22835a84695e86" +checksum = "8970a78afe0628a3e3430376fc5fd76b6b45c4d43360ffd6cdd40bdde72b682a" dependencies = [ - "cfg-if", "indoc", "libc", "memoffset", @@ -468,9 +475,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.24.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9b6c2b34cf71427ea37c7001aefbaeb85886a074795e35f161f5aecc7620a7a" +checksum = "458eb0c55e7ece017adeba38f2248ff3ac615e53660d7c71a238d7d2a01c7598" dependencies = [ "once_cell", "python3-dll-a", @@ -479,9 +486,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.24.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5507651906a46432cdda02cd02dd0319f6064f1374c9147c45b978621d2c3a9c" +checksum = "7114fe5457c61b276ab77c5055f206295b812608083644a5c5b2640c3102565c" dependencies = [ "libc", "pyo3-build-config", @@ -489,9 +496,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.24.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0d394b5b4fd8d97d48336bb0dd2aebabad39f1d294edd6bcd2cccf2eefe6f42" +checksum = "a8725c0a622b374d6cb051d11a0983786448f7785336139c3c94f5aa6bef7e50" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -501,9 +508,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.24.0" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd72da09cfa943b1080f621f024d2ef7e2773df7badd51aa30a2be1f8caa7c8e" +checksum = "4109984c22491085343c05b0dbc54ddc405c3cf7b4374fc533f5c3313a572ccc" dependencies = [ "heck", "proc-macro2", @@ -514,9 +521,9 @@ dependencies = [ [[package]] name = "python3-dll-a" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49fe4227a288cf9493942ad0220ea3f185f4d1f2a14f197f7344d6d02f4ed4ed" +checksum = "d381ef313ae70b4da5f95f8a4de773c6aa5cd28f73adec4b4a31df70b66780d8" dependencies = [ "cc", ] @@ -530,6 +537,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + [[package]] name = "radium" version = "0.7.0" @@ -579,18 +592,18 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "serde" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8dfc9d19bdbf6d17e22319da49161d5d0108e4188e8b680aef6299eed22df60" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.218" +version = "1.0.219" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09503e191f4e797cb8aac08e9a4a4695c5edf6a2e70e376d961ddd5c969f82b" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" dependencies = [ "proc-macro2", "quote", @@ -599,11 +612,10 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.138" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" dependencies = [ - "indexmap", "itoa", "memchr", "ryu", @@ -612,16 +624,17 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "speedate" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a5e7adf4e07e7de39a64d77962ca14a09165e592d42d0c9f9acadb679f4f937" +checksum = "bc823f2eb39713ef0d286058af264ce0d8ddcf62b8a78a0aec02cd0105576d87" dependencies = [ + "lexical-parse-float", "strum", "strum_macros", ] @@ -640,18 +653,18 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "strum" -version = "0.26.3" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.26.4" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" dependencies = [ "heck", "proc-macro2", @@ -741,9 +754,13 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.15.1" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0f540e3240398cce6128b64ba83fdbdd86129c16a3aa1a3a252efd66eb3d587" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +dependencies = [ + "js-sys", + "wasm-bindgen", +] [[package]] name = "version_check" @@ -753,9 +770,79 @@ checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] [[package]] name = "write16" @@ -804,18 +891,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.8.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 278149ac8..cf08c14dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pydantic-core" -version = "2.33.1" +version = "2.35.2" edition = "2021" license = "MIT" homepage = "https://github.com/pydantic/pydantic-core" @@ -12,10 +12,8 @@ include = [ "/LICENSE", "/Makefile", "/build.rs", - "/generate_self_schema.py", "/rust-toolchain", "/src", - "!/src/self_schema.py", "/python/pydantic_core", "/tests", "/.cargo", @@ -29,23 +27,24 @@ rust-version = "1.75" [dependencies] # TODO it would be very nice to remove the "py-clone" feature as it can panic, # but needs a bit of work to make sure it's not used in the codebase -pyo3 = { version = "0.24", features = ["generate-import-lib", "num-bigint", "py-clone"] } +pyo3 = { version = "0.25", features = ["generate-import-lib", "num-bigint", "py-clone"] } regex = "1.11.1" -strum = { version = "0.26.3", features = ["derive"] } -strum_macros = "0.26.4" -serde_json = {version = "1.0.138", features = ["arbitrary_precision", "preserve_order"]} +strum = { version = "0.27", features = ["derive"] } +strum_macros = "0.27" +serde_json = { version = "1.0.140", features = ["arbitrary_precision"] } enum_dispatch = "0.3.13" -serde = { version = "1.0.218", features = ["derive"] } -speedate = "0.15.0" -smallvec = "1.14.0" -ahash = "0.8.10" +serde = { version = "1.0.219", features = ["derive"] } +speedate = "0.16.0" +smallvec = "1.15.1" +ahash = "0.8.12" url = "2.5.4" # idna is already required by url, added here to be explicit idna = "1.0.3" base64 = "0.22.1" num-bigint = "0.4.6" -uuid = "1.15.1" -jiter = { version = "0.9.0", features = ["python"] } +num-traits = "0.2.19" +uuid = "1.17.0" +jiter = { version = "0.10.0", features = ["python"] } hex = "0.4.3" [lib] @@ -73,12 +72,12 @@ debug = true strip = false [dev-dependencies] -pyo3 = { version = "0.24", features = ["auto-initialize"] } +pyo3 = { version = "0.25", features = ["auto-initialize"] } [build-dependencies] version_check = "0.9.5" # used where logic has to be version/distribution specific, e.g. pypy -pyo3-build-config = { version = "0.24" } +pyo3-build-config = { version = "0.25" } [lints.clippy] dbg_macro = "warn" diff --git a/Makefile b/Makefile index b52e097d6..6ca8fc075 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ .DEFAULT_GOAL := all -sources = python/pydantic_core tests generate_self_schema.py wasm-preview/run_tests.py +sources = python/pydantic_core tests wasm-preview/run_tests.py mypy-stubtest = uv run python -m mypy.stubtest pydantic_core._pydantic_core --allowlist .mypy-stubtest-allowlist @@ -124,7 +124,6 @@ clean: rm -f `find . -type f -name '*.py[co]' ` rm -f `find . -type f -name '*~' ` rm -f `find . -type f -name '.*~' ` - rm -rf src/self_schema.py rm -rf .cache rm -rf htmlcov rm -rf .pytest_cache diff --git a/benches/main.rs b/benches/main.rs index c558ca3c6..84ff2e330 100644 --- a/benches/main.rs +++ b/benches/main.rs @@ -8,15 +8,14 @@ use test::{black_box, Bencher}; use pyo3::prelude::*; use pyo3::types::{PyDict, PyString}; -use _pydantic_core::{validate_core_schema, SchemaValidator}; +use _pydantic_core::SchemaValidator; fn build_schema_validator_with_globals( py: Python, code: &CStr, globals: Option<&Bound<'_, PyDict>>, ) -> SchemaValidator { - let mut schema = py.eval(code, globals, None).unwrap().extract().unwrap(); - schema = validate_core_schema(&schema, None).unwrap().extract().unwrap(); + let schema = py.eval(code, globals, None).unwrap().extract().unwrap(); SchemaValidator::py_new(py, &schema, None).unwrap() } @@ -510,8 +509,7 @@ fn complete_model(bench: &mut Bencher) { sys_path.call_method1("append", ("./tests/benchmarks/",)).unwrap(); let complete_schema = py.import("complete_schema").unwrap(); - let mut schema = complete_schema.call_method0("schema").unwrap(); - schema = validate_core_schema(&schema, None).unwrap().extract().unwrap(); + let schema = complete_schema.call_method0("schema").unwrap(); let validator = SchemaValidator::py_new(py, &schema, None).unwrap(); let input = complete_schema.call_method0("input_data_lax").unwrap(); @@ -534,8 +532,7 @@ fn nested_model_using_definitions(bench: &mut Bencher) { sys_path.call_method1("append", ("./tests/benchmarks/",)).unwrap(); let complete_schema = py.import("nested_schema").unwrap(); - let mut schema = complete_schema.call_method0("schema_using_defs").unwrap(); - schema = validate_core_schema(&schema, None).unwrap().extract().unwrap(); + let schema = complete_schema.call_method0("schema_using_defs").unwrap(); let validator = SchemaValidator::py_new(py, &schema, None).unwrap(); let input = complete_schema.call_method0("input_data_valid").unwrap(); @@ -562,8 +559,7 @@ fn nested_model_inlined(bench: &mut Bencher) { sys_path.call_method1("append", ("./tests/benchmarks/",)).unwrap(); let complete_schema = py.import("nested_schema").unwrap(); - let mut schema = complete_schema.call_method0("inlined_schema").unwrap(); - schema = validate_core_schema(&schema, None).unwrap().extract().unwrap(); + let schema = complete_schema.call_method0("inlined_schema").unwrap(); let validator = SchemaValidator::py_new(py, &schema, None).unwrap(); let input = complete_schema.call_method0("input_data_valid").unwrap(); diff --git a/build.rs b/build.rs index f8f66901a..41a831eca 100644 --- a/build.rs +++ b/build.rs @@ -1,35 +1,3 @@ -use std::env; -use std::path::Path; -use std::process::Command; -use std::str::from_utf8; - -fn generate_self_schema() { - println!("cargo:rerun-if-changed=python/pydantic_core/core_schema.py"); - println!("cargo:rerun-if-changed=generate_self_schema.py"); - if Path::new("./src/self_schema.py").exists() && option_env!("CI") == Some("true") { - // self_schema.py already exists and CI indicates we're running on a github actions build, - // don't bother generating again - return; - } - - let output = Command::new( - env::var("PYTHON") - .ok() - .or_else(|| pyo3_build_config::get().executable.clone()) - .unwrap_or_else(|| "python3".to_owned()), - ) - .arg("generate_self_schema.py") - .output() - .expect("failed to execute process"); - - if !output.status.success() { - let stdout = from_utf8(&output.stdout).unwrap(); - let stderr = from_utf8(&output.stderr).unwrap(); - eprint!("{stdout}{stderr}"); - panic!("generate_self_schema.py failed with {}", output.status); - } -} - fn main() { pyo3_build_config::use_pyo3_cfgs(); if let Some(true) = version_check::supports_feature("coverage_attribute") { @@ -44,7 +12,5 @@ fn main() { println!("cargo:rustc-cfg=specified_profile_use"); } println!("cargo:rustc-check-cfg=cfg(specified_profile_use)"); - - generate_self_schema(); println!("cargo:rustc-env=PROFILE={}", std::env::var("PROFILE").unwrap()); } diff --git a/generate_self_schema.py b/generate_self_schema.py deleted file mode 100644 index 623acba58..000000000 --- a/generate_self_schema.py +++ /dev/null @@ -1,245 +0,0 @@ -""" -This script generates the schema for the schema - e.g. -a definition of what inputs can be provided to `SchemaValidator()`. - -The schema is generated from `python/pydantic_core/core_schema.py`. -""" - -from __future__ import annotations as _annotations - -import decimal -import importlib.util -import re -import sys -from collections.abc import Callable -from datetime import date, datetime, time, timedelta -from pathlib import Path -from re import Pattern -from typing import TYPE_CHECKING, Any, ForwardRef, Union - -from typing_extensions import TypedDict, get_args, get_origin, is_typeddict - -TypingUnionType = type[Union[str, int]] - -try: - from types import UnionType as TypesUnionType - - UnionType = Union[TypingUnionType, TypesUnionType] - -except ImportError: - TypesUnionType = TypingUnionType - UnionType = TypingUnionType - - -THIS_DIR = Path(__file__).parent -SAVE_PATH = THIS_DIR / 'src' / 'self_schema.py' - -if TYPE_CHECKING: - from pydantic_core import core_schema -else: - # can't import core_schema.py directly as pydantic-core might not be installed - core_schema_spec = importlib.util.spec_from_file_location( - '_typing', str(THIS_DIR / 'python' / 'pydantic_core' / 'core_schema.py') - ) - core_schema = importlib.util.module_from_spec(core_schema_spec) - core_schema_spec.loader.exec_module(core_schema) - -# the validator for referencing schema (Schema is used recursively, so has to use a reference) -schema_ref_validator = {'type': 'definition-ref', 'schema_ref': 'root-schema'} - - -def get_schema(obj: Any, definitions: dict[str, core_schema.CoreSchema]) -> core_schema.CoreSchema: # noqa: C901 - if isinstance(obj, str): - return {'type': obj} - elif obj in (datetime, timedelta, date, time, bool, int, float, str, decimal.Decimal, complex): - return {'type': obj.__name__.lower()} - elif is_typeddict(obj): - return type_dict_schema(obj, definitions) - elif obj == Any or obj == type: - return {'type': 'any'} - if isinstance(obj, type) and issubclass(obj, core_schema.Protocol): - return {'type': 'callable'} - - origin = get_origin(obj) - assert origin is not None, f'origin cannot be None, obj={obj}, you probably need to fix generate_self_schema.py' - if origin is Union or origin is TypesUnionType: - return union_schema(obj, definitions) - elif obj is Callable or origin is Callable: - return {'type': 'callable'} - elif origin is core_schema.Literal: - expected = all_literal_values(obj) - assert expected, f'literal "expected" cannot be empty, obj={obj}' - return {'type': 'literal', 'expected': expected} - elif issubclass(origin, list): - return {'type': 'list', 'items_schema': get_schema(obj.__args__[0], definitions)} - elif issubclass(origin, set): - return {'type': 'set', 'items_schema': get_schema(obj.__args__[0], definitions)} - elif issubclass(origin, dict): - return { - 'type': 'dict', - 'keys_schema': get_schema(obj.__args__[0], definitions), - 'values_schema': get_schema(obj.__args__[1], definitions), - } - elif issubclass(origin, type): - # can't really use 'is-instance' since this is used for the class_ parameter of 'is-instance' validators - return {'type': 'any'} - elif origin in (Pattern, re.Pattern): - # can't really use 'is-instance' easily with Pattern, so we use `any` as a placeholder for now - return {'type': 'any'} - else: - # debug(obj) - raise TypeError(f'Unknown type: {obj!r}') - - -def tagged_union(std_union_schema: dict[str, Any], discriminator_key: str, ref: str | None = None) -> dict[str, Any]: - """ - Build a tagged union schema from a standard union schema. - """ - tagged_choices = {} - for choice in std_union_schema['choices']: - literal = choice['fields'][discriminator_key]['schema']['expected'] - assert isinstance(literal, list), 'literal expected must be a list' - assert all(isinstance(arg, str) for arg in literal), 'literal expected must be a list of strings' - first, *rest = literal - tagged_choices[first] = choice - for arg in rest: - tagged_choices[arg] = choice - s = {'type': 'tagged-union', 'discriminator': discriminator_key, 'choices': tagged_choices} - if ref is not None: - s['ref'] = ref - return s - - -defined_ser_schema = False - - -def type_dict_schema( # noqa: C901 - typed_dict: type[TypedDict], definitions: dict[str, core_schema.CoreSchema] -) -> dict[str, Any]: - global defined_ser_schema - - required_keys = getattr(typed_dict, '__required_keys__', set()) - fields = {} - - for field_name, field_type in typed_dict.__annotations__.items(): - required = field_name in required_keys - schema = None - fr_arg = None - if type(field_type) == ForwardRef: - fr_arg = field_type.__forward_arg__ - - fr_arg, matched = re.subn(r'Required\[(.+)]', r'\1', fr_arg) - if matched: - required = True - - if 'CoreSchema' == fr_arg or re.search('[^a-zA-Z]CoreSchema', fr_arg): - if fr_arg == 'CoreSchema': - schema = schema_ref_validator - elif fr_arg == 'list[CoreSchema]': - schema = {'type': 'list', 'items_schema': schema_ref_validator} - elif fr_arg == 'dict[str, CoreSchema]': - schema = {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': schema_ref_validator} - elif fr_arg == 'dict[Hashable, CoreSchema]': - schema = {'type': 'dict', 'keys_schema': {'type': 'any'}, 'values_schema': schema_ref_validator} - elif fr_arg == 'list[Union[CoreSchema, tuple[CoreSchema, str]]]': - schema = { - 'type': 'list', - 'items_schema': { - 'type': 'union', - 'choices': [ - schema_ref_validator, - {'type': 'tuple', 'items_schema': [schema_ref_validator, {'type': 'str'}]}, - ], - }, - } - else: - raise ValueError(f'Unknown Schema forward ref: {fr_arg}') - else: - field_type = eval_forward_ref(field_type) - - if schema is None: - if get_origin(field_type) == core_schema.Required: - required = True - field_type = field_type.__args__[0] - - schema = get_schema(field_type, definitions) - if fr_arg == 'SerSchema': - if defined_ser_schema: - schema = {'type': 'definition-ref', 'schema_ref': 'ser-schema'} - else: - defined_ser_schema = True - definitions['ser-schema'] = tagged_union(schema, 'type', 'ser-schema') - schema = {'type': 'definition-ref', 'schema_ref': 'ser-schema'} - elif fr_arg.endswith('SerSchema'): - schema = tagged_union(schema, 'type') - - # now_utc_offset is an int that must be in the range -24 hours to +24 hours, we manually add a constraint here - if field_name == 'now_utc_offset': - schema.update(gt=-86_400, lt=86_400) - fields[field_name] = {'schema': schema, 'required': required} - - return {'type': 'typed-dict', 'fields': fields, 'extra_behavior': 'forbid'} - - -def union_schema(union_type: UnionType, definitions) -> core_schema.UnionSchema | core_schema.DefinitionReferenceSchema: - return {'type': 'union', 'choices': [get_schema(arg, definitions) for arg in union_type.__args__]} - - -def all_literal_values(type_: type[core_schema.Literal]) -> list[any]: - if get_origin(type_) is core_schema.Literal: - values = get_args(type_) - return [x for value in values for x in all_literal_values(value)] - else: - return [type_] - - -def eval_forward_ref(type_: Any) -> Any: - if sys.version_info < (3, 12, 4): - return type_._evaluate(core_schema.__dict__, None, recursive_guard=set()) - else: - return type_._evaluate(core_schema.__dict__, None, type_params=set(), recursive_guard=set()) - - -def main() -> None: - schema_union = core_schema.CoreSchema - assert get_origin(schema_union) is Union, 'expected core_schema.CoreSchema to be a Union' - - definitions: dict[str, core_schema.CoreSchema] = {} - - choices = {} - for s in schema_union.__args__: - type_ = s.__annotations__['type'] - m = re.search(r"Literal\['(.+?)']", type_.__forward_arg__) - assert m, f'Unknown schema type: {type_}' - key = m.group(1) - value = get_schema(s, definitions) - choices[key] = value - - schema = core_schema.definitions_schema( - schema=core_schema.definition_reference_schema(schema_ref='root-schema'), - definitions=[ - core_schema.tagged_union_schema(choices, discriminator='type', ref='root-schema'), - *definitions.values(), - ], - ) - python_code = ( - f'# this file is auto-generated by generate_self_schema.py, DO NOT edit manually\nself_schema = {schema}\n' - ) - try: - from black import Mode, TargetVersion, format_file_contents - except ImportError: - pass - else: - mode = Mode( - line_length=120, - string_normalization=False, - magic_trailing_comma=False, - target_versions={TargetVersion.PY37, TargetVersion.PY38, TargetVersion.PY39, TargetVersion.PY310}, - ) - python_code = format_file_contents(python_code, fast=False, mode=mode) - SAVE_PATH.write_text(python_code) - print(f'Self schema definition written to {SAVE_PATH}') - - -if __name__ == '__main__': - main() diff --git a/pyproject.toml b/pyproject.toml index 082f1b647..fb00a36a5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ['maturin>=1,<2', 'typing-extensions >=4.6.0,!=4.7.0'] +requires = ['maturin>=1,<2'] build-backend = 'maturin' [project] @@ -24,6 +24,7 @@ classifiers = [ 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', 'Programming Language :: Python :: 3.13', + 'Programming Language :: Python :: 3.14', 'Programming Language :: Rust', 'Framework :: Pydantic', 'Intended Audience :: Developers', @@ -34,8 +35,10 @@ classifiers = [ 'Operating System :: MacOS', 'Typing :: Typed', ] -dependencies = ['typing-extensions>=4.6.0,!=4.7.0'] -dynamic = ['description', 'license', 'readme', 'version'] +dependencies = [ + 'typing-extensions>=4.13.0', +] +dynamic = ['license', 'readme', 'version'] [project.urls] Homepage = 'https://github.com/pydantic/pydantic-core' @@ -46,13 +49,12 @@ Source = 'https://github.com/pydantic/pydantic-core' dev = ["maturin"] testing = [ { include-group = "dev" }, - 'backports.zoneinfo; python_version < "3.9"', 'coverage', 'dirty-equals', 'inline-snapshot', 'hypothesis', # pandas doesn't offer prebuilt wheels for all versions and platforms we test in CI e.g. aarch64 musllinux - 'pandas; python_version >= "3.9" and python_version < "3.13" and implementation_name == "cpython" and platform_machine == "x86_64"', + 'pandas; python_version < "3.13" and implementation_name == "cpython" and platform_machine == "x86_64"', 'pytest', # pytest-examples currently depends on aiohttp via black; we don't want to build it on platforms like aarch64 musllinux in CI 'pytest-examples; implementation_name == "cpython" and platform_machine == "x86_64"', @@ -63,13 +65,13 @@ testing = [ 'pytest-timeout', 'python-dateutil', # numpy doesn't offer prebuilt wheels for all versions and platforms we test in CI e.g. aarch64 musllinux - 'numpy; python_version >= "3.9" and python_version < "3.13" and implementation_name == "cpython" and platform_machine == "x86_64"', + 'numpy; python_version < "3.13" and implementation_name == "cpython" and platform_machine == "x86_64"', 'exceptiongroup; python_version < "3.11"', 'tzdata', - 'typing_extensions', + 'typing-inspection>=0.4.1', ] linting = [{ include-group = "dev" }, 'griffe', 'pyright', 'ruff', 'mypy'] -wasm = [{ include-group = "dev" }, 'typing_extensions', 'ruff'] +wasm = [{ include-group = "dev" }, 'ruff'] codspeed = [ # codspeed is only run on CI, with latest version of CPython 'pytest-codspeed; python_version == "3.13" and implementation_name == "cpython"', diff --git a/python/pydantic_core/__init__.py b/python/pydantic_core/__init__.py index 98b64b86e..a146499d0 100644 --- a/python/pydantic_core/__init__.py +++ b/python/pydantic_core/__init__.py @@ -25,7 +25,6 @@ from_json, to_json, to_jsonable_python, - validate_core_schema, ) from .core_schema import CoreConfig, CoreSchema, CoreSchemaType, ErrorType @@ -66,7 +65,6 @@ 'to_json', 'from_json', 'to_jsonable_python', - 'validate_core_schema', ] diff --git a/python/pydantic_core/_pydantic_core.pyi b/python/pydantic_core/_pydantic_core.pyi index 17098cca5..0e29a6b41 100644 --- a/python/pydantic_core/_pydantic_core.pyi +++ b/python/pydantic_core/_pydantic_core.pyi @@ -34,7 +34,6 @@ __all__ = [ 'to_jsonable_python', 'list_all_errors', 'TzInfo', - 'validate_core_schema', ] __version__: str build_profile: str @@ -345,6 +344,7 @@ class SchemaSerializer: value: Any, *, indent: int | None = None, + ensure_ascii: bool = False, include: _IncEx | None = None, exclude: _IncEx | None = None, by_alias: bool | None = None, @@ -363,6 +363,8 @@ class SchemaSerializer: Arguments: value: The Python object to serialize. indent: If `None`, the JSON will be compact, otherwise it will be pretty-printed with the indent provided. + ensure_ascii: If `True`, the output is guaranteed to have all incoming non-ASCII characters escaped. + If `False` (the default), these characters will be output as-is. include: A set of fields to include, if `None` all fields are included. exclude: A set of fields to exclude, if `None` no fields are excluded. by_alias: Whether to use the alias names of fields. @@ -390,6 +392,7 @@ def to_json( value: Any, *, indent: int | None = None, + ensure_ascii: bool = False, include: _IncEx | None = None, exclude: _IncEx | None = None, # Note: In Pydantic 2.11, the default value of `by_alias` on `SchemaSerializer` was changed from `True` to `None`, @@ -414,6 +417,8 @@ def to_json( Arguments: value: The Python object to serialize. indent: If `None`, the JSON will be compact, otherwise it will be pretty-printed with the indent provided. + ensure_ascii: If `True`, the output is guaranteed to have all incoming non-ASCII characters escaped. + If `False` (the default), these characters will be output as-is. include: A set of fields to include, if `None` all fields are included. exclude: A set of fields to exclude, if `None` no fields are excluded. by_alias: Whether to use the alias names of fields. @@ -714,22 +719,16 @@ class PydanticCustomError(ValueError): raise PydanticCustomError('custom_value_error', 'Value must be greater than {value}', {'value': 10, 'extra_context': 'extra_data'}) return v ``` + + Arguments: + error_type: The error type. + message_template: The message template. + context: The data to inject into the message template. """ def __init__( - self, error_type: LiteralString, message_template: LiteralString, context: dict[str, Any] | None = None - ) -> None: - """Initializes the `PydanticCustomError`. - - Arguments: - error_type: The error type. - message_template: The message template. - context: The data to inject into the message template. - """ - - def __new__( - cls, error_type: LiteralString, message_template: LiteralString, context: dict[str, Any] | None = None - ) -> Self: ... + self, error_type: LiteralString, message_template: LiteralString, context: dict[str, Any] | None = None, / + ) -> None: ... @property def context(self) -> dict[str, Any] | None: """Values which are required to render the error message, and could hence be useful in passing error data forward.""" @@ -757,20 +756,16 @@ class PydanticKnownError(ValueError): def custom_validator(v) -> None: if v <= 10: - raise PydanticKnownError(error_type='greater_than', context={'gt': 10}) + raise PydanticKnownError('greater_than', {'gt': 10}) return v ``` - """ - - def __init__(self, error_type: ErrorType, context: dict[str, Any] | None = None) -> None: - """Initializes the `PydanticKnownError`. - Arguments: - error_type: The error type. - context: The data to inject into the message template. - """ + Arguments: + error_type: The error type. + context: The data to inject into the message template. + """ - def __new__(cls, error_type: ErrorType, context: dict[str, Any] | None = None) -> Self: ... + def __init__(self, error_type: ErrorType, context: dict[str, Any] | None = None, /) -> None: ... @property def context(self) -> dict[str, Any] | None: """Values which are required to render the error message, and could hence be useful in passing error data forward.""" @@ -870,16 +865,12 @@ class PydanticSerializationError(ValueError): """An error raised when an issue occurs during serialization. In custom serializers, this error can be used to indicate that serialization has failed. - """ - def __init__(self, message: str) -> None: - """Initializes the `PydanticSerializationError`. - - Arguments: - message: The message associated with the error. - """ + Arguments: + message: The message associated with the error. + """ - def __new__(cls, message: str) -> Self: ... + def __init__(self, message: str, /) -> None: ... @final class PydanticSerializationUnexpectedValue(ValueError): @@ -918,16 +909,12 @@ class PydanticSerializationUnexpectedValue(ValueError): This is often used internally in `pydantic-core` when unexpected types are encountered during serialization, but it can also be used by users in custom serializers, as seen above. - """ - - def __init__(self, message: str) -> None: - """Initializes the `PydanticSerializationUnexpectedValue`. - Arguments: - message: The message associated with the unexpected value. - """ + Arguments: + message: The message associated with the unexpected value. + """ - def __new__(cls, message: str | None = None) -> Self: ... + def __init__(self, message: str, /) -> None: ... @final class ArgsKwargs: @@ -1028,12 +1015,3 @@ class TzInfo(datetime.tzinfo): More info can be found at [`tzinfo.fromutc`][datetime.tzinfo.fromutc].""" def __deepcopy__(self, _memo: dict[Any, Any]) -> TzInfo: ... - -def validate_core_schema(schema: CoreSchema, *, strict: bool | None = None) -> CoreSchema: - """Validate a core schema. - - This currently uses lax mode for validation (i.e. will coerce strings to dates and such) - but may use strict mode in the future. - We may also remove this function altogether, do not rely on it being present if you are - using pydantic-core directly. - """ diff --git a/python/pydantic_core/core_schema.py b/python/pydantic_core/core_schema.py index 0ab3dd947..803569244 100644 --- a/python/pydantic_core/core_schema.py +++ b/python/pydantic_core/core_schema.py @@ -13,7 +13,7 @@ from re import Pattern from typing import TYPE_CHECKING, Any, Callable, Literal, Union -from typing_extensions import deprecated +from typing_extensions import TypeVar, deprecated if sys.version_info < (3, 12): from typing_extensions import TypedDict @@ -118,38 +118,61 @@ class CoreConfig(TypedDict, total=False): IncExCall: TypeAlias = 'set[int | str] | dict[int | str, IncExCall] | None' +ContextT = TypeVar('ContextT', covariant=True, default='Any | None') + + +class SerializationInfo(Protocol[ContextT]): + """Extra data used during serialization.""" -class SerializationInfo(Protocol): @property - def include(self) -> IncExCall: ... + def include(self) -> IncExCall: + """The `include` argument set during serialization.""" + ... @property - def exclude(self) -> IncExCall: ... + def exclude(self) -> IncExCall: + """The `exclude` argument set during serialization.""" + ... @property - def context(self) -> Any | None: - """Current serialization context.""" + def context(self) -> ContextT: + """The current serialization context.""" + ... @property - def mode(self) -> str: ... + def mode(self) -> Literal['python', 'json']: + """The serialization mode set during serialization.""" + ... @property - def by_alias(self) -> bool: ... + def by_alias(self) -> bool: + """The `by_alias` argument set during serialization.""" + ... @property - def exclude_unset(self) -> bool: ... + def exclude_unset(self) -> bool: + """The `exclude_unset` argument set during serialization.""" + ... @property - def exclude_defaults(self) -> bool: ... + def exclude_defaults(self) -> bool: + """The `exclude_defaults` argument set during serialization.""" + ... @property - def exclude_none(self) -> bool: ... + def exclude_none(self) -> bool: + """The `exclude_none` argument set during serialization.""" + ... @property - def serialize_as_any(self) -> bool: ... + def serialize_as_any(self) -> bool: + """The `serialize_as_any` argument set during serialization.""" + ... @property - def round_trip(self) -> bool: ... + def round_trip(self) -> bool: + """The `round_trip` argument set during serialization.""" + ... def mode_is_json(self) -> bool: ... @@ -158,19 +181,21 @@ def __str__(self) -> str: ... def __repr__(self) -> str: ... -class FieldSerializationInfo(SerializationInfo, Protocol): +class FieldSerializationInfo(SerializationInfo[ContextT], Protocol): + """Extra data used during field serialization.""" + @property - def field_name(self) -> str: ... + def field_name(self) -> str: + """The name of the current field being serialized.""" + ... -class ValidationInfo(Protocol): - """ - Argument passed to validation functions. - """ +class ValidationInfo(Protocol[ContextT]): + """Extra data used during validation.""" @property - def context(self) -> Any | None: - """Current validation context.""" + def context(self) -> ContextT: + """The current validation context.""" ... @property @@ -180,7 +205,7 @@ def config(self) -> CoreConfig | None: @property def mode(self) -> Literal['python', 'json']: - """The type of input data we are currently validating""" + """The type of input data we are currently validating.""" ... @property @@ -240,11 +265,11 @@ def simple_ser_schema(type: ExpectedSerializationTypes) -> SimpleSerSchema: # (input_value: Any, /) -> Any GeneralPlainNoInfoSerializerFunction = Callable[[Any], Any] # (input_value: Any, info: FieldSerializationInfo, /) -> Any -GeneralPlainInfoSerializerFunction = Callable[[Any, SerializationInfo], Any] +GeneralPlainInfoSerializerFunction = Callable[[Any, SerializationInfo[Any]], Any] # (model: Any, input_value: Any, /) -> Any FieldPlainNoInfoSerializerFunction = Callable[[Any, Any], Any] # (model: Any, input_value: Any, info: FieldSerializationInfo, /) -> Any -FieldPlainInfoSerializerFunction = Callable[[Any, Any, FieldSerializationInfo], Any] +FieldPlainInfoSerializerFunction = Callable[[Any, Any, FieldSerializationInfo[Any]], Any] SerializerFunction = Union[ GeneralPlainNoInfoSerializerFunction, GeneralPlainInfoSerializerFunction, @@ -311,11 +336,11 @@ def __call__(self, input_value: Any, index_key: int | str | None = None, /) -> A # (input_value: Any, serializer: SerializerFunctionWrapHandler, /) -> Any GeneralWrapNoInfoSerializerFunction = Callable[[Any, SerializerFunctionWrapHandler], Any] # (input_value: Any, serializer: SerializerFunctionWrapHandler, info: SerializationInfo, /) -> Any -GeneralWrapInfoSerializerFunction = Callable[[Any, SerializerFunctionWrapHandler, SerializationInfo], Any] +GeneralWrapInfoSerializerFunction = Callable[[Any, SerializerFunctionWrapHandler, SerializationInfo[Any]], Any] # (model: Any, input_value: Any, serializer: SerializerFunctionWrapHandler, /) -> Any FieldWrapNoInfoSerializerFunction = Callable[[Any, Any, SerializerFunctionWrapHandler], Any] # (model: Any, input_value: Any, serializer: SerializerFunctionWrapHandler, info: FieldSerializationInfo, /) -> Any -FieldWrapInfoSerializerFunction = Callable[[Any, Any, SerializerFunctionWrapHandler, FieldSerializationInfo], Any] +FieldWrapInfoSerializerFunction = Callable[[Any, Any, SerializerFunctionWrapHandler, FieldSerializationInfo[Any]], Any] WrapSerializerFunction = Union[ GeneralWrapNoInfoSerializerFunction, GeneralWrapInfoSerializerFunction, @@ -953,7 +978,7 @@ class DateSchema(TypedDict, total=False): gt: date now_op: Literal['past', 'future'] # defaults to current local utc offset from `time.localtime().tm_gmtoff` - # value is restricted to -86_400 < offset < 86_400 by bounds in generate_self_schema.py + # value is restricted to -86_400 < offset < 86_400: now_utc_offset: int ref: str metadata: dict[str, Any] @@ -1948,13 +1973,13 @@ class NoInfoValidatorFunctionSchema(TypedDict): # (input_value: Any, info: ValidationInfo, /) -> Any -WithInfoValidatorFunction = Callable[[Any, ValidationInfo], Any] +WithInfoValidatorFunction = Callable[[Any, ValidationInfo[Any]], Any] class WithInfoValidatorFunctionSchema(TypedDict, total=False): type: Required[Literal['with-info']] function: Required[WithInfoValidatorFunction] - field_name: str + field_name: str # deprecated ValidationFunction = Union[NoInfoValidatorFunctionSchema, WithInfoValidatorFunctionSchema] @@ -2042,7 +2067,7 @@ def fn(v: bytes, info: core_schema.ValidationInfo) -> str: return v.decode() + 'world' func_schema = core_schema.with_info_before_validator_function( - function=fn, schema=core_schema.str_schema(), field_name='a' + function=fn, schema=core_schema.str_schema() ) schema = core_schema.typed_dict_schema({'a': core_schema.typed_dict_field(func_schema)}) @@ -2052,13 +2077,20 @@ def fn(v: bytes, info: core_schema.ValidationInfo) -> str: Args: function: The validator function to call - field_name: The name of the field + field_name: The name of the field this validator is applied to, if any (deprecated) schema: The schema to validate the output of the validator function ref: optional unique identifier of the schema, used to reference the schema in other places json_schema_input_schema: The core schema to be used to generate the corresponding JSON Schema input type metadata: Any other information you want to include with the schema, not used by pydantic-core serialization: Custom serialization schema """ + if field_name is not None: + warnings.warn( + 'The `field_name` argument on `with_info_before_validator_function` is deprecated, it will be passed to the function through `ValidationState` instead.', + DeprecationWarning, + stacklevel=2, + ) + return _dict_not_none( type='function-before', function=_dict_not_none(type='with-info', function=function, field_name=field_name), @@ -2140,7 +2172,7 @@ def fn(v: str, info: core_schema.ValidationInfo) -> str: return v + 'world' func_schema = core_schema.with_info_after_validator_function( - function=fn, schema=core_schema.str_schema(), field_name='a' + function=fn, schema=core_schema.str_schema() ) schema = core_schema.typed_dict_schema({'a': core_schema.typed_dict_field(func_schema)}) @@ -2151,11 +2183,18 @@ def fn(v: str, info: core_schema.ValidationInfo) -> str: Args: function: The validator function to call after the schema is validated schema: The schema to validate before the validator function - field_name: The name of the field this validators is applied to, if any + field_name: The name of the field this validator is applied to, if any (deprecated) ref: optional unique identifier of the schema, used to reference the schema in other places metadata: Any other information you want to include with the schema, not used by pydantic-core serialization: Custom serialization schema """ + if field_name is not None: + warnings.warn( + 'The `field_name` argument on `with_info_after_validator_function` is deprecated, it will be passed to the function through `ValidationState` instead.', + DeprecationWarning, + stacklevel=2, + ) + return _dict_not_none( type='function-after', function=_dict_not_none(type='with-info', function=function, field_name=field_name), @@ -2181,13 +2220,13 @@ class NoInfoWrapValidatorFunctionSchema(TypedDict): # (input_value: Any, validator: ValidatorFunctionWrapHandler, info: ValidationInfo, /) -> Any -WithInfoWrapValidatorFunction = Callable[[Any, ValidatorFunctionWrapHandler, ValidationInfo], Any] +WithInfoWrapValidatorFunction = Callable[[Any, ValidatorFunctionWrapHandler, ValidationInfo[Any]], Any] class WithInfoWrapValidatorFunctionSchema(TypedDict, total=False): type: Required[Literal['with-info']] function: Required[WithInfoWrapValidatorFunction] - field_name: str + field_name: str # deprecated WrapValidatorFunction = Union[NoInfoWrapValidatorFunctionSchema, WithInfoWrapValidatorFunctionSchema] @@ -2287,12 +2326,19 @@ def fn( Args: function: The validator function to call schema: The schema to validate the output of the validator function - field_name: The name of the field this validators is applied to, if any + field_name: The name of the field this validator is applied to, if any (deprecated) json_schema_input_schema: The core schema to be used to generate the corresponding JSON Schema input type ref: optional unique identifier of the schema, used to reference the schema in other places metadata: Any other information you want to include with the schema, not used by pydantic-core serialization: Custom serialization schema """ + if field_name is not None: + warnings.warn( + 'The `field_name` argument on `with_info_wrap_validator_function` is deprecated, it will be passed to the function through `ValidationState` instead.', + DeprecationWarning, + stacklevel=2, + ) + return _dict_not_none( type='function-wrap', function=_dict_not_none(type='with-info', function=function, field_name=field_name), @@ -2379,12 +2425,19 @@ def fn(v: str, info: core_schema.ValidationInfo) -> str: Args: function: The validator function to call - field_name: The name of the field this validators is applied to, if any + field_name: The name of the field this validator is applied to, if any (deprecated) ref: optional unique identifier of the schema, used to reference the schema in other places json_schema_input_schema: The core schema to be used to generate the corresponding JSON Schema input type metadata: Any other information you want to include with the schema, not used by pydantic-core serialization: Custom serialization schema """ + if field_name is not None: + warnings.warn( + 'The `field_name` argument on `with_info_plain_validator_function` is deprecated, it will be passed to the function through `ValidationState` instead.', + DeprecationWarning, + stacklevel=2, + ) + return _dict_not_none( type='function-plain', function=_dict_not_none(type='with-info', function=function, field_name=field_name), diff --git a/src/errors/location.rs b/src/errors/location.rs index d020519e7..3d3e90849 100644 --- a/src/errors/location.rs +++ b/src/errors/location.rs @@ -147,7 +147,7 @@ impl Location { Self::Empty => { *self = Self::new_some(loc_item); } - }; + } } } diff --git a/src/errors/validation_exception.rs b/src/errors/validation_exception.rs index 16e89eb68..5d36851c2 100644 --- a/src/errors/validation_exception.rs +++ b/src/errors/validation_exception.rs @@ -18,7 +18,7 @@ use crate::build_tools::py_schema_error_type; use crate::errors::LocItem; use crate::get_pydantic_version; use crate::input::InputType; -use crate::serializers::{DuckTypingSerMode, Extra, SerMode, SerializationState}; +use crate::serializers::{Extra, SerMode, SerializationState}; use crate::tools::{safe_repr, write_truncated_to_limited_bytes, SchemaDict}; use super::line_error::ValLineError; @@ -110,7 +110,7 @@ impl ValidationError { } pub fn use_default_error() -> PyErr { - py_schema_error_type!("Uncaught UseDefault error, please check your usage of `default` validators.") + py_schema_error_type!("Uncaught `PydanticUseDefault` exception: the error was raised in a field validator and no default value is available for that field.") } fn maybe_add_cause(self_: PyRef<'_, Self>, py: Python) -> Option { @@ -341,17 +341,7 @@ impl ValidationError { include_input: bool, ) -> PyResult> { let state = SerializationState::new("iso8601", "utf8", "constants")?; - let extra = state.extra( - py, - &SerMode::Json, - None, - false, - false, - true, - None, - DuckTypingSerMode::SchemaBased, - None, - ); + let extra = state.extra(py, &SerMode::Json, None, false, false, true, None, false, None); let serializer = ValidationErrorSerializer { py, line_errors: &self.line_errors, diff --git a/src/errors/value_exception.rs b/src/errors/value_exception.rs index d428dc524..964899905 100644 --- a/src/errors/value_exception.rs +++ b/src/errors/value_exception.rs @@ -65,7 +65,7 @@ pub struct PydanticCustomError { #[pymethods] impl PydanticCustomError { #[new] - #[pyo3(signature = (error_type, message_template, context = None))] + #[pyo3(signature = (error_type, message_template, context = None, /))] pub fn py_new(error_type: String, message_template: String, context: Option>) -> Self { Self { error_type, @@ -144,7 +144,7 @@ pub struct PydanticKnownError { #[pymethods] impl PydanticKnownError { #[new] - #[pyo3(signature = (error_type, context=None))] + #[pyo3(signature = (error_type, context=None, /))] pub fn py_new(py: Python, error_type: &str, context: Option>) -> PyResult { let error_type = ErrorType::new(py, error_type, context)?; Ok(Self { error_type }) diff --git a/src/input/datetime.rs b/src/input/datetime.rs index 9afe49a0a..279e79159 100644 --- a/src/input/datetime.rs +++ b/src/input/datetime.rs @@ -6,10 +6,12 @@ use pyo3::pyclass::CompareOp; use pyo3::types::PyTuple; use pyo3::types::{PyDate, PyDateTime, PyDelta, PyDeltaAccess, PyDict, PyTime, PyTzInfo}; use pyo3::IntoPyObjectExt; -use speedate::MicrosecondsPrecisionOverflowBehavior; -use speedate::{Date, DateTime, Duration, ParseError, Time, TimeConfig}; +use speedate::{ + Date, DateTime, DateTimeConfig, Duration, MicrosecondsPrecisionOverflowBehavior, ParseError, Time, TimeConfig, +}; use std::borrow::Cow; use std::collections::hash_map::DefaultHasher; +use std::fmt::Write; use std::hash::Hash; use std::hash::Hasher; @@ -59,7 +61,7 @@ impl<'py> EitherDate<'py> { }, input, )); - }; + } let py_date = PyDate::new(py, date.year.into(), date.month, date.day)?; Ok(py_date.into()) } @@ -296,7 +298,7 @@ impl<'py> EitherDateTime<'py> { }, input, )); - }; + } let py_dt = PyDateTime::new( py, dt.date.year.into(), @@ -365,9 +367,12 @@ pub fn bytes_as_datetime<'py>( ) -> ValResult> { match DateTime::parse_bytes_with_config( bytes, - &TimeConfig { - microseconds_precision_overflow_behavior: microseconds_overflow_behavior, - unix_timestamp_offset: Some(0), + &DateTimeConfig { + time_config: TimeConfig { + microseconds_precision_overflow_behavior: microseconds_overflow_behavior, + unix_timestamp_offset: Some(0), + }, + ..Default::default() }, ) { Ok(dt) => Ok(dt.into()), @@ -389,8 +394,11 @@ pub fn int_as_datetime<'py>( match DateTime::from_timestamp_with_config( timestamp, timestamp_microseconds, - &TimeConfig { - unix_timestamp_offset: Some(0), + &DateTimeConfig { + time_config: TimeConfig { + unix_timestamp_offset: Some(0), + ..Default::default() + }, ..Default::default() }, ) { @@ -573,7 +581,7 @@ impl TzInfo { } fn __repr__(&self) -> String { - format!("TzInfo({})", self.__str__()) + format!("TzInfo({})", self.seconds) } fn __str__(&self) -> String { @@ -590,7 +598,7 @@ impl TzInfo { ); if seconds != 0 { - result.push_str(&format!(":{:02}", seconds.abs())); + write!(result, ":{:02}", seconds.abs()).expect("writing to string should never fail"); } result diff --git a/src/input/input_json.rs b/src/input/input_json.rs index 4de3fd4cf..6828f5927 100644 --- a/src/input/input_json.rs +++ b/src/input/input_json.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use jiter::{JsonArray, JsonObject, JsonValue}; +use num_traits::cast::ToPrimitive; use pyo3::prelude::*; use pyo3::types::{PyDict, PyList, PyString}; use speedate::MicrosecondsPrecisionOverflowBehavior; @@ -173,6 +174,9 @@ impl<'py, 'data> Input<'py> for JsonValue<'data> { match self { JsonValue::Float(f) => Ok(ValidationMatch::exact(EitherFloat::F64(*f))), JsonValue::Int(i) => Ok(ValidationMatch::strict(EitherFloat::F64(*i as f64))), + JsonValue::BigInt(b) => Ok(ValidationMatch::strict(EitherFloat::F64( + b.to_f64().expect("BigInt should always return some value"), + ))), JsonValue::Bool(b) if !strict => Ok(ValidationMatch::lax(EitherFloat::F64(if *b { 1.0 } else { 0.0 }))), JsonValue::Str(str) if !strict => str_as_float(self, str).map(ValidationMatch::lax), _ => Err(ValError::new(ErrorTypeDefaults::FloatType, self)), diff --git a/src/input/mod.rs b/src/input/mod.rs index 779454b3c..19be9fad1 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -13,7 +13,7 @@ mod shared; pub use datetime::TzInfo; pub(crate) use datetime::{ duration_as_pytimedelta, pydate_as_date, pydatetime_as_datetime, pytime_as_time, EitherDate, EitherDateTime, - EitherTime, EitherTimedelta, + EitherTimedelta, }; pub(crate) use input_abstract::{ Arguments, BorrowInput, ConsumeIterator, Input, InputType, KeywordArgs, PositionalArgs, ValidatedDict, diff --git a/src/input/return_enums.rs b/src/input/return_enums.rs index 6ac382430..bada53ace 100644 --- a/src/input/return_enums.rs +++ b/src/input/return_enums.rs @@ -11,7 +11,6 @@ use pyo3::exceptions::PyTypeError; use pyo3::ffi; use pyo3::intern; use pyo3::prelude::*; -#[cfg(not(PyPy))] use pyo3::types::PyFunction; use pyo3::types::{PyBytes, PyComplex, PyFloat, PyFrozenSet, PyIterator, PyMapping, PySet, PyString}; @@ -348,17 +347,9 @@ pub(crate) fn iterate_attributes<'a, 'py>( // the PyFunction::is_type_of(attr) catches `staticmethod`, but also any other function, // I think that's better than including static methods in the yielded attributes, // if someone really wants fields, they can use an explicit field, or a function to modify input - #[cfg(not(PyPy))] if !is_bound && !attr.is_instance_of::() { return Some(Ok((name, attr))); } - // MASSIVE HACK! PyFunction doesn't exist for PyPy, - // is_instance_of:: crashes with a null pointer, hence this hack, see - // https://github.com/pydantic/pydantic-core/pull/161#discussion_r917257635 - #[cfg(PyPy)] - if !is_bound && attr.get_type().to_string() != "" { - return Some(Ok((name, attr))); - } } } None diff --git a/src/input/shared.rs b/src/input/shared.rs index f3d8a3b9f..1a90b4142 100644 --- a/src/input/shared.rs +++ b/src/input/shared.rs @@ -181,7 +181,7 @@ fn strip_leading_zeros(s: &str) -> Option<&str> { Some((_, c)) if ('1'..='9').contains(&c) || c == '-' => return Some(s), // anything else is invalid, we return None _ => return None, - }; + } for (i, c) in char_iter { match c { // continue on more leading zeros or if we get an underscore we continue - we're "within the number" diff --git a/src/lib.rs b/src/lib.rs index 2404ebdfb..84bf95a22 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,7 +39,7 @@ pub use serializers::{ to_json, to_jsonable_python, PydanticSerializationError, PydanticSerializationUnexpectedValue, SchemaSerializer, WarningsArg, }; -pub use validators::{validate_core_schema, PySome, SchemaValidator}; +pub use validators::{PySome, SchemaValidator}; use crate::input::Input; @@ -113,8 +113,8 @@ mod _pydantic_core { #[pymodule_export] use crate::{ - from_json, list_all_errors, to_json, to_jsonable_python, validate_core_schema, ArgsKwargs, PyMultiHostUrl, - PySome, PyUrl, PydanticCustomError, PydanticKnownError, PydanticOmit, PydanticSerializationError, + from_json, list_all_errors, to_json, to_jsonable_python, ArgsKwargs, PyMultiHostUrl, PySome, PyUrl, + PydanticCustomError, PydanticKnownError, PydanticOmit, PydanticSerializationError, PydanticSerializationUnexpectedValue, PydanticUndefinedType, PydanticUseDefault, SchemaError, SchemaSerializer, SchemaValidator, TzInfo, ValidationError, }; diff --git a/src/py_gc.rs b/src/py_gc.rs index 8af285afb..c4f83f5b0 100644 --- a/src/py_gc.rs +++ b/src/py_gc.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use ahash::AHashMap; use enum_dispatch::enum_dispatch; -use pyo3::{AsPyPointer, Py, PyTraverseError, PyVisit}; +use pyo3::{Py, PyTraverseError, PyVisit}; /// Trait implemented by types which can be traversed by the Python GC. #[enum_dispatch] @@ -10,10 +10,7 @@ pub trait PyGcTraverse { fn py_gc_traverse(&self, visit: &PyVisit<'_>) -> Result<(), PyTraverseError>; } -impl PyGcTraverse for Py -where - Py: AsPyPointer, -{ +impl PyGcTraverse for Py { fn py_gc_traverse(&self, visit: &PyVisit<'_>) -> Result<(), PyTraverseError> { visit.call(self) } diff --git a/src/self_schema.py b/src/self_schema.py new file mode 100644 index 000000000..6d8c02cad --- /dev/null +++ b/src/self_schema.py @@ -0,0 +1,2 @@ +# this file is auto-generated by generate_self_schema.py, DO NOT edit manually +self_schema = {'type': 'definitions', 'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'definitions': [{'type': 'tagged-union', 'choices': {'invalid': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['invalid']}, 'required': True}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'any': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['any']}, 'required': True}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'none': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none']}, 'required': True}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'bool': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['bool']}, 'required': True}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'int': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['int']}, 'required': True}, 'multiple_of': {'schema': {'type': 'int'}, 'required': False}, 'le': {'schema': {'type': 'int'}, 'required': False}, 'ge': {'schema': {'type': 'int'}, 'required': False}, 'lt': {'schema': {'type': 'int'}, 'required': False}, 'gt': {'schema': {'type': 'int'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'float': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['float']}, 'required': True}, 'allow_inf_nan': {'schema': {'type': 'bool'}, 'required': False}, 'multiple_of': {'schema': {'type': 'float'}, 'required': False}, 'le': {'schema': {'type': 'float'}, 'required': False}, 'ge': {'schema': {'type': 'float'}, 'required': False}, 'lt': {'schema': {'type': 'float'}, 'required': False}, 'gt': {'schema': {'type': 'float'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'decimal': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['decimal']}, 'required': True}, 'allow_inf_nan': {'schema': {'type': 'bool'}, 'required': False}, 'multiple_of': {'schema': {'type': 'decimal'}, 'required': False}, 'le': {'schema': {'type': 'decimal'}, 'required': False}, 'ge': {'schema': {'type': 'decimal'}, 'required': False}, 'lt': {'schema': {'type': 'decimal'}, 'required': False}, 'gt': {'schema': {'type': 'decimal'}, 'required': False}, 'max_digits': {'schema': {'type': 'int'}, 'required': False}, 'decimal_places': {'schema': {'type': 'int'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'str': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['str']}, 'required': True}, 'pattern': {'schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'any'}]}, 'required': False}, 'max_length': {'schema': {'type': 'int'}, 'required': False}, 'min_length': {'schema': {'type': 'int'}, 'required': False}, 'strip_whitespace': {'schema': {'type': 'bool'}, 'required': False}, 'to_lower': {'schema': {'type': 'bool'}, 'required': False}, 'to_upper': {'schema': {'type': 'bool'}, 'required': False}, 'regex_engine': {'schema': {'type': 'literal', 'expected': ['rust-regex', 'python-re']}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'coerce_numbers_to_str': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'bytes': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['bytes']}, 'required': True}, 'max_length': {'schema': {'type': 'int'}, 'required': False}, 'min_length': {'schema': {'type': 'int'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'date': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['date']}, 'required': True}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'le': {'schema': {'type': 'date'}, 'required': False}, 'ge': {'schema': {'type': 'date'}, 'required': False}, 'lt': {'schema': {'type': 'date'}, 'required': False}, 'gt': {'schema': {'type': 'date'}, 'required': False}, 'now_op': {'schema': {'type': 'literal', 'expected': ['past', 'future']}, 'required': False}, 'now_utc_offset': {'schema': {'type': 'int', 'gt': -86400, 'lt': 86400}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'time': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['time']}, 'required': True}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'le': {'schema': {'type': 'time'}, 'required': False}, 'ge': {'schema': {'type': 'time'}, 'required': False}, 'lt': {'schema': {'type': 'time'}, 'required': False}, 'gt': {'schema': {'type': 'time'}, 'required': False}, 'tz_constraint': {'schema': {'type': 'union', 'choices': [{'type': 'literal', 'expected': ['aware', 'naive']}, {'type': 'int'}]}, 'required': False}, 'microseconds_precision': {'schema': {'type': 'literal', 'expected': ['truncate', 'error']}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'datetime': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['datetime']}, 'required': True}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'le': {'schema': {'type': 'datetime'}, 'required': False}, 'ge': {'schema': {'type': 'datetime'}, 'required': False}, 'lt': {'schema': {'type': 'datetime'}, 'required': False}, 'gt': {'schema': {'type': 'datetime'}, 'required': False}, 'now_op': {'schema': {'type': 'literal', 'expected': ['past', 'future']}, 'required': False}, 'tz_constraint': {'schema': {'type': 'union', 'choices': [{'type': 'literal', 'expected': ['aware', 'naive']}, {'type': 'int'}]}, 'required': False}, 'now_utc_offset': {'schema': {'type': 'int', 'gt': -86400, 'lt': 86400}, 'required': False}, 'microseconds_precision': {'schema': {'type': 'literal', 'expected': ['truncate', 'error']}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'timedelta': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['timedelta']}, 'required': True}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'le': {'schema': {'type': 'timedelta'}, 'required': False}, 'ge': {'schema': {'type': 'timedelta'}, 'required': False}, 'lt': {'schema': {'type': 'timedelta'}, 'required': False}, 'gt': {'schema': {'type': 'timedelta'}, 'required': False}, 'microseconds_precision': {'schema': {'type': 'literal', 'expected': ['truncate', 'error']}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'literal': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['literal']}, 'required': True}, 'expected': {'schema': {'type': 'list', 'items_schema': {'type': 'any'}}, 'required': True}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'enum': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['enum']}, 'required': True}, 'cls': {'schema': {'type': 'any'}, 'required': True}, 'members': {'schema': {'type': 'list', 'items_schema': {'type': 'any'}}, 'required': True}, 'sub_type': {'schema': {'type': 'literal', 'expected': ['str', 'int', 'float']}, 'required': False}, 'missing': {'schema': {'type': 'callable'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'is-instance': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['is-instance']}, 'required': True}, 'cls': {'schema': {'type': 'any'}, 'required': True}, 'cls_repr': {'schema': {'type': 'str'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'is-subclass': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['is-subclass']}, 'required': True}, 'cls': {'schema': {'type': 'any'}, 'required': True}, 'cls_repr': {'schema': {'type': 'str'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'callable': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['callable']}, 'required': True}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'list': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['list']}, 'required': True}, 'items_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'min_length': {'schema': {'type': 'int'}, 'required': False}, 'max_length': {'schema': {'type': 'int'}, 'required': False}, 'fail_fast': {'schema': {'type': 'bool'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'tagged-union', 'discriminator': 'type', 'choices': {'include-exclude-sequence': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['include-exclude-sequence']}, 'required': True}, 'include': {'schema': {'type': 'set', 'items_schema': {'type': 'int'}}, 'required': False}, 'exclude': {'schema': {'type': 'set', 'items_schema': {'type': 'int'}}, 'required': False}}, 'extra_behavior': 'forbid'}, 'none': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'int': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'bool': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'float': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'str': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'bytes': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'bytearray': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'list': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'tuple': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'set': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'frozenset': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'generator': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'dict': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'datetime': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'date': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'time': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'timedelta': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'url': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'multi-host-url': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'json': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'uuid': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'any': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'function-plain': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['function-plain']}, 'required': True}, 'function': {'schema': {'type': 'union', 'choices': [{'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}]}, 'required': True}, 'is_field_serializer': {'schema': {'type': 'bool'}, 'required': False}, 'info_arg': {'schema': {'type': 'bool'}, 'required': False}, 'return_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'function-wrap': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['function-wrap']}, 'required': True}, 'function': {'schema': {'type': 'union', 'choices': [{'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}]}, 'required': True}, 'is_field_serializer': {'schema': {'type': 'bool'}, 'required': False}, 'info_arg': {'schema': {'type': 'bool'}, 'required': False}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'return_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'format': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['format']}, 'required': True}, 'formatting_string': {'schema': {'type': 'str'}, 'required': True}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'to-string': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['to-string']}, 'required': True}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'model': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['model']}, 'required': True}, 'cls': {'schema': {'type': 'any'}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}}, 'extra_behavior': 'forbid'}}}, 'required': False}}, 'extra_behavior': 'forbid'}, 'tuple': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['tuple']}, 'required': True}, 'items_schema': {'schema': {'type': 'list', 'items_schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}}, 'required': True}, 'variadic_item_index': {'schema': {'type': 'int'}, 'required': False}, 'min_length': {'schema': {'type': 'int'}, 'required': False}, 'max_length': {'schema': {'type': 'int'}, 'required': False}, 'fail_fast': {'schema': {'type': 'bool'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'tagged-union', 'discriminator': 'type', 'choices': {'include-exclude-sequence': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['include-exclude-sequence']}, 'required': True}, 'include': {'schema': {'type': 'set', 'items_schema': {'type': 'int'}}, 'required': False}, 'exclude': {'schema': {'type': 'set', 'items_schema': {'type': 'int'}}, 'required': False}}, 'extra_behavior': 'forbid'}, 'none': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'int': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'bool': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'float': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'str': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'bytes': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'bytearray': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'list': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'tuple': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'set': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'frozenset': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'generator': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'dict': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'datetime': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'date': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'time': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'timedelta': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'url': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'multi-host-url': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'json': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'uuid': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'any': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'function-plain': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['function-plain']}, 'required': True}, 'function': {'schema': {'type': 'union', 'choices': [{'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}]}, 'required': True}, 'is_field_serializer': {'schema': {'type': 'bool'}, 'required': False}, 'info_arg': {'schema': {'type': 'bool'}, 'required': False}, 'return_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'function-wrap': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['function-wrap']}, 'required': True}, 'function': {'schema': {'type': 'union', 'choices': [{'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}]}, 'required': True}, 'is_field_serializer': {'schema': {'type': 'bool'}, 'required': False}, 'info_arg': {'schema': {'type': 'bool'}, 'required': False}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'return_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'format': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['format']}, 'required': True}, 'formatting_string': {'schema': {'type': 'str'}, 'required': True}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'to-string': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['to-string']}, 'required': True}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'model': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['model']}, 'required': True}, 'cls': {'schema': {'type': 'any'}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}}, 'extra_behavior': 'forbid'}}}, 'required': False}}, 'extra_behavior': 'forbid'}, 'set': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['set']}, 'required': True}, 'items_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'min_length': {'schema': {'type': 'int'}, 'required': False}, 'max_length': {'schema': {'type': 'int'}, 'required': False}, 'fail_fast': {'schema': {'type': 'bool'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'frozenset': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['frozenset']}, 'required': True}, 'items_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'min_length': {'schema': {'type': 'int'}, 'required': False}, 'max_length': {'schema': {'type': 'int'}, 'required': False}, 'fail_fast': {'schema': {'type': 'bool'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'generator': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['generator']}, 'required': True}, 'items_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'min_length': {'schema': {'type': 'int'}, 'required': False}, 'max_length': {'schema': {'type': 'int'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'tagged-union', 'discriminator': 'type', 'choices': {'include-exclude-sequence': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['include-exclude-sequence']}, 'required': True}, 'include': {'schema': {'type': 'set', 'items_schema': {'type': 'int'}}, 'required': False}, 'exclude': {'schema': {'type': 'set', 'items_schema': {'type': 'int'}}, 'required': False}}, 'extra_behavior': 'forbid'}, 'none': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'int': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'bool': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'float': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'str': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'bytes': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'bytearray': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'list': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'tuple': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'set': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'frozenset': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'generator': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'dict': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'datetime': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'date': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'time': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'timedelta': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'url': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'multi-host-url': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'json': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'uuid': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'any': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'function-plain': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['function-plain']}, 'required': True}, 'function': {'schema': {'type': 'union', 'choices': [{'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}]}, 'required': True}, 'is_field_serializer': {'schema': {'type': 'bool'}, 'required': False}, 'info_arg': {'schema': {'type': 'bool'}, 'required': False}, 'return_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'function-wrap': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['function-wrap']}, 'required': True}, 'function': {'schema': {'type': 'union', 'choices': [{'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}]}, 'required': True}, 'is_field_serializer': {'schema': {'type': 'bool'}, 'required': False}, 'info_arg': {'schema': {'type': 'bool'}, 'required': False}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'return_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'format': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['format']}, 'required': True}, 'formatting_string': {'schema': {'type': 'str'}, 'required': True}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'to-string': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['to-string']}, 'required': True}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'model': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['model']}, 'required': True}, 'cls': {'schema': {'type': 'any'}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}}, 'extra_behavior': 'forbid'}}}, 'required': False}}, 'extra_behavior': 'forbid'}, 'dict': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['dict']}, 'required': True}, 'keys_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'values_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'min_length': {'schema': {'type': 'int'}, 'required': False}, 'max_length': {'schema': {'type': 'int'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'tagged-union', 'discriminator': 'type', 'choices': {'include-exclude-dict': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['include-exclude-dict']}, 'required': True}, 'include': {'schema': {'type': 'set', 'items_schema': {'type': 'union', 'choices': [{'type': 'int'}, {'type': 'str'}]}}, 'required': False}, 'exclude': {'schema': {'type': 'set', 'items_schema': {'type': 'union', 'choices': [{'type': 'int'}, {'type': 'str'}]}}, 'required': False}}, 'extra_behavior': 'forbid'}, 'none': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'int': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'bool': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'float': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'str': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'bytes': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'bytearray': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'list': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'tuple': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'set': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'frozenset': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'generator': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'dict': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'datetime': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'date': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'time': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'timedelta': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'url': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'multi-host-url': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'json': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'uuid': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'any': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'function-plain': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['function-plain']}, 'required': True}, 'function': {'schema': {'type': 'union', 'choices': [{'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}]}, 'required': True}, 'is_field_serializer': {'schema': {'type': 'bool'}, 'required': False}, 'info_arg': {'schema': {'type': 'bool'}, 'required': False}, 'return_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'function-wrap': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['function-wrap']}, 'required': True}, 'function': {'schema': {'type': 'union', 'choices': [{'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}]}, 'required': True}, 'is_field_serializer': {'schema': {'type': 'bool'}, 'required': False}, 'info_arg': {'schema': {'type': 'bool'}, 'required': False}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'return_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'format': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['format']}, 'required': True}, 'formatting_string': {'schema': {'type': 'str'}, 'required': True}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'to-string': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['to-string']}, 'required': True}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'model': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['model']}, 'required': True}, 'cls': {'schema': {'type': 'any'}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}}, 'extra_behavior': 'forbid'}}}, 'required': False}}, 'extra_behavior': 'forbid'}, 'function-after': {'type': 'typed-dict', 'fields': {'function': {'schema': {'type': 'union', 'choices': [{'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['no-info']}, 'required': True}, 'function': {'schema': {'type': 'callable'}, 'required': True}}, 'extra_behavior': 'forbid'}, {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['with-info']}, 'required': True}, 'function': {'schema': {'type': 'callable'}, 'required': True}, 'field_name': {'schema': {'type': 'str'}, 'required': False}}, 'extra_behavior': 'forbid'}]}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}, 'type': {'schema': {'type': 'literal', 'expected': ['function-after']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'function-before': {'type': 'typed-dict', 'fields': {'function': {'schema': {'type': 'union', 'choices': [{'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['no-info']}, 'required': True}, 'function': {'schema': {'type': 'callable'}, 'required': True}}, 'extra_behavior': 'forbid'}, {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['with-info']}, 'required': True}, 'function': {'schema': {'type': 'callable'}, 'required': True}, 'field_name': {'schema': {'type': 'str'}, 'required': False}}, 'extra_behavior': 'forbid'}]}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}, 'type': {'schema': {'type': 'literal', 'expected': ['function-before']}, 'required': True}, 'json_schema_input_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'function-wrap': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['function-wrap']}, 'required': True}, 'function': {'schema': {'type': 'union', 'choices': [{'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['no-info']}, 'required': True}, 'function': {'schema': {'type': 'callable'}, 'required': True}}, 'extra_behavior': 'forbid'}, {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['with-info']}, 'required': True}, 'function': {'schema': {'type': 'callable'}, 'required': True}, 'field_name': {'schema': {'type': 'str'}, 'required': False}}, 'extra_behavior': 'forbid'}]}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'json_schema_input_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'function-plain': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['function-plain']}, 'required': True}, 'function': {'schema': {'type': 'union', 'choices': [{'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['no-info']}, 'required': True}, 'function': {'schema': {'type': 'callable'}, 'required': True}}, 'extra_behavior': 'forbid'}, {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['with-info']}, 'required': True}, 'function': {'schema': {'type': 'callable'}, 'required': True}, 'field_name': {'schema': {'type': 'str'}, 'required': False}}, 'extra_behavior': 'forbid'}]}, 'required': True}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'json_schema_input_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'default': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['default']}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'default': {'schema': {'type': 'any'}, 'required': False}, 'default_factory': {'schema': {'type': 'union', 'choices': [{'type': 'callable'}, {'type': 'callable'}]}, 'required': False}, 'default_factory_takes_data': {'schema': {'type': 'bool'}, 'required': False}, 'on_error': {'schema': {'type': 'literal', 'expected': ['raise', 'omit', 'default']}, 'required': False}, 'validate_default': {'schema': {'type': 'bool'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'nullable': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['nullable']}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'union': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['union']}, 'required': True}, 'choices': {'schema': {'type': 'list', 'items_schema': {'type': 'union', 'choices': [{'type': 'definition-ref', 'schema_ref': 'root-schema'}, {'type': 'tuple', 'items_schema': [{'type': 'definition-ref', 'schema_ref': 'root-schema'}, {'type': 'str'}]}]}}, 'required': True}, 'auto_collapse': {'schema': {'type': 'bool'}, 'required': False}, 'custom_error_type': {'schema': {'type': 'str'}, 'required': False}, 'custom_error_message': {'schema': {'type': 'str'}, 'required': False}, 'custom_error_context': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'int'}, {'type': 'float'}]}}, 'required': False}, 'mode': {'schema': {'type': 'literal', 'expected': ['smart', 'left_to_right']}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'tagged-union': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['tagged-union']}, 'required': True}, 'choices': {'schema': {'type': 'dict', 'keys_schema': {'type': 'any'}, 'values_schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}}, 'required': True}, 'discriminator': {'schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'list', 'items_schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'int'}]}}, {'type': 'list', 'items_schema': {'type': 'list', 'items_schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'int'}]}}}, {'type': 'callable'}]}, 'required': True}, 'custom_error_type': {'schema': {'type': 'str'}, 'required': False}, 'custom_error_message': {'schema': {'type': 'str'}, 'required': False}, 'custom_error_context': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'int'}, {'type': 'float'}]}}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'from_attributes': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'chain': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['chain']}, 'required': True}, 'steps': {'schema': {'type': 'list', 'items_schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}}, 'required': True}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'lax-or-strict': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['lax-or-strict']}, 'required': True}, 'lax_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'strict_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'json-or-python': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['json-or-python']}, 'required': True}, 'json_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'python_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'typed-dict': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['typed-dict']}, 'required': True}, 'fields': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['typed-dict-field']}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'required': {'schema': {'type': 'bool'}, 'required': False}, 'validation_alias': {'schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'list', 'items_schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'int'}]}}, {'type': 'list', 'items_schema': {'type': 'list', 'items_schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'int'}]}}}]}, 'required': False}, 'serialization_alias': {'schema': {'type': 'str'}, 'required': False}, 'serialization_exclude': {'schema': {'type': 'bool'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}}, 'extra_behavior': 'forbid'}}, 'required': True}, 'cls': {'schema': {'type': 'any'}, 'required': False}, 'cls_name': {'schema': {'type': 'str'}, 'required': False}, 'computed_fields': {'schema': {'type': 'list', 'items_schema': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['computed-field']}, 'required': True}, 'property_name': {'schema': {'type': 'str'}, 'required': True}, 'return_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'alias': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}}, 'extra_behavior': 'forbid'}}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'extras_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'extra_behavior': {'schema': {'type': 'literal', 'expected': ['allow', 'forbid', 'ignore']}, 'required': False}, 'total': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}, 'config': {'schema': {'type': 'typed-dict', 'fields': {'title': {'schema': {'type': 'str'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'extra_fields_behavior': {'schema': {'type': 'literal', 'expected': ['allow', 'forbid', 'ignore']}, 'required': False}, 'typed_dict_total': {'schema': {'type': 'bool'}, 'required': False}, 'from_attributes': {'schema': {'type': 'bool'}, 'required': False}, 'loc_by_alias': {'schema': {'type': 'bool'}, 'required': False}, 'revalidate_instances': {'schema': {'type': 'literal', 'expected': ['always', 'never', 'subclass-instances']}, 'required': False}, 'validate_default': {'schema': {'type': 'bool'}, 'required': False}, 'str_max_length': {'schema': {'type': 'int'}, 'required': False}, 'str_min_length': {'schema': {'type': 'int'}, 'required': False}, 'str_strip_whitespace': {'schema': {'type': 'bool'}, 'required': False}, 'str_to_lower': {'schema': {'type': 'bool'}, 'required': False}, 'str_to_upper': {'schema': {'type': 'bool'}, 'required': False}, 'allow_inf_nan': {'schema': {'type': 'bool'}, 'required': False}, 'ser_json_timedelta': {'schema': {'type': 'literal', 'expected': ['iso8601', 'float']}, 'required': False}, 'ser_json_bytes': {'schema': {'type': 'literal', 'expected': ['utf8', 'base64', 'hex']}, 'required': False}, 'ser_json_inf_nan': {'schema': {'type': 'literal', 'expected': ['null', 'constants', 'strings']}, 'required': False}, 'val_json_bytes': {'schema': {'type': 'literal', 'expected': ['utf8', 'base64', 'hex']}, 'required': False}, 'hide_input_in_errors': {'schema': {'type': 'bool'}, 'required': False}, 'validation_error_cause': {'schema': {'type': 'bool'}, 'required': False}, 'coerce_numbers_to_str': {'schema': {'type': 'bool'}, 'required': False}, 'regex_engine': {'schema': {'type': 'literal', 'expected': ['rust-regex', 'python-re']}, 'required': False}, 'cache_strings': {'schema': {'type': 'union', 'choices': [{'type': 'bool'}, {'type': 'literal', 'expected': ['all', 'keys', 'none']}]}, 'required': False}, 'validate_by_alias': {'schema': {'type': 'bool'}, 'required': False}, 'validate_by_name': {'schema': {'type': 'bool'}, 'required': False}, 'serialize_by_alias': {'schema': {'type': 'bool'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'model-fields': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['model-fields']}, 'required': True}, 'fields': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['model-field']}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'validation_alias': {'schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'list', 'items_schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'int'}]}}, {'type': 'list', 'items_schema': {'type': 'list', 'items_schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'int'}]}}}]}, 'required': False}, 'serialization_alias': {'schema': {'type': 'str'}, 'required': False}, 'serialization_exclude': {'schema': {'type': 'bool'}, 'required': False}, 'frozen': {'schema': {'type': 'bool'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}}, 'extra_behavior': 'forbid'}}, 'required': True}, 'model_name': {'schema': {'type': 'str'}, 'required': False}, 'computed_fields': {'schema': {'type': 'list', 'items_schema': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['computed-field']}, 'required': True}, 'property_name': {'schema': {'type': 'str'}, 'required': True}, 'return_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'alias': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}}, 'extra_behavior': 'forbid'}}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'extras_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'extras_keys_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'extra_behavior': {'schema': {'type': 'literal', 'expected': ['allow', 'forbid', 'ignore']}, 'required': False}, 'from_attributes': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'model': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['model']}, 'required': True}, 'cls': {'schema': {'type': 'any'}, 'required': True}, 'generic_origin': {'schema': {'type': 'any'}, 'required': False}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'custom_init': {'schema': {'type': 'bool'}, 'required': False}, 'root_model': {'schema': {'type': 'bool'}, 'required': False}, 'post_init': {'schema': {'type': 'str'}, 'required': False}, 'revalidate_instances': {'schema': {'type': 'literal', 'expected': ['always', 'never', 'subclass-instances']}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'frozen': {'schema': {'type': 'bool'}, 'required': False}, 'extra_behavior': {'schema': {'type': 'literal', 'expected': ['allow', 'forbid', 'ignore']}, 'required': False}, 'config': {'schema': {'type': 'typed-dict', 'fields': {'title': {'schema': {'type': 'str'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'extra_fields_behavior': {'schema': {'type': 'literal', 'expected': ['allow', 'forbid', 'ignore']}, 'required': False}, 'typed_dict_total': {'schema': {'type': 'bool'}, 'required': False}, 'from_attributes': {'schema': {'type': 'bool'}, 'required': False}, 'loc_by_alias': {'schema': {'type': 'bool'}, 'required': False}, 'revalidate_instances': {'schema': {'type': 'literal', 'expected': ['always', 'never', 'subclass-instances']}, 'required': False}, 'validate_default': {'schema': {'type': 'bool'}, 'required': False}, 'str_max_length': {'schema': {'type': 'int'}, 'required': False}, 'str_min_length': {'schema': {'type': 'int'}, 'required': False}, 'str_strip_whitespace': {'schema': {'type': 'bool'}, 'required': False}, 'str_to_lower': {'schema': {'type': 'bool'}, 'required': False}, 'str_to_upper': {'schema': {'type': 'bool'}, 'required': False}, 'allow_inf_nan': {'schema': {'type': 'bool'}, 'required': False}, 'ser_json_timedelta': {'schema': {'type': 'literal', 'expected': ['iso8601', 'float']}, 'required': False}, 'ser_json_bytes': {'schema': {'type': 'literal', 'expected': ['utf8', 'base64', 'hex']}, 'required': False}, 'ser_json_inf_nan': {'schema': {'type': 'literal', 'expected': ['null', 'constants', 'strings']}, 'required': False}, 'val_json_bytes': {'schema': {'type': 'literal', 'expected': ['utf8', 'base64', 'hex']}, 'required': False}, 'hide_input_in_errors': {'schema': {'type': 'bool'}, 'required': False}, 'validation_error_cause': {'schema': {'type': 'bool'}, 'required': False}, 'coerce_numbers_to_str': {'schema': {'type': 'bool'}, 'required': False}, 'regex_engine': {'schema': {'type': 'literal', 'expected': ['rust-regex', 'python-re']}, 'required': False}, 'cache_strings': {'schema': {'type': 'union', 'choices': [{'type': 'bool'}, {'type': 'literal', 'expected': ['all', 'keys', 'none']}]}, 'required': False}, 'validate_by_alias': {'schema': {'type': 'bool'}, 'required': False}, 'validate_by_name': {'schema': {'type': 'bool'}, 'required': False}, 'serialize_by_alias': {'schema': {'type': 'bool'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'dataclass-args': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['dataclass-args']}, 'required': True}, 'dataclass_name': {'schema': {'type': 'str'}, 'required': True}, 'fields': {'schema': {'type': 'list', 'items_schema': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['dataclass-field']}, 'required': True}, 'name': {'schema': {'type': 'str'}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'kw_only': {'schema': {'type': 'bool'}, 'required': False}, 'init': {'schema': {'type': 'bool'}, 'required': False}, 'init_only': {'schema': {'type': 'bool'}, 'required': False}, 'frozen': {'schema': {'type': 'bool'}, 'required': False}, 'validation_alias': {'schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'list', 'items_schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'int'}]}}, {'type': 'list', 'items_schema': {'type': 'list', 'items_schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'int'}]}}}]}, 'required': False}, 'serialization_alias': {'schema': {'type': 'str'}, 'required': False}, 'serialization_exclude': {'schema': {'type': 'bool'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}}, 'extra_behavior': 'forbid'}}, 'required': True}, 'computed_fields': {'schema': {'type': 'list', 'items_schema': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['computed-field']}, 'required': True}, 'property_name': {'schema': {'type': 'str'}, 'required': True}, 'return_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'alias': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}}, 'extra_behavior': 'forbid'}}, 'required': False}, 'collect_init_only': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}, 'extra_behavior': {'schema': {'type': 'literal', 'expected': ['allow', 'forbid', 'ignore']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'dataclass': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['dataclass']}, 'required': True}, 'cls': {'schema': {'type': 'any'}, 'required': True}, 'generic_origin': {'schema': {'type': 'any'}, 'required': False}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'fields': {'schema': {'type': 'list', 'items_schema': {'type': 'str'}}, 'required': True}, 'cls_name': {'schema': {'type': 'str'}, 'required': False}, 'post_init': {'schema': {'type': 'bool'}, 'required': False}, 'revalidate_instances': {'schema': {'type': 'literal', 'expected': ['always', 'never', 'subclass-instances']}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'frozen': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}, 'slots': {'schema': {'type': 'bool'}, 'required': False}, 'config': {'schema': {'type': 'typed-dict', 'fields': {'title': {'schema': {'type': 'str'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'extra_fields_behavior': {'schema': {'type': 'literal', 'expected': ['allow', 'forbid', 'ignore']}, 'required': False}, 'typed_dict_total': {'schema': {'type': 'bool'}, 'required': False}, 'from_attributes': {'schema': {'type': 'bool'}, 'required': False}, 'loc_by_alias': {'schema': {'type': 'bool'}, 'required': False}, 'revalidate_instances': {'schema': {'type': 'literal', 'expected': ['always', 'never', 'subclass-instances']}, 'required': False}, 'validate_default': {'schema': {'type': 'bool'}, 'required': False}, 'str_max_length': {'schema': {'type': 'int'}, 'required': False}, 'str_min_length': {'schema': {'type': 'int'}, 'required': False}, 'str_strip_whitespace': {'schema': {'type': 'bool'}, 'required': False}, 'str_to_lower': {'schema': {'type': 'bool'}, 'required': False}, 'str_to_upper': {'schema': {'type': 'bool'}, 'required': False}, 'allow_inf_nan': {'schema': {'type': 'bool'}, 'required': False}, 'ser_json_timedelta': {'schema': {'type': 'literal', 'expected': ['iso8601', 'float']}, 'required': False}, 'ser_json_bytes': {'schema': {'type': 'literal', 'expected': ['utf8', 'base64', 'hex']}, 'required': False}, 'ser_json_inf_nan': {'schema': {'type': 'literal', 'expected': ['null', 'constants', 'strings']}, 'required': False}, 'val_json_bytes': {'schema': {'type': 'literal', 'expected': ['utf8', 'base64', 'hex']}, 'required': False}, 'hide_input_in_errors': {'schema': {'type': 'bool'}, 'required': False}, 'validation_error_cause': {'schema': {'type': 'bool'}, 'required': False}, 'coerce_numbers_to_str': {'schema': {'type': 'bool'}, 'required': False}, 'regex_engine': {'schema': {'type': 'literal', 'expected': ['rust-regex', 'python-re']}, 'required': False}, 'cache_strings': {'schema': {'type': 'union', 'choices': [{'type': 'bool'}, {'type': 'literal', 'expected': ['all', 'keys', 'none']}]}, 'required': False}, 'validate_by_alias': {'schema': {'type': 'bool'}, 'required': False}, 'validate_by_name': {'schema': {'type': 'bool'}, 'required': False}, 'serialize_by_alias': {'schema': {'type': 'bool'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'arguments': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['arguments']}, 'required': True}, 'arguments_schema': {'schema': {'type': 'list', 'items_schema': {'type': 'typed-dict', 'fields': {'name': {'schema': {'type': 'str'}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'mode': {'schema': {'type': 'literal', 'expected': ['positional_only', 'positional_or_keyword', 'keyword_only']}, 'required': False}, 'alias': {'schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'list', 'items_schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'int'}]}}, {'type': 'list', 'items_schema': {'type': 'list', 'items_schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'int'}]}}}]}, 'required': False}}, 'extra_behavior': 'forbid'}}, 'required': True}, 'validate_by_name': {'schema': {'type': 'bool'}, 'required': False}, 'validate_by_alias': {'schema': {'type': 'bool'}, 'required': False}, 'var_args_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'var_kwargs_mode': {'schema': {'type': 'literal', 'expected': ['uniform', 'unpacked-typed-dict']}, 'required': False}, 'var_kwargs_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'arguments-v3': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['arguments-v3']}, 'required': True}, 'arguments_schema': {'schema': {'type': 'list', 'items_schema': {'type': 'typed-dict', 'fields': {'name': {'schema': {'type': 'str'}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'mode': {'schema': {'type': 'literal', 'expected': ['positional_only', 'positional_or_keyword', 'keyword_only', 'var_args', 'var_kwargs_uniform', 'var_kwargs_unpacked_typed_dict']}, 'required': False}, 'alias': {'schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'list', 'items_schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'int'}]}}, {'type': 'list', 'items_schema': {'type': 'list', 'items_schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'int'}]}}}]}, 'required': False}}, 'extra_behavior': 'forbid'}}, 'required': True}, 'validate_by_name': {'schema': {'type': 'bool'}, 'required': False}, 'validate_by_alias': {'schema': {'type': 'bool'}, 'required': False}, 'extra_behavior': {'schema': {'type': 'literal', 'expected': ['forbid', 'ignore']}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'call': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['call']}, 'required': True}, 'arguments_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'function': {'schema': {'type': 'callable'}, 'required': True}, 'function_name': {'schema': {'type': 'str'}, 'required': False}, 'return_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'custom-error': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['custom-error']}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'custom_error_type': {'schema': {'type': 'str'}, 'required': True}, 'custom_error_message': {'schema': {'type': 'str'}, 'required': False}, 'custom_error_context': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'union', 'choices': [{'type': 'str'}, {'type': 'int'}, {'type': 'float'}]}}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'json': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['json']}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'url': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['url']}, 'required': True}, 'max_length': {'schema': {'type': 'int'}, 'required': False}, 'allowed_schemes': {'schema': {'type': 'list', 'items_schema': {'type': 'str'}}, 'required': False}, 'host_required': {'schema': {'type': 'bool'}, 'required': False}, 'default_host': {'schema': {'type': 'str'}, 'required': False}, 'default_port': {'schema': {'type': 'int'}, 'required': False}, 'default_path': {'schema': {'type': 'str'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'multi-host-url': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['multi-host-url']}, 'required': True}, 'max_length': {'schema': {'type': 'int'}, 'required': False}, 'allowed_schemes': {'schema': {'type': 'list', 'items_schema': {'type': 'str'}}, 'required': False}, 'host_required': {'schema': {'type': 'bool'}, 'required': False}, 'default_host': {'schema': {'type': 'str'}, 'required': False}, 'default_port': {'schema': {'type': 'int'}, 'required': False}, 'default_path': {'schema': {'type': 'str'}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'definitions': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['definitions']}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}, 'definitions': {'schema': {'type': 'list', 'items_schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}}, 'required': True}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'definition-ref': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['definition-ref']}, 'required': True}, 'schema_ref': {'schema': {'type': 'str'}, 'required': True}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'uuid': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['uuid']}, 'required': True}, 'version': {'schema': {'type': 'literal', 'expected': [1, 3, 4, 5, 7]}, 'required': False}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}, 'complex': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['complex']}, 'required': True}, 'strict': {'schema': {'type': 'bool'}, 'required': False}, 'ref': {'schema': {'type': 'str'}, 'required': False}, 'metadata': {'schema': {'type': 'dict', 'keys_schema': {'type': 'str'}, 'values_schema': {'type': 'any'}}, 'required': False}, 'serialization': {'schema': {'type': 'definition-ref', 'schema_ref': 'ser-schema'}, 'required': False}}, 'extra_behavior': 'forbid'}}, 'discriminator': 'type', 'ref': 'root-schema'}, {'type': 'tagged-union', 'discriminator': 'type', 'choices': {'none': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'int': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'bool': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'float': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'str': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'bytes': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'bytearray': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'list': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'tuple': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'set': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'frozenset': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'generator': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'dict': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'datetime': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'date': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'time': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'timedelta': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'url': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'multi-host-url': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'json': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'uuid': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'any': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['none', 'int', 'bool', 'float', 'str', 'bytes', 'bytearray', 'list', 'tuple', 'set', 'frozenset', 'generator', 'dict', 'datetime', 'date', 'time', 'timedelta', 'url', 'multi-host-url', 'json', 'uuid', 'any']}, 'required': True}}, 'extra_behavior': 'forbid'}, 'function-plain': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['function-plain']}, 'required': True}, 'function': {'schema': {'type': 'union', 'choices': [{'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}]}, 'required': True}, 'is_field_serializer': {'schema': {'type': 'bool'}, 'required': False}, 'info_arg': {'schema': {'type': 'bool'}, 'required': False}, 'return_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'function-wrap': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['function-wrap']}, 'required': True}, 'function': {'schema': {'type': 'union', 'choices': [{'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}, {'type': 'callable'}]}, 'required': True}, 'is_field_serializer': {'schema': {'type': 'bool'}, 'required': False}, 'info_arg': {'schema': {'type': 'bool'}, 'required': False}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'return_schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': False}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'format': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['format']}, 'required': True}, 'formatting_string': {'schema': {'type': 'str'}, 'required': True}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'to-string': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['to-string']}, 'required': True}, 'when_used': {'schema': {'type': 'literal', 'expected': ['always', 'unless-none', 'json', 'json-unless-none']}, 'required': False}}, 'extra_behavior': 'forbid'}, 'model': {'type': 'typed-dict', 'fields': {'type': {'schema': {'type': 'literal', 'expected': ['model']}, 'required': True}, 'cls': {'schema': {'type': 'any'}, 'required': True}, 'schema': {'schema': {'type': 'definition-ref', 'schema_ref': 'root-schema'}, 'required': True}}, 'extra_behavior': 'forbid'}}, 'ref': 'ser-schema'}]} diff --git a/src/serializers/computed_fields.rs b/src/serializers/computed_fields.rs index 6e6786d73..7a574093c 100644 --- a/src/serializers/computed_fields.rs +++ b/src/serializers/computed_fields.rs @@ -2,13 +2,12 @@ use pyo3::prelude::*; use pyo3::types::{PyDict, PyList, PyString}; use pyo3::{intern, PyTraverseError, PyVisit}; use serde::ser::SerializeMap; -use serde::Serialize; use crate::build_tools::py_schema_error_type; use crate::definitions::DefinitionsBuilder; use crate::py_gc::PyGcTraverse; use crate::serializers::filter::SchemaFilter; -use crate::serializers::shared::{BuildSerializer, CombinedSerializer, PydanticSerializer, TypeSerializer}; +use crate::serializers::shared::{BuildSerializer, CombinedSerializer, PydanticSerializer}; use crate::tools::SchemaDict; use super::errors::py_err_se_err; @@ -48,18 +47,31 @@ impl ComputedFields { exclude: Option<&Bound<'_, PyAny>>, extra: &Extra, ) -> PyResult<()> { - if extra.round_trip { - // Do not serialize computed fields - return Ok(()); - } - for computed_field in &self.0 { - let field_extra = Extra { - field_name: Some(computed_field.property_name.as_str()), - ..*extra - }; - computed_field.to_python(model, output_dict, filter, include, exclude, &field_extra)?; - } - Ok(()) + self.serialize_fields( + model, + filter, + include, + exclude, + extra, + |e| e, + |ComputedFieldToSerialize { + computed_field, + value, + include, + exclude, + field_extra, + }| { + let key = match field_extra.serialize_by_alias_or(computed_field.serialize_by_alias) { + true => computed_field.alias_py.bind(model.py()), + false => computed_field.property_name_py.bind(model.py()), + }; + let value = + computed_field + .serializer + .to_python(&value, include.as_ref(), exclude.as_ref(), &field_extra)?; + output_dict.set_item(key, value) + }, + ) } pub fn serde_serialize( @@ -71,6 +83,49 @@ impl ComputedFields { exclude: Option<&Bound<'_, PyAny>>, extra: &Extra, ) -> Result<(), S::Error> { + self.serialize_fields( + model, + filter, + include, + exclude, + extra, + py_err_se_err, + |ComputedFieldToSerialize { + computed_field, + value, + include, + exclude, + field_extra, + }| { + let key = match field_extra.serialize_by_alias_or(computed_field.serialize_by_alias) { + true => &computed_field.alias, + false => &computed_field.property_name, + }; + let s = PydanticSerializer::new( + &value, + &computed_field.serializer, + include.as_ref(), + exclude.as_ref(), + &field_extra, + ); + map.serialize_entry(key, &s) + }, + ) + } + + /// Iterate each field for serialization, filtering on + /// `include` and `exclude` if provided. + #[allow(clippy::too_many_arguments)] + fn serialize_fields<'a, 'py, E>( + &'a self, + model: &'a Bound<'py, PyAny>, + filter: &'a SchemaFilter, + include: Option<&'a Bound<'py, PyAny>>, + exclude: Option<&'a Bound<'py, PyAny>>, + extra: &'a Extra, + convert_error: impl FnOnce(PyErr) -> E, + mut serialize: impl FnMut(ComputedFieldToSerialize<'a, 'py>) -> Result<(), E>, + ) -> Result<(), E> { if extra.round_trip { // Do not serialize computed fields return Ok(()); @@ -78,37 +133,46 @@ impl ComputedFields { for computed_field in &self.0 { let property_name_py = computed_field.property_name_py.bind(model.py()); + let (next_include, next_exclude) = match filter.key_filter(property_name_py, include, exclude) { + Ok(Some((next_include, next_exclude))) => (next_include, next_exclude), + Ok(None) => continue, + Err(e) => return Err(convert_error(e)), + }; - if let Some((next_include, next_exclude)) = filter - .key_filter(property_name_py, include, exclude) - .map_err(py_err_se_err)? - { - let value = model.getattr(property_name_py).map_err(py_err_se_err)?; - if extra.exclude_none && value.is_none() { - continue; + let value = match model.getattr(property_name_py) { + Ok(field_value) => field_value, + Err(e) => { + return Err(convert_error(e)); } - let field_extra = Extra { - field_name: Some(computed_field.property_name.as_str()), - ..*extra - }; - let cfs = ComputedFieldSerializer { - model, - computed_field, - include: next_include.as_ref(), - exclude: next_exclude.as_ref(), - extra: &field_extra, - }; - let key = match extra.serialize_by_alias_or(computed_field.serialize_by_alias) { - true => computed_field.alias.as_str(), - false => computed_field.property_name.as_str(), - }; - map.serialize_entry(key, &cfs)?; + }; + if extra.exclude_none && value.is_none() { + continue; } + + let field_extra = Extra { + field_name: Some(&computed_field.property_name), + ..*extra + }; + serialize(ComputedFieldToSerialize { + computed_field, + value, + include: next_include, + exclude: next_exclude, + field_extra, + })?; } Ok(()) } } +struct ComputedFieldToSerialize<'a, 'py> { + computed_field: &'a ComputedField, + value: Bound<'py, PyAny>, + include: Option>, + exclude: Option>, + field_extra: Extra<'a>, +} + #[derive(Debug)] struct ComputedField { property_name: String, @@ -143,44 +207,6 @@ impl ComputedField { serialize_by_alias: config.get_as(intern!(py, "serialize_by_alias"))?, }) } - - fn to_python( - &self, - model: &Bound<'_, PyAny>, - output_dict: &Bound<'_, PyDict>, - filter: &SchemaFilter, - include: Option<&Bound<'_, PyAny>>, - exclude: Option<&Bound<'_, PyAny>>, - extra: &Extra, - ) -> PyResult<()> { - let py = model.py(); - let property_name_py = self.property_name_py.bind(py); - - if let Some((next_include, next_exclude)) = filter.key_filter(property_name_py, include, exclude)? { - let next_value = model.getattr(property_name_py)?; - - let value = self - .serializer - .to_python(&next_value, next_include.as_ref(), next_exclude.as_ref(), extra)?; - if extra.exclude_none && value.is_none(py) { - return Ok(()); - } - let key = match extra.serialize_by_alias_or(self.serialize_by_alias) { - true => self.alias_py.bind(py), - false => property_name_py, - }; - output_dict.set_item(key, value)?; - } - Ok(()) - } -} - -pub(crate) struct ComputedFieldSerializer<'py> { - model: &'py Bound<'py, PyAny>, - computed_field: &'py ComputedField, - include: Option<&'py Bound<'py, PyAny>>, - exclude: Option<&'py Bound<'py, PyAny>>, - extra: &'py Extra<'py>, } impl_py_gc_traverse!(ComputedField { serializer }); @@ -190,21 +216,3 @@ impl PyGcTraverse for ComputedFields { self.0.py_gc_traverse(visit) } } - -impl_py_gc_traverse!(ComputedFieldSerializer<'_> { computed_field }); - -impl Serialize for ComputedFieldSerializer<'_> { - fn serialize(&self, serializer: S) -> Result { - let py = self.model.py(); - let property_name_py = self.computed_field.property_name_py.bind(py); - let next_value = self.model.getattr(property_name_py).map_err(py_err_se_err)?; - let s = PydanticSerializer::new( - &next_value, - &self.computed_field.serializer, - self.include, - self.exclude, - self.extra, - ); - s.serialize(serializer) - } -} diff --git a/src/serializers/errors.rs b/src/serializers/errors.rs index 5f736c11b..c309b9e3a 100644 --- a/src/serializers/errors.rs +++ b/src/serializers/errors.rs @@ -1,4 +1,5 @@ use std::fmt; +use std::fmt::Write; use pyo3::exceptions::PyValueError; use pyo3::prelude::*; @@ -80,6 +81,7 @@ impl PydanticSerializationError { #[pymethods] impl PydanticSerializationError { #[new] + #[pyo3(signature = (message, /))] fn py_new(message: String) -> Self { Self { message } } @@ -138,7 +140,7 @@ impl PydanticSerializationUnexpectedValue { #[pymethods] impl PydanticSerializationUnexpectedValue { #[new] - #[pyo3(signature = (message=None, field_type=None, input_value=None))] + #[pyo3(signature = (message=None, field_type=None, input_value=None, /))] fn py_new(message: Option, field_type: Option, input_value: Option) -> Self { Self { message, @@ -154,7 +156,7 @@ impl PydanticSerializationUnexpectedValue { if !message.is_empty() { message.push_str(": "); } - message.push_str(&format!("Expected `{field_type}`")); + write!(message, "Expected `{field_type}`").expect("writing to string should never fail"); if self.input_value.is_some() { message.push_str(" - serialized value may not be as expected"); } @@ -170,7 +172,8 @@ impl PydanticSerializationUnexpectedValue { let value_str = truncate_safe_repr(bound_input, None); - message.push_str(&format!(" [input_value={value_str}, input_type={input_type}]")); + write!(message, " [input_value={value_str}, input_type={input_type}]") + .expect("writing to string should never fail"); } if message.is_empty() { diff --git a/src/serializers/extra.rs b/src/serializers/extra.rs index 82c432342..e919beb8c 100644 --- a/src/serializers/extra.rs +++ b/src/serializers/extra.rs @@ -27,45 +27,6 @@ pub(crate) struct SerializationState { config: SerializationConfig, } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum DuckTypingSerMode { - // Don't check the type of the value, use the type of the schema - SchemaBased, - // Check the type of the value, use the type of the value - NeedsInference, - // We already checked the type of the value - // we don't want to infer again, but if we recurse down - // we do want to flip this back to NeedsInference for the - // fields / keys / items of any inner serializers - Inferred, -} - -impl DuckTypingSerMode { - pub fn from_bool(serialize_as_any: bool) -> Self { - if serialize_as_any { - DuckTypingSerMode::NeedsInference - } else { - DuckTypingSerMode::SchemaBased - } - } - - pub fn to_bool(self) -> bool { - match self { - DuckTypingSerMode::SchemaBased => false, - DuckTypingSerMode::NeedsInference => true, - DuckTypingSerMode::Inferred => true, - } - } - - pub fn next_mode(self) -> Self { - match self { - DuckTypingSerMode::SchemaBased => DuckTypingSerMode::SchemaBased, - DuckTypingSerMode::NeedsInference => DuckTypingSerMode::Inferred, - DuckTypingSerMode::Inferred => DuckTypingSerMode::NeedsInference, - } - } -} - impl SerializationState { pub fn new(timedelta_mode: &str, bytes_mode: &str, inf_nan_mode: &str) -> PyResult { let warnings = CollectWarnings::new(WarningsMode::None); @@ -88,7 +49,7 @@ impl SerializationState { round_trip: bool, serialize_unknown: bool, fallback: Option<&'py Bound<'_, PyAny>>, - duck_typing_ser_mode: DuckTypingSerMode, + serialize_as_any: bool, context: Option<&'py Bound<'_, PyAny>>, ) -> Extra<'py> { Extra::new( @@ -104,7 +65,7 @@ impl SerializationState { &self.rec_guard, serialize_unknown, fallback, - duck_typing_ser_mode, + serialize_as_any, context, ) } @@ -137,7 +98,7 @@ pub(crate) struct Extra<'a> { pub field_name: Option<&'a str>, pub serialize_unknown: bool, pub fallback: Option<&'a Bound<'a, PyAny>>, - pub duck_typing_ser_mode: DuckTypingSerMode, + pub serialize_as_any: bool, pub context: Option<&'a Bound<'a, PyAny>>, } @@ -156,7 +117,7 @@ impl<'a> Extra<'a> { rec_guard: &'a SerRecursionState, serialize_unknown: bool, fallback: Option<&'a Bound<'a, PyAny>>, - duck_typing_ser_mode: DuckTypingSerMode, + serialize_as_any: bool, context: Option<&'a Bound<'a, PyAny>>, ) -> Self { Self { @@ -175,7 +136,7 @@ impl<'a> Extra<'a> { field_name: None, serialize_unknown, fallback, - duck_typing_ser_mode, + serialize_as_any, context, } } @@ -243,7 +204,7 @@ pub(crate) struct ExtraOwned { field_name: Option, serialize_unknown: bool, pub fallback: Option, - duck_typing_ser_mode: DuckTypingSerMode, + serialize_as_any: bool, pub context: Option, } @@ -264,7 +225,7 @@ impl ExtraOwned { field_name: extra.field_name.map(ToString::to_string), serialize_unknown: extra.serialize_unknown, fallback: extra.fallback.map(|model| model.clone().into()), - duck_typing_ser_mode: extra.duck_typing_ser_mode, + serialize_as_any: extra.serialize_as_any, context: extra.context.map(|model| model.clone().into()), } } @@ -286,7 +247,7 @@ impl ExtraOwned { field_name: self.field_name.as_deref(), serialize_unknown: self.serialize_unknown, fallback: self.fallback.as_ref().map(|m| m.bind(py)), - duck_typing_ser_mode: self.duck_typing_ser_mode, + serialize_as_any: self.serialize_as_any, context: self.context.as_ref().map(|m| m.bind(py)), } } diff --git a/src/serializers/fields.rs b/src/serializers/fields.rs index b89468d4e..a5c5bc6b3 100644 --- a/src/serializers/fields.rs +++ b/src/serializers/fields.rs @@ -8,7 +8,6 @@ use serde::ser::SerializeMap; use smallvec::SmallVec; use crate::serializers::extra::SerCheck; -use crate::serializers::DuckTypingSerMode; use crate::PydanticSerializationUnexpectedValue; use super::computed_fields::ComputedFields; @@ -162,11 +161,6 @@ impl GeneralFieldsSerializer { let key_str = key_str(&key)?; let op_field = self.fields.get(key_str); if extra.exclude_none && value.is_none() { - if let Some(field) = op_field { - if field.required { - used_req_fields += 1; - } - } continue; } let field_extra = Extra { @@ -196,7 +190,7 @@ impl GeneralFieldsSerializer { Some(serializer) => { serializer.to_python(&value, next_include.as_ref(), next_exclude.as_ref(), &field_extra)? } - None => infer_to_python(&value, next_include.as_ref(), next_exclude.as_ref(), &field_extra)?, + _ => infer_to_python(&value, next_include.as_ref(), next_exclude.as_ref(), &field_extra)?, }; output_dict.set_item(key, value)?; } else if field_extra.check == SerCheck::Strict { @@ -337,20 +331,6 @@ impl TypeSerializer for GeneralFieldsSerializer { // If there is no model, we (a TypedDict) are the model let model = extra.model.map_or_else(|| Some(value), Some); - // If there is no model, use duck typing ser logic for TypedDict - // If there is a model, skip this step, as BaseModel and dataclass duck typing - // is handled in their respective serializers - if extra.model.is_none() { - let duck_typing_ser_mode = extra.duck_typing_ser_mode.next_mode(); - let td_extra = Extra { - model, - duck_typing_ser_mode, - ..*extra - }; - if td_extra.duck_typing_ser_mode == DuckTypingSerMode::Inferred { - return infer_to_python(value, include, exclude, &td_extra); - } - } let (main_dict, extra_dict) = if let Some(main_extra_dict) = self.extract_dicts(value) { main_extra_dict } else { @@ -372,7 +352,7 @@ impl TypeSerializer for GeneralFieldsSerializer { Some(serializer) => { serializer.to_python(&value, next_include.as_ref(), next_exclude.as_ref(), extra)? } - None => infer_to_python(&value, next_include.as_ref(), next_exclude.as_ref(), extra)?, + _ => infer_to_python(&value, next_include.as_ref(), next_exclude.as_ref(), extra)?, }; output_dict.set_item(key, value)?; } @@ -406,20 +386,6 @@ impl TypeSerializer for GeneralFieldsSerializer { // If there is no model, we (a TypedDict) are the model let model = extra.model.map_or_else(|| Some(value), Some); - // If there is no model, use duck typing ser logic for TypedDict - // If there is a model, skip this step, as BaseModel and dataclass duck typing - // is handled in their respective serializers - if extra.model.is_none() { - let duck_typing_ser_mode = extra.duck_typing_ser_mode.next_mode(); - let td_extra = Extra { - model, - duck_typing_ser_mode, - ..*extra - }; - if td_extra.duck_typing_ser_mode == DuckTypingSerMode::Inferred { - return infer_serialize(value, serializer, include, exclude, &td_extra); - } - } let expected_len = match self.mode { FieldsMode::TypedDictAllow => main_dict.len() + self.computed_field_count(), _ => self.fields.len() + option_length!(extra_dict) + self.computed_field_count(), diff --git a/src/serializers/filter.rs b/src/serializers/filter.rs index 65ec4062d..7f893726a 100644 --- a/src/serializers/filter.rs +++ b/src/serializers/filter.rs @@ -320,7 +320,7 @@ where /// detect both ellipsis and `True` to be compatible with pydantic V1 fn is_ellipsis_like(v: &Bound<'_, PyAny>) -> bool { - v.is(&v.py().Ellipsis()) + v.is(v.py().Ellipsis()) || match v.downcast::() { Ok(b) => b.is_true(), Err(_) => false, diff --git a/src/serializers/infer.rs b/src/serializers/infer.rs index 33f53b290..eb067b81d 100644 --- a/src/serializers/infer.rs +++ b/src/serializers/infer.rs @@ -21,7 +21,7 @@ use super::errors::{py_err_se_err, PydanticSerializationError}; use super::extra::{Extra, SerMode}; use super::filter::{AnyFilter, SchemaFilter}; use super::ob_type::ObType; -use super::shared::{any_dataclass_iter, PydanticSerializer, TypeSerializer}; +use super::shared::any_dataclass_iter; use super::SchemaSerializer; pub(crate) fn infer_to_python( @@ -106,10 +106,14 @@ pub(crate) fn infer_to_python_known( extra.rec_guard, extra.serialize_unknown, extra.fallback, - extra.duck_typing_ser_mode, + extra.serialize_as_any, extra.context, ); - serializer.serializer.to_python(value, include, exclude, &extra) + // Avoid falling immediately back into inference because we need to use the serializer + // to drive the next step of serialization + serializer + .serializer + .to_python_no_infer(value, include, exclude, &extra) }; let value = match extra.mode { @@ -140,10 +144,14 @@ pub(crate) fn infer_to_python_known( .into_py_any(py)?, ObType::Bytearray => { let py_byte_array = value.downcast::()?; - // Safety: the GIL is held while bytes_to_string is running; it doesn't run - // arbitrary Python code, so py_byte_array cannot be mutated. - let bytes = unsafe { py_byte_array.as_bytes() }; - extra.config.bytes_mode.bytes_to_string(py, bytes)?.into_py_any(py)? + pyo3::sync::with_critical_section(py_byte_array, || { + // SAFETY: `py_byte_array` is protected by a critical section, + // which guarantees no mutation, and `bytes_to_string` does not + // run any code which could cause the critical section to be + // released. + let bytes = unsafe { py_byte_array.as_bytes() }; + extra.config.bytes_mode.bytes_to_string(py, bytes)?.into_py_any(py) + })? } ObType::Tuple => { let elements = serialize_seq_filter!(PyTuple); @@ -432,12 +440,14 @@ pub(crate) fn infer_serialize_known( } ObType::Bytearray => { let py_byte_array = value.downcast::().map_err(py_err_se_err)?; - // Safety: the GIL is held while serialize_bytes is running; it doesn't run - // arbitrary Python code, so py_byte_array cannot be mutated. - extra - .config - .bytes_mode - .serialize_bytes(unsafe { py_byte_array.as_bytes() }, serializer) + pyo3::sync::with_critical_section(py_byte_array, || { + // SAFETY: `py_byte_array` is protected by a critical section, + // which guarantees no mutation, and `serialize_bytes` does not + // run any code which could cause the critical section to be + // released. + let bytes = unsafe { py_byte_array.as_bytes() }; + extra.config.bytes_mode.serialize_bytes(bytes, serializer) + }) } ObType::Dict => { let dict = value.downcast::().map_err(py_err_se_err)?; @@ -483,6 +493,7 @@ pub(crate) fn infer_serialize_known( .getattr(intern!(py, "__pydantic_serializer__")) .map_err(py_err_se_err)?; let extracted_serializer: PyRef = py_serializer.extract().map_err(py_err_se_err)?; + let extra = extracted_serializer.build_extra( py, extra.mode, @@ -495,12 +506,14 @@ pub(crate) fn infer_serialize_known( extra.rec_guard, extra.serialize_unknown, extra.fallback, - extra.duck_typing_ser_mode, + extra.serialize_as_any, extra.context, ); - let pydantic_serializer = - PydanticSerializer::new(value, &extracted_serializer.serializer, include, exclude, &extra); - pydantic_serializer.serialize(serializer) + // Avoid falling immediately back into inference because we need to use the serializer + // to drive the next step of serialization + extracted_serializer + .serializer + .serde_serialize_no_infer(value, serializer, include, exclude, &extra) } ObType::Dataclass => { let (pairs_iter, fields_dict) = any_dataclass_iter(value).map_err(py_err_se_err)?; @@ -612,15 +625,15 @@ pub(crate) fn infer_json_key_known<'a>( .bytes_to_string(key.py(), key.downcast::()?.as_bytes()), ObType::Bytearray => { let py_byte_array = key.downcast::()?; - // Safety: the GIL is held while serialize_bytes is running; it doesn't run - // arbitrary Python code, so py_byte_array cannot be mutated during the call. - // - // We copy the bytes into a new buffer immediately afterwards - extra - .config - .bytes_mode - .bytes_to_string(key.py(), unsafe { py_byte_array.as_bytes() }) - .map(|cow| Cow::Owned(cow.into_owned())) + pyo3::sync::with_critical_section(py_byte_array, || { + // SAFETY: `py_byte_array` is protected by a critical section, + // which guarantees no mutation, and `bytes_to_string` does not + // run any code which could cause the critical section to be + // released. + let bytes = unsafe { py_byte_array.as_bytes() }; + extra.config.bytes_mode.bytes_to_string(key.py(), bytes) + }) + .map(|cow| Cow::Owned(cow.into_owned())) } ObType::Datetime => { let iso_dt = super::type_serializers::datetime_etc::datetime_to_string(key.downcast()?)?; diff --git a/src/serializers/mod.rs b/src/serializers/mod.rs index 434b43c53..f9b51496f 100644 --- a/src/serializers/mod.rs +++ b/src/serializers/mod.rs @@ -4,6 +4,7 @@ use std::sync::atomic::{AtomicUsize, Ordering}; use pyo3::prelude::*; use pyo3::types::{PyBytes, PyDict, PyTuple, PyType}; use pyo3::{PyTraverseError, PyVisit}; +use type_serializers::any::AnySerializer; use crate::definitions::{Definitions, DefinitionsBuilder}; use crate::py_gc::PyGcTraverse; @@ -12,9 +13,9 @@ pub(crate) use config::BytesMode; use config::SerializationConfig; pub use errors::{PydanticSerializationError, PydanticSerializationUnexpectedValue}; use extra::{CollectWarnings, SerRecursionState, WarningsMode}; -pub(crate) use extra::{DuckTypingSerMode, Extra, SerMode, SerializationState}; +pub(crate) use extra::{Extra, SerMode, SerializationState}; +use shared::to_json_bytes; pub use shared::CombinedSerializer; -use shared::{to_json_bytes, BuildSerializer, TypeSerializer}; mod computed_fields; mod config; @@ -63,7 +64,7 @@ impl SchemaSerializer { rec_guard: &'a SerRecursionState, serialize_unknown: bool, fallback: Option<&'a Bound<'a, PyAny>>, - duck_typing_ser_mode: DuckTypingSerMode, + serialize_as_any: bool, context: Option<&'a Bound<'a, PyAny>>, ) -> Extra<'b> { Extra::new( @@ -79,7 +80,7 @@ impl SchemaSerializer { rec_guard, serialize_unknown, fallback, - duck_typing_ser_mode, + serialize_as_any, context, ) } @@ -91,7 +92,7 @@ impl SchemaSerializer { #[pyo3(signature = (schema, config=None))] pub fn py_new(schema: Bound<'_, PyDict>, config: Option<&Bound<'_, PyDict>>) -> PyResult { let mut definitions_builder = DefinitionsBuilder::new(); - let serializer = CombinedSerializer::build(schema.downcast()?, config, &mut definitions_builder)?; + let serializer = CombinedSerializer::build_base(schema.downcast()?, config, &mut definitions_builder)?; Ok(Self { serializer, definitions: definitions_builder.finish()?, @@ -133,7 +134,6 @@ impl SchemaSerializer { }; let warnings = CollectWarnings::new(warnings_mode); let rec_guard = SerRecursionState::default(); - let duck_typing_ser_mode = DuckTypingSerMode::from_bool(serialize_as_any); let extra = self.build_extra( py, &mode, @@ -146,7 +146,7 @@ impl SchemaSerializer { &rec_guard, false, fallback, - duck_typing_ser_mode, + serialize_as_any, context, ); let v = self.serializer.to_python(value, include, exclude, &extra)?; @@ -155,7 +155,7 @@ impl SchemaSerializer { } #[allow(clippy::too_many_arguments)] - #[pyo3(signature = (value, *, indent = None, include = None, exclude = None, by_alias = None, + #[pyo3(signature = (value, *, indent = None, ensure_ascii = false, include = None, exclude = None, by_alias = None, exclude_unset = false, exclude_defaults = false, exclude_none = false, round_trip = false, warnings = WarningsArg::Bool(true), fallback = None, serialize_as_any = false, context = None))] pub fn to_json( @@ -163,6 +163,7 @@ impl SchemaSerializer { py: Python, value: &Bound<'_, PyAny>, indent: Option, + ensure_ascii: Option, include: Option<&Bound<'_, PyAny>>, exclude: Option<&Bound<'_, PyAny>>, by_alias: Option, @@ -181,7 +182,6 @@ impl SchemaSerializer { }; let warnings = CollectWarnings::new(warnings_mode); let rec_guard = SerRecursionState::default(); - let duck_typing_ser_mode = DuckTypingSerMode::from_bool(serialize_as_any); let extra = self.build_extra( py, &SerMode::Json, @@ -194,7 +194,7 @@ impl SchemaSerializer { &rec_guard, false, fallback, - duck_typing_ser_mode, + serialize_as_any, context, ); let bytes = to_json_bytes( @@ -204,6 +204,7 @@ impl SchemaSerializer { exclude, &extra, indent, + ensure_ascii.unwrap_or(false), self.expected_json_size.load(Ordering::Relaxed), )?; @@ -239,7 +240,7 @@ impl SchemaSerializer { #[allow(clippy::too_many_arguments)] #[pyfunction] -#[pyo3(signature = (value, *, indent = None, include = None, exclude = None, by_alias = true, +#[pyo3(signature = (value, *, indent = None, ensure_ascii = false, include = None, exclude = None, by_alias = true, exclude_none = false, round_trip = false, timedelta_mode = "iso8601", bytes_mode = "utf8", inf_nan_mode = "constants", serialize_unknown = false, fallback = None, serialize_as_any = false, context = None))] @@ -247,6 +248,7 @@ pub fn to_json( py: Python, value: &Bound<'_, PyAny>, indent: Option, + ensure_ascii: Option, include: Option<&Bound<'_, PyAny>>, exclude: Option<&Bound<'_, PyAny>>, by_alias: bool, @@ -261,7 +263,6 @@ pub fn to_json( context: Option<&Bound<'_, PyAny>>, ) -> PyResult { let state = SerializationState::new(timedelta_mode, bytes_mode, inf_nan_mode)?; - let duck_typing_ser_mode = DuckTypingSerMode::from_bool(serialize_as_any); let extra = state.extra( py, &SerMode::Json, @@ -270,11 +271,19 @@ pub fn to_json( round_trip, serialize_unknown, fallback, - duck_typing_ser_mode, + serialize_as_any, context, ); - let serializer = type_serializers::any::AnySerializer.into(); - let bytes = to_json_bytes(value, &serializer, include, exclude, &extra, indent, 1024)?; + let bytes = to_json_bytes( + value, + AnySerializer::get(), + include, + exclude, + &extra, + indent, + ensure_ascii.unwrap_or(false), + 1024, + )?; state.final_check(py)?; let py_bytes = PyBytes::new(py, &bytes); Ok(py_bytes.into()) @@ -302,7 +311,6 @@ pub fn to_jsonable_python( context: Option<&Bound<'_, PyAny>>, ) -> PyResult { let state = SerializationState::new(timedelta_mode, bytes_mode, inf_nan_mode)?; - let duck_typing_ser_mode = DuckTypingSerMode::from_bool(serialize_as_any); let extra = state.extra( py, &SerMode::Json, @@ -311,7 +319,7 @@ pub fn to_jsonable_python( round_trip, serialize_unknown, fallback, - duck_typing_ser_mode, + serialize_as_any, context, ); let v = infer::infer_to_python(value, include, exclude, &extra)?; diff --git a/src/serializers/prebuilt.rs b/src/serializers/prebuilt.rs index 3f1cf1c68..323dbe2e9 100644 --- a/src/serializers/prebuilt.rs +++ b/src/serializers/prebuilt.rs @@ -39,11 +39,11 @@ impl TypeSerializer for PrebuiltSerializer { self.schema_serializer .get() .serializer - .to_python(value, include, exclude, extra) + .to_python_no_infer(value, include, exclude, extra) } fn json_key<'a>(&self, key: &'a Bound<'_, PyAny>, extra: &Extra) -> PyResult> { - self.schema_serializer.get().serializer.json_key(key, extra) + self.schema_serializer.get().serializer.json_key_no_infer(key, extra) } fn serde_serialize( @@ -57,7 +57,7 @@ impl TypeSerializer for PrebuiltSerializer { self.schema_serializer .get() .serializer - .serde_serialize(value, serializer, include, exclude, extra) + .serde_serialize_no_infer(value, serializer, include, exclude, extra) } fn get_name(&self) -> &str { diff --git a/src/serializers/shared.rs b/src/serializers/shared.rs index f7a018749..81a673dde 100644 --- a/src/serializers/shared.rs +++ b/src/serializers/shared.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; use std::fmt::Debug; +use std::io::{self, Write}; use pyo3::exceptions::PyTypeError; use pyo3::prelude::*; @@ -9,7 +10,7 @@ use pyo3::{intern, PyTraverseError, PyVisit}; use enum_dispatch::enum_dispatch; use serde::Serialize; -use serde_json::ser::PrettyFormatter; +use serde_json::ser::{Formatter, PrettyFormatter}; use crate::build_tools::py_schema_err; use crate::build_tools::py_schema_error_type; @@ -20,7 +21,7 @@ use crate::tools::{py_err, SchemaDict}; use super::errors::se_err_py_err; use super::extra::Extra; -use super::infer::infer_json_key; +use super::infer::{infer_json_key, infer_serialize, infer_to_python}; use super::ob_type::{IsType, ObType}; pub(crate) trait BuildSerializer: Sized { @@ -149,10 +150,21 @@ combined_serializer! { } impl CombinedSerializer { + // Used when creating the base serializer instance, to avoid reusing the instance + // when unpickling: + pub fn build_base( + schema: &Bound<'_, PyDict>, + config: Option<&Bound<'_, PyDict>>, + definitions: &mut DefinitionsBuilder, + ) -> PyResult { + Self::_build(schema, config, definitions, false) + } + fn _build( schema: &Bound<'_, PyDict>, config: Option<&Bound<'_, PyDict>>, definitions: &mut DefinitionsBuilder, + use_prebuilt: bool, ) -> PyResult { let py = schema.py(); let type_key = intern!(py, "type"); @@ -199,13 +211,85 @@ impl CombinedSerializer { let type_: Bound<'_, PyString> = schema.get_as_req(type_key)?; let type_ = type_.to_str()?; - // if we have a SchemaValidator on the type already, use it - if let Ok(Some(prebuilt_serializer)) = super::prebuilt::PrebuiltSerializer::try_get_from_schema(type_, schema) { - return Ok(prebuilt_serializer); + if use_prebuilt { + // if we have a SchemaValidator on the type already, use it + if let Ok(Some(prebuilt_serializer)) = + super::prebuilt::PrebuiltSerializer::try_get_from_schema(type_, schema) + { + return Ok(prebuilt_serializer); + } } Self::find_serializer(type_, schema, config, definitions) } + + /// Main recursive way to call serializers, supports possible recursive type inference by + /// switching to type inference mode eagerly. + pub fn to_python( + &self, + value: &Bound<'_, PyAny>, + include: Option<&Bound<'_, PyAny>>, + exclude: Option<&Bound<'_, PyAny>>, + extra: &Extra, + ) -> PyResult { + if extra.serialize_as_any { + infer_to_python(value, include, exclude, extra) + } else { + self.to_python_no_infer(value, include, exclude, extra) + } + } + + /// Variant of the above which does not fall back to inference mode immediately + #[inline] + pub fn to_python_no_infer( + &self, + value: &Bound<'_, PyAny>, + include: Option<&Bound<'_, PyAny>>, + exclude: Option<&Bound<'_, PyAny>>, + extra: &Extra, + ) -> PyResult { + TypeSerializer::to_python(self, value, include, exclude, extra) + } + + pub fn json_key<'a>(&self, key: &'a Bound<'_, PyAny>, extra: &Extra) -> PyResult> { + if extra.serialize_as_any { + infer_json_key(key, extra) + } else { + self.json_key_no_infer(key, extra) + } + } + + #[inline] + pub fn json_key_no_infer<'a>(&self, key: &'a Bound<'_, PyAny>, extra: &Extra) -> PyResult> { + TypeSerializer::json_key(self, key, extra) + } + + pub fn serde_serialize( + &self, + value: &Bound<'_, PyAny>, + serializer: S, + include: Option<&Bound<'_, PyAny>>, + exclude: Option<&Bound<'_, PyAny>>, + extra: &Extra, + ) -> Result { + if extra.serialize_as_any { + infer_serialize(value, serializer, include, exclude, extra) + } else { + self.serde_serialize_no_infer(value, serializer, include, exclude, extra) + } + } + + #[inline] + pub fn serde_serialize_no_infer( + &self, + value: &Bound<'_, PyAny>, + serializer: S, + include: Option<&Bound<'_, PyAny>>, + exclude: Option<&Bound<'_, PyAny>>, + extra: &Extra, + ) -> Result { + TypeSerializer::serde_serialize(self, value, serializer, include, exclude, extra) + } } impl BuildSerializer for CombinedSerializer { @@ -217,7 +301,7 @@ impl BuildSerializer for CombinedSerializer { config: Option<&Bound<'_, PyDict>>, definitions: &mut DefinitionsBuilder, ) -> PyResult { - Self::_build(schema, config, definitions) + Self::_build(schema, config, definitions, true) } } @@ -349,6 +433,87 @@ impl Serialize for PydanticSerializer<'_> { } } +struct EscapeNonAsciiFormatter; + +impl Formatter for EscapeNonAsciiFormatter { + fn write_string_fragment(&mut self, writer: &mut W, fragment: &str) -> io::Result<()> { + let mut input = fragment; + + while let Some((idx, non_ascii_char)) = input.chars().enumerate().find(|(_, c)| !c.is_ascii()) { + if idx > 0 { + // write all ascii characters before the non-ascii one + let ascii_run = &input[..idx]; + writer.write_all(ascii_run.as_bytes()).unwrap(); + } + + let codepoint = non_ascii_char as u32; + if codepoint < 0xFFFF { + // write basic codepoint as single escape + write!(writer, "\\u{codepoint:04x}").unwrap(); + } else { + // encode extended plane character as utf16 pair + for escape in non_ascii_char.encode_utf16(&mut [0; 2]) { + write!(writer, "\\u{escape:04x}").unwrap(); + } + } + + input = &input[(idx + non_ascii_char.len_utf8())..]; + } + + // write any ascii trailer + writer.write_all(input.as_bytes())?; + Ok(()) + } +} + +struct EscapeNonAsciiPrettyFormatter<'a> { + pretty: PrettyFormatter<'a>, + escape_non_ascii: EscapeNonAsciiFormatter, +} + +impl<'a> EscapeNonAsciiPrettyFormatter<'a> { + pub fn with_indent(indent: &'a [u8]) -> Self { + Self { + pretty: PrettyFormatter::with_indent(indent), + escape_non_ascii: EscapeNonAsciiFormatter, + } + } +} + +macro_rules! defer { + ($formatter:ident, $fun:ident) => { + fn $fun(&mut self, writer: &mut W) -> io::Result<()> + where + W: ?Sized + io::Write, + { + self.$formatter.$fun(writer) + } + }; + ($formatter:ident, $fun:ident, $val:ty) => { + fn $fun(&mut self, writer: &mut W, val: $val) -> io::Result<()> + where + W: ?Sized + io::Write, + { + self.$formatter.$fun(writer, val) + } + }; +} + +#[allow(clippy::needless_lifetimes)] +impl Formatter for EscapeNonAsciiPrettyFormatter<'_> { + defer!(escape_non_ascii, write_string_fragment, &str); + defer!(pretty, begin_array); + defer!(pretty, end_array); + defer!(pretty, begin_array_value, bool); + defer!(pretty, end_array_value); + defer!(pretty, begin_object); + defer!(pretty, end_object); + defer!(pretty, begin_object_key, bool); + defer!(pretty, end_object_key); + defer!(pretty, begin_object_value); + defer!(pretty, end_object_value); +} + #[allow(clippy::too_many_arguments)] pub(crate) fn to_json_bytes( value: &Bound<'_, PyAny>, @@ -357,25 +522,40 @@ pub(crate) fn to_json_bytes( exclude: Option<&Bound<'_, PyAny>>, extra: &Extra, indent: Option, + ensure_ascii: bool, expected_json_size: usize, ) -> PyResult> { let serializer = PydanticSerializer::new(value, serializer, include, exclude, extra); let writer: Vec = Vec::with_capacity(expected_json_size); - let bytes = match indent { - Some(indent) => { + + let bytes = match (indent, ensure_ascii) { + (Some(indent), true) => { + let indent = vec![b' '; indent]; + let formatter = EscapeNonAsciiPrettyFormatter::with_indent(&indent); + let mut ser = PythonSerializer::with_formatter(writer, formatter); + serializer.serialize(&mut ser).map_err(se_err_py_err)?; + ser.into_inner() + } + (Some(indent), false) => { let indent = vec![b' '; indent]; let formatter = PrettyFormatter::with_indent(&indent); let mut ser = PythonSerializer::with_formatter(writer, formatter); serializer.serialize(&mut ser).map_err(se_err_py_err)?; ser.into_inner() } - None => { + (None, true) => { + let mut ser = PythonSerializer::with_formatter(writer, EscapeNonAsciiFormatter); + serializer.serialize(&mut ser).map_err(se_err_py_err)?; + ser.into_inner() + } + (None, false) => { let mut ser = PythonSerializer::new(writer); serializer.serialize(&mut ser).map_err(se_err_py_err)?; ser.into_inner() } }; + Ok(bytes) } diff --git a/src/serializers/type_serializers/dataclass.rs b/src/serializers/type_serializers/dataclass.rs index a080a9b4f..996a80d72 100644 --- a/src/serializers/type_serializers/dataclass.rs +++ b/src/serializers/type_serializers/dataclass.rs @@ -8,7 +8,6 @@ use serde::ser::SerializeMap; use crate::build_tools::{py_schema_error_type, ExtraBehavior}; use crate::definitions::DefinitionsBuilder; -use crate::serializers::DuckTypingSerMode; use crate::tools::SchemaDict; use super::{ @@ -141,19 +140,11 @@ impl TypeSerializer for DataclassSerializer { extra: &Extra, ) -> PyResult { let model = Some(value); - let duck_typing_ser_mode = extra.duck_typing_ser_mode.next_mode(); - let dc_extra = Extra { - model, - duck_typing_ser_mode, - ..*extra - }; - if dc_extra.duck_typing_ser_mode == DuckTypingSerMode::Inferred { - return infer_to_python(value, include, exclude, &dc_extra); - } + let dc_extra = Extra { model, ..*extra }; if self.allow_value(value, &dc_extra)? { let py = value.py(); if let CombinedSerializer::Fields(ref fields_serializer) = *self.serializer { - let output_dict = fields_serializer.main_to_python( + let output_dict: Bound = fields_serializer.main_to_python( py, known_dataclass_iter(&self.fields, value), include, @@ -190,16 +181,8 @@ impl TypeSerializer for DataclassSerializer { exclude: Option<&Bound<'_, PyAny>>, extra: &Extra, ) -> Result { - let duck_typing_ser_mode = extra.duck_typing_ser_mode.next_mode(); let model = Some(value); - let dc_extra = Extra { - model, - duck_typing_ser_mode, - ..*extra - }; - if dc_extra.duck_typing_ser_mode == DuckTypingSerMode::Inferred { - return infer_serialize(value, serializer, include, exclude, &dc_extra); - } + let dc_extra = Extra { model, ..*extra }; if self.allow_value(value, &dc_extra).map_err(py_err_se_err)? { if let CombinedSerializer::Fields(ref fields_serializer) = *self.serializer { let expected_len = self.fields.len() + fields_serializer.computed_field_count(); diff --git a/src/serializers/type_serializers/definitions.rs b/src/serializers/type_serializers/definitions.rs index 38fd7cea5..4f517b6f2 100644 --- a/src/serializers/type_serializers/definitions.rs +++ b/src/serializers/type_serializers/definitions.rs @@ -94,12 +94,12 @@ impl TypeSerializer for DefinitionRefSerializer { self.definition.read(|comb_serializer| { let comb_serializer = comb_serializer.unwrap(); let mut guard = extra.recursion_guard(value, self.definition.id())?; - comb_serializer.to_python(value, include, exclude, guard.state()) + comb_serializer.to_python_no_infer(value, include, exclude, guard.state()) }) } fn json_key<'a>(&self, key: &'a Bound<'_, PyAny>, extra: &Extra) -> PyResult> { - self.definition.read(|s| s.unwrap().json_key(key, extra)) + self.definition.read(|s| s.unwrap().json_key_no_infer(key, extra)) } fn serde_serialize( @@ -115,7 +115,7 @@ impl TypeSerializer for DefinitionRefSerializer { let mut guard = extra .recursion_guard(value, self.definition.id()) .map_err(py_err_se_err)?; - comb_serializer.serde_serialize(value, serializer, include, exclude, guard.state()) + comb_serializer.serde_serialize_no_infer(value, serializer, include, exclude, guard.state()) }) } diff --git a/src/serializers/type_serializers/function.rs b/src/serializers/type_serializers/function.rs index 3c66583e2..9a351694c 100644 --- a/src/serializers/type_serializers/function.rs +++ b/src/serializers/type_serializers/function.rs @@ -497,6 +497,10 @@ impl SerializationCallable { value: &Bound<'_, PyAny>, index_key: Option<&Bound<'_, PyAny>>, ) -> PyResult> { + // NB wrap serializers have strong coupling to their inner type, + // so use to_python_no_infer so that type inference can't apply + // at this layer + let include = self.include.as_ref().map(|o| o.bind(py)); let exclude = self.exclude.as_ref().map(|o| o.bind(py)); let extra = self.extra_owned.to_extra(py); @@ -508,16 +512,16 @@ impl SerializationCallable { self.filter.key_filter(index_key, include, exclude)? }; if let Some((next_include, next_exclude)) = filter { - let v = self - .serializer - .to_python(value, next_include.as_ref(), next_exclude.as_ref(), &extra)?; + let v = + self.serializer + .to_python_no_infer(value, next_include.as_ref(), next_exclude.as_ref(), &extra)?; extra.warnings.final_check(py)?; Ok(Some(v)) } else { Err(PydanticOmit::new_err()) } } else { - let v = self.serializer.to_python(value, include, exclude, &extra)?; + let v = self.serializer.to_python_no_infer(value, include, exclude, &extra)?; extra.warnings.final_check(py)?; Ok(Some(v)) } @@ -581,7 +585,7 @@ impl SerializationInfo { exclude_none: extra.exclude_none, round_trip: extra.round_trip, field_name: Some(field_name.to_string()), - serialize_as_any: extra.duck_typing_ser_mode.to_bool(), + serialize_as_any: extra.serialize_as_any, }), _ => Err(PyRuntimeError::new_err( "Model field context expected for field serialization info but no model field was found", @@ -599,7 +603,7 @@ impl SerializationInfo { exclude_none: extra.exclude_none, round_trip: extra.round_trip, field_name: None, - serialize_as_any: extra.duck_typing_ser_mode.to_bool(), + serialize_as_any: extra.serialize_as_any, }) } } diff --git a/src/serializers/type_serializers/generator.rs b/src/serializers/type_serializers/generator.rs index 86379bade..0e5050c64 100644 --- a/src/serializers/type_serializers/generator.rs +++ b/src/serializers/type_serializers/generator.rs @@ -115,10 +115,7 @@ impl TypeSerializer for GeneratorSerializer { ) -> Result { match value.downcast::() { Ok(py_iter) => { - let len = match value.len() { - Ok(len) => Some(len), - Err(_) => None, - }; + let len = value.len().ok(); let mut seq = serializer.serialize_seq(len)?; let item_serializer = self.item_serializer.as_ref(); diff --git a/src/serializers/type_serializers/json.rs b/src/serializers/type_serializers/json.rs index 6b8b4294f..fb2a53f6b 100644 --- a/src/serializers/type_serializers/json.rs +++ b/src/serializers/type_serializers/json.rs @@ -54,7 +54,7 @@ impl TypeSerializer for JsonSerializer { extra: &Extra, ) -> PyResult { if extra.round_trip { - let bytes = to_json_bytes(value, &self.serializer, include, exclude, extra, None, 0)?; + let bytes = to_json_bytes(value, &self.serializer, include, exclude, extra, None, false, 0)?; let py = value.py(); let s = from_utf8(&bytes).map_err(|e| utf8_py_error(py, e, &bytes))?; Ok(PyString::new(py, s).into()) @@ -65,7 +65,7 @@ impl TypeSerializer for JsonSerializer { fn json_key<'a>(&self, key: &'a Bound<'_, PyAny>, extra: &Extra) -> PyResult> { if extra.round_trip { - let bytes = to_json_bytes(key, &self.serializer, None, None, extra, None, 0)?; + let bytes = to_json_bytes(key, &self.serializer, None, None, extra, None, false, 0)?; let py = key.py(); let s = from_utf8(&bytes).map_err(|e| utf8_py_error(py, e, &bytes))?; Ok(Cow::Owned(s.to_string())) @@ -83,8 +83,8 @@ impl TypeSerializer for JsonSerializer { extra: &Extra, ) -> Result { if extra.round_trip { - let bytes = - to_json_bytes(value, &self.serializer, include, exclude, extra, None, 0).map_err(py_err_se_err)?; + let bytes = to_json_bytes(value, &self.serializer, include, exclude, extra, None, false, 0) + .map_err(py_err_se_err)?; match from_utf8(&bytes) { Ok(s) => serializer.serialize_str(s), Err(e) => Err(Error::custom(e.to_string())), diff --git a/src/serializers/type_serializers/model.rs b/src/serializers/type_serializers/model.rs index 4bae243fc..21f7ce024 100644 --- a/src/serializers/type_serializers/model.rs +++ b/src/serializers/type_serializers/model.rs @@ -16,7 +16,6 @@ use crate::build_tools::py_schema_err; use crate::build_tools::{py_schema_error_type, ExtraBehavior}; use crate::definitions::DefinitionsBuilder; use crate::serializers::errors::PydanticSerializationUnexpectedValue; -use crate::serializers::extra::DuckTypingSerMode; use crate::tools::SchemaDict; const ROOT_FIELD: &str = "root"; @@ -171,16 +170,8 @@ impl TypeSerializer for ModelSerializer { extra: &Extra, ) -> PyResult { let model = Some(value); - let duck_typing_ser_mode = extra.duck_typing_ser_mode.next_mode(); - let model_extra = Extra { - model, - duck_typing_ser_mode, - ..*extra - }; - if model_extra.duck_typing_ser_mode == DuckTypingSerMode::Inferred { - return infer_to_python(value, include, exclude, &model_extra); - } + let model_extra = Extra { model, ..*extra }; if self.root_model { let field_name = Some(ROOT_FIELD); let root_extra = Extra { @@ -198,7 +189,10 @@ impl TypeSerializer for ModelSerializer { self.serializer.to_python(&root, include, exclude, &root_extra) } else if self.allow_value(value, &model_extra)? { let inner_value = self.get_inner_value(value, &model_extra)?; - self.serializer.to_python(&inner_value, include, exclude, &model_extra) + // There is strong coupling between a model serializer and its child, we should + // not fall back to type inference in the midddle. + self.serializer + .to_python_no_infer(&inner_value, include, exclude, &model_extra) } else { extra.warnings.on_fallback_py(self.get_name(), value, &model_extra)?; infer_to_python(value, include, exclude, &model_extra) @@ -223,15 +217,7 @@ impl TypeSerializer for ModelSerializer { extra: &Extra, ) -> Result { let model = Some(value); - let duck_typing_ser_mode = extra.duck_typing_ser_mode.next_mode(); - let model_extra = Extra { - model, - duck_typing_ser_mode, - ..*extra - }; - if model_extra.duck_typing_ser_mode == DuckTypingSerMode::Inferred { - return infer_serialize(value, serializer, include, exclude, &model_extra); - } + let model_extra = Extra { model, ..*extra }; if self.root_model { let field_name = Some(ROOT_FIELD); let root_extra = Extra { @@ -244,8 +230,10 @@ impl TypeSerializer for ModelSerializer { .serde_serialize(&root, serializer, include, exclude, &root_extra) } else if self.allow_value(value, &model_extra).map_err(py_err_se_err)? { let inner_value = self.get_inner_value(value, &model_extra).map_err(py_err_se_err)?; + // There is strong coupling between a model serializer and its child, we should + // not fall back to type inference in the midddle. self.serializer - .serde_serialize(&inner_value, serializer, include, exclude, &model_extra) + .serde_serialize_no_infer(&inner_value, serializer, include, exclude, &model_extra) } else { extra .warnings diff --git a/src/serializers/type_serializers/tuple.rs b/src/serializers/type_serializers/tuple.rs index e5e3da353..e6bc6d2f0 100644 --- a/src/serializers/type_serializers/tuple.rs +++ b/src/serializers/type_serializers/tuple.rs @@ -243,10 +243,10 @@ impl TupleSerializer { serializer: &CombinedSerializer::Any(AnySerializer), }) { return Ok(Err(e)); - }; + } } } - }; + } Ok(Ok(())) } } diff --git a/src/tools.rs b/src/tools.rs index 96146d30c..edf9b6bac 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -8,7 +8,7 @@ use pyo3::types::{PyDict, PyString}; use pyo3::{intern, FromPyObject}; use crate::input::Int; -use jiter::{cached_py_string, pystring_fast_new, StringCacheMode}; +use jiter::{cached_py_string, StringCacheMode}; pub trait SchemaDict<'py> { fn get_as(&self, key: &Bound<'py, PyString>) -> PyResult> @@ -129,14 +129,6 @@ pub fn truncate_safe_repr(v: &Bound<'_, PyAny>, max_len: Option) -> Strin } pub fn extract_i64(v: &Bound<'_, PyAny>) -> Option { - #[cfg(PyPy)] - if !v.is_instance_of::() { - // PyPy used __int__ to cast floats to ints after CPython removed it, - // see https://github.com/pypy/pypy/issues/4949 - // - // Can remove this after PyPy 7.3.17 is released - return None; - } v.extract().ok() } @@ -148,11 +140,10 @@ pub fn extract_int(v: &Bound<'_, PyAny>) -> Option { pub(crate) fn new_py_string<'py>(py: Python<'py>, s: &str, cache_str: StringCacheMode) -> Bound<'py, PyString> { // we could use `bytecount::num_chars(s.as_bytes()) == s.len()` as orjson does, but it doesn't appear to be faster - let ascii_only = false; if matches!(cache_str, StringCacheMode::All) { - cached_py_string(py, s, ascii_only) + cached_py_string(py, s) } else { - pystring_fast_new(py, s, ascii_only) + PyString::new(py, s) } } diff --git a/src/url.rs b/src/url.rs index 8d31fb27e..da63be5af 100644 --- a/src/url.rs +++ b/src/url.rs @@ -392,7 +392,7 @@ impl PyMultiHostUrl { multi_url.push_str(&single_host.to_string()); if index != hosts.len() - 1 { multi_url.push(','); - }; + } } multi_url } else if host.is_some() { @@ -456,7 +456,7 @@ impl fmt::Display for UrlHostParts { (None, Some(password)) => write!(f, ":{password}@")?, (Some(username), Some(password)) => write!(f, "{username}:{password}@")?, (None, None) => {} - }; + } if let Some(host) = &self.host { write!(f, "{host}")?; } diff --git a/src/validators/arguments.rs b/src/validators/arguments.rs index 7c397d69f..2ca3ba5f6 100644 --- a/src/validators/arguments.rs +++ b/src/validators/arguments.rs @@ -229,6 +229,9 @@ impl Validator for ArgumentsValidator { } } + let state = + &mut state.rebind_extra(|extra| extra.field_name = Some(PyString::new(py, parameter.name.as_str()))); + match (pos_value, kw_value) { (Some(_), Some((_, kw_value))) => { errors.push(ValLineError::new_with_loc( @@ -280,7 +283,7 @@ impl Validator for ArgumentsValidator { input, index, )); - }; + } } } } diff --git a/src/validators/dataclass.rs b/src/validators/dataclass.rs index 0f2cbefc7..9cfb9dbae 100644 --- a/src/validators/dataclass.rs +++ b/src/validators/dataclass.rs @@ -24,7 +24,7 @@ use super::{build_validator, BuildValidator, CombinedValidator, DefinitionsBuild struct Field { kw_only: bool, name: String, - py_name: Py, + name_py: Py, init: bool, init_only: bool, lookup_key_collection: LookupKeyCollection, @@ -72,8 +72,8 @@ impl BuildValidator for DataclassArgsValidator { for field in fields_schema { let field = field.downcast::()?; - let py_name: Bound<'_, PyString> = field.get_as_req(intern!(py, "name"))?; - let name: String = py_name.extract()?; + let name_py: Bound<'_, PyString> = field.get_as_req(intern!(py, "name"))?; + let name: String = name_py.extract()?; let schema = field.get_as_req(intern!(py, "schema"))?; @@ -99,7 +99,7 @@ impl BuildValidator for DataclassArgsValidator { fields.push(Field { kw_only, name, - py_name: py_name.into(), + name_py: name_py.into(), lookup_key_collection, validator, init: field.get_as(intern!(py, "init"))?.unwrap_or(true), @@ -163,13 +163,13 @@ impl Validator for DataclassArgsValidator { macro_rules! set_item { ($field:ident, $value:expr) => {{ - let py_name = $field.py_name.bind(py); + let name_py = $field.name_py.bind(py); if $field.init_only { if let Some(ref mut init_only_args) = init_only_args { init_only_args.push($value); } } else { - output_dict.set_item(py_name, $value)?; + output_dict.set_item(name_py, $value)?; } }}; } @@ -190,9 +190,9 @@ impl Validator for DataclassArgsValidator { // We could try to "fix" this in the future if desired. Err(ValError::LineErrors(line_errors)) => errors.extend(line_errors), Err(err) => return Err(err), - }; + } continue; - }; + } let mut pos_value = None; if let Some(args) = args.args() { @@ -214,6 +214,8 @@ impl Validator for DataclassArgsValidator { } let kw_value = kw_value.as_ref().map(|(path, value)| (path, value.borrow_input())); + let state = &mut state.rebind_extra(|extra| extra.field_name = Some(field.name_py.bind(py).clone())); + match (pos_value, kw_value) { // found both positional and keyword arguments, error (Some(_), Some((_, kw_value))) => { @@ -265,7 +267,7 @@ impl Validator for DataclassArgsValidator { &field.name, )); } - Err(ValError::Omit) => continue, + Err(ValError::Omit) => {} Err(ValError::LineErrors(line_errors)) => { for err in line_errors { // Note: this will always use the field name even if there is an alias @@ -399,16 +401,17 @@ impl Validator for DataclassArgsValidator { let data_dict = dict.copy()?; if let Err(err) = data_dict.del_item(field_name) { // KeyError is fine here as the field might not be in the dict - if !err.get_type(py).is(&PyType::new::(py)) { + if !err.get_type(py).is(PyType::new::(py)) { return Err(err.into()); } } - match field.validator.validate( - py, - field_value, - &mut state.rebind_extra(|extra| extra.data = Some(data_dict.clone())), - ) { + let state = &mut state.rebind_extra(|extra| { + extra.data = Some(data_dict.clone()); + extra.field_name = Some(field.name_py.bind(py).clone()); + }); + + match field.validator.validate(py, field_value, state) { Ok(output) => ok(output), Err(ValError::LineErrors(line_errors)) => { let errors = line_errors diff --git a/src/validators/datetime.rs b/src/validators/datetime.rs index d82a3dd6c..f6384cd2c 100644 --- a/src/validators/datetime.rs +++ b/src/validators/datetime.rs @@ -32,7 +32,7 @@ pub(crate) fn extract_microseconds_precision( schema_or_config_same(schema, config, intern!(schema.py(), "microseconds_precision"))? .map_or( Ok(speedate::MicrosecondsPrecisionOverflowBehavior::Truncate), - |v: Bound<'_, PyString>| speedate::MicrosecondsPrecisionOverflowBehavior::try_from(v.to_str().unwrap()), + |v: Bound<'_, PyString>| v.to_str().unwrap().parse(), ) .map_err(|_| { py_schema_error_type!("Invalid `microseconds_precision`, must be one of \"truncate\" or \"error\"") diff --git a/src/validators/decimal.rs b/src/validators/decimal.rs index 3d8c90c6e..a2a9e0b5b 100644 --- a/src/validators/decimal.rs +++ b/src/validators/decimal.rs @@ -194,7 +194,7 @@ impl Validator for DecimalValidator { } } } - }; + } } } diff --git a/src/validators/enum_.rs b/src/validators/enum_.rs index 0e34cb182..60f24d9d6 100644 --- a/src/validators/enum_.rs +++ b/src/validators/enum_.rs @@ -138,7 +138,7 @@ impl Validator for EnumValidator { // https://github.com/python/cpython/blob/v3.12.2/Lib/enum.py#L1148 if enum_value.is_instance(class)? { return Ok(enum_value.into()); - } else if !enum_value.is(&py.None()) { + } else if !enum_value.is(py.None()) { let type_error = PyTypeError::new_err(format!( "error in {}._missing_: returned {} instead of None or a valid member", class diff --git a/src/validators/function.rs b/src/validators/function.rs index 6f0eea7f4..ddb096054 100644 --- a/src/validators/function.rs +++ b/src/validators/function.rs @@ -100,7 +100,13 @@ impl FunctionBeforeValidator { state: &'s mut ValidationState<'_, 'py>, ) -> ValResult { let r = if self.info_arg { - let info = ValidationInfo::new(py, state.extra(), &self.config, self.field_name.clone()); + let field_name = state + .extra() + .field_name + .clone() + .map(Bound::unbind) + .or_else(|| self.field_name.clone()); + let info = ValidationInfo::new(py, state.extra(), &self.config, field_name); self.func.call1(py, (input.to_object(py)?, info)) } else { self.func.call1(py, (input.to_object(py)?,)) @@ -169,7 +175,13 @@ impl FunctionAfterValidator { ) -> ValResult { let v = call(input, state)?; let r = if self.info_arg { - let info = ValidationInfo::new(py, state.extra(), &self.config, self.field_name.clone()); + let field_name = state + .extra() + .field_name + .clone() + .map(Bound::unbind) + .or_else(|| self.field_name.clone()); + let info = ValidationInfo::new(py, state.extra(), &self.config, field_name); self.func.call1(py, (v, info)) } else { self.func.call1(py, (v,)) @@ -258,7 +270,13 @@ impl Validator for FunctionPlainValidator { state: &mut ValidationState<'_, 'py>, ) -> ValResult { let r = if self.info_arg { - let info = ValidationInfo::new(py, state.extra(), &self.config, self.field_name.clone()); + let field_name = state + .extra() + .field_name + .clone() + .map(Bound::unbind) + .or_else(|| self.field_name.clone()); + let info = ValidationInfo::new(py, state.extra(), &self.config, field_name); self.func.call1(py, (input.to_object(py)?, info)) } else { self.func.call1(py, (input.to_object(py)?,)) @@ -322,7 +340,13 @@ impl FunctionWrapValidator { state: &mut ValidationState<'_, 'py>, ) -> ValResult { let r = if self.info_arg { - let info = ValidationInfo::new(py, state.extra(), &self.config, self.field_name.clone()); + let field_name = state + .extra() + .field_name + .clone() + .map(Bound::unbind) + .or_else(|| self.field_name.clone()); + let info = ValidationInfo::new(py, state.extra(), &self.config, field_name); self.func.call1(py, (input.to_object(py)?, handler, info)) } else { self.func.call1(py, (input.to_object(py)?, handler)) @@ -356,7 +380,9 @@ impl Validator for FunctionWrapValidator { let handler = Bound::new(py, handler)?; #[allow(clippy::used_underscore_items)] let result = self._validate(handler.as_any(), py, input, state); - state.exactness = handler.borrow_mut().validator.exactness; + let handler = handler.borrow(); + state.exactness = handler.validator.exactness; + state.fields_set_count = handler.validator.fields_set_count; result } diff --git a/src/validators/generator.rs b/src/validators/generator.rs index bc0cbd82a..b4be4c68f 100644 --- a/src/validators/generator.rs +++ b/src/validators/generator.rs @@ -225,6 +225,7 @@ pub struct InternalValidator { self_instance: Option, recursion_guard: RecursionState, pub(crate) exactness: Option, + pub(crate) fields_set_count: Option, validation_mode: InputType, hide_input_in_errors: bool, validation_error_cause: bool, @@ -256,6 +257,7 @@ impl InternalValidator { self_instance: extra.self_instance.map(|d| d.clone().unbind()), recursion_guard: state.recursion_guard.clone(), exactness: state.exactness, + fields_set_count: state.fields_set_count, validation_mode: extra.input_type, hide_input_in_errors, validation_error_cause, @@ -276,6 +278,7 @@ impl InternalValidator { data: self.data.as_ref().map(|data| data.bind(py).clone()), strict: self.strict, from_attributes: self.from_attributes, + field_name: Some(PyString::new(py, field_name)), context: self.context.as_ref().map(|data| data.bind(py)), self_instance: self.self_instance.as_ref().map(|data| data.bind(py)), cache_str: self.cache_str, @@ -313,6 +316,7 @@ impl InternalValidator { data: self.data.as_ref().map(|data| data.bind(py).clone()), strict: self.strict, from_attributes: self.from_attributes, + field_name: None, context: self.context.as_ref().map(|data| data.bind(py)), self_instance: self.self_instance.as_ref().map(|data| data.bind(py)), cache_str: self.cache_str, @@ -321,6 +325,7 @@ impl InternalValidator { }; let mut state = ValidationState::new(extra, &mut self.recursion_guard, false.into()); state.exactness = self.exactness; + state.fields_set_count = self.fields_set_count; let result = self.validator.validate(py, input, &mut state).map_err(|e| { ValidationError::from_val_error( py, @@ -333,6 +338,7 @@ impl InternalValidator { ) }); self.exactness = state.exactness; + self.fields_set_count = state.fields_set_count; result } } diff --git a/src/validators/literal.rs b/src/validators/literal.rs index ffe615fe3..3da5e9d47 100644 --- a/src/validators/literal.rs +++ b/src/validators/literal.rs @@ -158,7 +158,7 @@ impl LiteralLookup { let id: usize = v.extract().unwrap(); return Ok(Some((input, &self.values[id]))); } - }; + } if let Some(expected_py_values) = &self.expected_py_values { let py_input = get_py_input()?; for (k, id) in expected_py_values { @@ -166,7 +166,7 @@ impl LiteralLookup { return Ok(Some((input, &self.values[*id]))); } } - }; + } // this one must be last to avoid conflicts with the other lookups, think of this // almost as a lax fallback @@ -179,7 +179,7 @@ impl LiteralLookup { let id: usize = v.extract().unwrap(); return Ok(Some((input, &self.values[id]))); } - }; + } Ok(None) } diff --git a/src/validators/mod.rs b/src/validators/mod.rs index f105e1854..2fd79c495 100644 --- a/src/validators/mod.rs +++ b/src/validators/mod.rs @@ -4,13 +4,11 @@ use enum_dispatch::enum_dispatch; use jiter::{PartialMode, StringCacheMode}; use pyo3::exceptions::PyTypeError; -use pyo3::ffi::c_str; -use pyo3::sync::GILOnceCell; use pyo3::types::{PyAny, PyDict, PyString, PyTuple, PyType}; use pyo3::{intern, PyTraverseError, PyVisit}; use pyo3::{prelude::*, IntoPyObjectExt}; -use crate::build_tools::{py_schema_err, py_schema_error_type, SchemaError}; +use crate::build_tools::{py_schema_err, py_schema_error_type}; use crate::definitions::{Definitions, DefinitionsBuilder}; use crate::errors::{LocItem, ValError, ValResult, ValidationError}; use crate::input::{Input, InputType, StringMapping}; @@ -127,7 +125,7 @@ impl SchemaValidator { pub fn py_new(py: Python, schema: &Bound<'_, PyAny>, config: Option<&Bound<'_, PyDict>>) -> PyResult { let mut definitions_builder = DefinitionsBuilder::new(); - let validator = build_validator(schema, config, &mut definitions_builder)?; + let validator = build_validator_base(schema, config, &mut definitions_builder)?; let definitions = definitions_builder.finish()?; let py_schema = schema.clone().unbind(); let py_config = match config { @@ -159,11 +157,6 @@ impl SchemaValidator { }) } - pub fn __reduce__<'py>(slf: &Bound<'py, Self>) -> PyResult<(Bound<'py, PyType>, Bound<'py, PyTuple>)> { - let init_args = (&slf.get().py_schema, &slf.get().py_config).into_pyobject(slf.py())?; - Ok((slf.get_type(), init_args)) - } - #[allow(clippy::too_many_arguments)] #[pyo3(signature = (input, *, strict=None, from_attributes=None, context=None, self_instance=None, allow_partial=PartialMode::Off, by_alias=None, by_name=None))] pub fn validate_python( @@ -311,6 +304,7 @@ impl SchemaValidator { data: None, strict, from_attributes, + field_name: Some(PyString::new(py, field_name)), context, self_instance: None, cache_str: self.cache_str, @@ -337,6 +331,7 @@ impl SchemaValidator { data: None, strict, from_attributes: None, + field_name: None, context, self_instance: None, cache_str: self.cache_str, @@ -355,6 +350,11 @@ impl SchemaValidator { } } + pub fn __reduce__<'py>(slf: &Bound<'py, Self>) -> PyResult<(Bound<'py, PyType>, Bound<'py, PyTuple>)> { + let init_args = (&slf.get().py_schema, &slf.get().py_config).into_pyobject(slf.py())?; + Ok((slf.get_type(), init_args)) + } + pub fn __repr__(&self, py: Python) -> String { format!( "SchemaValidator(title={:?}, validator={:#?}, definitions={:#?}, cache_strings={})", @@ -455,68 +455,6 @@ impl SchemaValidator { } } -static SCHEMA_DEFINITION: GILOnceCell = GILOnceCell::new(); - -#[derive(Debug, Clone)] -pub struct SelfValidator<'py> { - validator: &'py SchemaValidator, -} - -impl<'py> SelfValidator<'py> { - pub fn new(py: Python<'py>) -> PyResult { - let validator = SCHEMA_DEFINITION.get_or_init(py, || match Self::build(py) { - Ok(schema) => schema, - Err(e) => panic!("Error building schema validator:\n {e}"), - }); - Ok(Self { validator }) - } - - pub fn validate_schema(&self, schema: &Bound<'py, PyAny>, strict: Option) -> PyResult> { - let py = schema.py(); - let mut recursion_guard = RecursionState::default(); - let mut state = ValidationState::new( - Extra::new(strict, None, None, None, InputType::Python, true.into(), None, None), - &mut recursion_guard, - false.into(), - ); - match self.validator.validator.validate(py, schema, &mut state) { - Ok(schema_obj) => Ok(schema_obj.into_bound(py)), - Err(e) => Err(SchemaError::from_val_error(py, e)), - } - } - - fn build(py: Python) -> PyResult { - let code = c_str!(include_str!("../self_schema.py")); - let locals = PyDict::new(py); - py.run(code, None, Some(&locals))?; - let self_schema = locals.get_as_req(intern!(py, "self_schema"))?; - - let mut definitions_builder = DefinitionsBuilder::new(); - - let validator = match build_validator(&self_schema, None, &mut definitions_builder) { - Ok(v) => v, - Err(err) => return py_schema_err!("Error building self-schema:\n {}", err), - }; - let definitions = definitions_builder.finish()?; - Ok(SchemaValidator { - validator, - definitions, - py_schema: py.None(), - py_config: None, - title: "Self Schema".into_py_any(py)?, - hide_input_in_errors: false, - validation_error_cause: false, - cache_str: true.into(), - }) - } -} - -#[pyfunction(signature = (schema, *, strict = None))] -pub fn validate_core_schema<'py>(schema: &Bound<'py, PyAny>, strict: Option) -> PyResult> { - let self_validator = SelfValidator::new(schema.py())?; - self_validator.validate_schema(schema, strict) -} - pub trait BuildValidator: Sized { const EXPECTED_TYPE: &'static str; @@ -553,19 +491,40 @@ macro_rules! validator_match { }; } +// Used when creating the base validator instance, to avoid reusing the instance +// when unpickling: +pub fn build_validator_base( + schema: &Bound<'_, PyAny>, + config: Option<&Bound<'_, PyDict>>, + definitions: &mut DefinitionsBuilder, +) -> PyResult { + build_validator_inner(schema, config, definitions, false) +} + pub fn build_validator( schema: &Bound<'_, PyAny>, config: Option<&Bound<'_, PyDict>>, definitions: &mut DefinitionsBuilder, +) -> PyResult { + build_validator_inner(schema, config, definitions, true) +} + +fn build_validator_inner( + schema: &Bound<'_, PyAny>, + config: Option<&Bound<'_, PyDict>>, + definitions: &mut DefinitionsBuilder, + use_prebuilt: bool, ) -> PyResult { let dict = schema.downcast::()?; let py = schema.py(); let type_: Bound<'_, PyString> = dict.get_as_req(intern!(py, "type"))?; let type_ = type_.to_str()?; - // if we have a SchemaValidator on the type already, use it - if let Ok(Some(prebuilt_validator)) = prebuilt::PrebuiltValidator::try_get_from_schema(type_, dict) { - return Ok(prebuilt_validator); + if use_prebuilt { + // if we have a SchemaValidator on the type already, use it + if let Ok(Some(prebuilt_validator)) = prebuilt::PrebuiltValidator::try_get_from_schema(type_, dict) { + return Ok(prebuilt_validator); + } } validator_match!( @@ -678,6 +637,8 @@ pub struct Extra<'a, 'py> { pub from_attributes: Option, /// context used in validator functions pub context: Option<&'a Bound<'py, PyAny>>, + /// The name of the field being validated, if applicable + pub field_name: Option>, /// This is an instance of the model or dataclass being validated, when validation is performed from `__init__` self_instance: Option<&'a Bound<'py, PyAny>>, /// Whether to use a cache of short strings to accelerate python string construction @@ -705,6 +666,7 @@ impl<'a, 'py> Extra<'a, 'py> { data: None, strict, from_attributes, + field_name: None, context, self_instance, cache_str, @@ -721,6 +683,7 @@ impl Extra<'_, '_> { data: self.data.clone(), strict: Some(true), from_attributes: self.from_attributes, + field_name: self.field_name.clone(), context: self.context, self_instance: self.self_instance, cache_str: self.cache_str, diff --git a/src/validators/model.rs b/src/validators/model.rs index 6c93c209c..f2c3658e8 100644 --- a/src/validators/model.rs +++ b/src/validators/model.rs @@ -202,6 +202,7 @@ impl Validator for ModelValidator { field_name.to_string(), )) } else { + let state = &mut state.rebind_extra(|extra| extra.field_name = Some(PyString::new(py, ROOT_FIELD))); let output = self.validator.validate(py, field_value, state)?; force_setattr(py, model, intern!(py, ROOT_FIELD), output)?; @@ -255,9 +256,11 @@ impl ModelValidator { // we need to set `self_instance` to None for nested validators as we don't want to operate on self_instance // anymore let state = &mut state.rebind_extra(|extra| extra.self_instance = None); - let output = self.validator.validate(py, input, state)?; if self.root_model { + let state = &mut state.rebind_extra(|extra| extra.field_name = Some(PyString::new(py, ROOT_FIELD))); + let output = self.validator.validate(py, input, state)?; + let fields_set = if input.as_python().is_some_and(|py_input| py_input.is(&self.undefined)) { PySet::empty(py)? } else { @@ -266,6 +269,8 @@ impl ModelValidator { force_setattr(py, self_instance, intern!(py, DUNDER_FIELDS_SET_KEY), &fields_set)?; force_setattr(py, self_instance, intern!(py, ROOT_FIELD), &output)?; } else { + let output = self.validator.validate(py, input, state)?; + let (model_dict, model_extra, fields_set): (Bound, Bound, Bound) = output.extract(py)?; set_model_attrs(self_instance, &model_dict, &model_extra, &fields_set)?; @@ -294,11 +299,12 @@ impl ModelValidator { } } - let output = self.validator.validate(py, input, state)?; - let instance = create_class(self.class.bind(py))?; if self.root_model { + let state = &mut state.rebind_extra(|extra| extra.field_name = Some(PyString::new(py, ROOT_FIELD))); + let output = self.validator.validate(py, input, state)?; + let fields_set = if input.as_python().is_some_and(|py_input| py_input.is(&self.undefined)) { PySet::empty(py)? } else { @@ -307,6 +313,8 @@ impl ModelValidator { force_setattr(py, &instance, intern!(py, DUNDER_FIELDS_SET_KEY), &fields_set)?; force_setattr(py, &instance, intern!(py, ROOT_FIELD), output)?; } else { + let output = self.validator.validate(py, input, state)?; + let (model_dict, model_extra, val_fields_set): (Bound, Bound, Bound) = output.extract(py)?; let fields_set = existing_fields_set.unwrap_or(&val_fields_set); diff --git a/src/validators/model_fields.rs b/src/validators/model_fields.rs index ba1f7d1ba..d3af284fa 100644 --- a/src/validators/model_fields.rs +++ b/src/validators/model_fields.rs @@ -197,6 +197,10 @@ impl Validator for ModelFieldsValidator { // extra logic either way used_keys.insert(lookup_path.first_key()); } + + let state = + &mut state.rebind_extra(|extra| extra.field_name = Some(field.name_py.bind(py).clone())); + match field.validator.validate(py, value.borrow_input(), state) { Ok(value) => { model_dict.set_item(&field.name_py, value)?; @@ -228,7 +232,7 @@ impl Validator for ModelFieldsValidator { &field.name, )); } - Err(ValError::Omit) => continue, + Err(ValError::Omit) => {} Err(ValError::LineErrors(line_errors)) => { for err in line_errors { // Note: this will always use the field name even if there is an alias @@ -334,7 +338,7 @@ impl Validator for ModelFieldsValidator { } else { model_extra_dict.set_item(&py_key, value.to_object(self.py)?)?; self.fields_set_vec.push(py_key.into()); - }; + } } } } @@ -368,7 +372,7 @@ impl Validator for ModelFieldsValidator { // from attributes, set it now so __pydantic_extra__ is always a dict if extra=allow if matches!(self.extra_behavior, ExtraBehavior::Allow) && model_extra_dict_op.is_none() { model_extra_dict_op = Some(PyDict::new(py)); - }; + } Ok((model_dict, model_extra_dict_op, fields_set).into_py_any(py)?) } @@ -405,7 +409,7 @@ impl Validator for ModelFieldsValidator { let data_dict = dict.copy()?; if let Err(err) = data_dict.del_item(field_name) { // KeyError is fine here as the field might not be in the dict - if !err.get_type(py).is(&PyType::new::(py)) { + if !err.get_type(py).is(PyType::new::(py)) { return Err(err.into()); } } @@ -422,6 +426,8 @@ impl Validator for ModelFieldsValidator { )); } + let state = &mut state.rebind_extra(|extra| extra.field_name = Some(field.name_py.bind(py).clone())); + prepare_result(field.validator.validate(py, field_value, state))? } else { // Handle extra (unknown) field diff --git a/src/validators/time.rs b/src/validators/time.rs index eda4935a3..db98846b1 100644 --- a/src/validators/time.rs +++ b/src/validators/time.rs @@ -1,14 +1,14 @@ +use pyo3::exceptions::PyValueError; use pyo3::intern; use pyo3::prelude::*; use pyo3::types::{PyDict, PyString}; use pyo3::IntoPyObjectExt; -use speedate::Time; +use speedate::{MicrosecondsPrecisionOverflowBehavior, Time}; use crate::build_tools::is_strict; use crate::errors::{ErrorType, ValError, ValResult}; -use crate::input::{EitherTime, Input}; -use crate::tools::SchemaDict; +use crate::input::Input; use super::datetime::extract_microseconds_precision; use super::datetime::TZConstraint; @@ -18,7 +18,7 @@ use super::{BuildValidator, CombinedValidator, DefinitionsBuilder, ValidationSta pub struct TimeValidator { strict: bool, constraints: Option, - microseconds_precision: speedate::MicrosecondsPrecisionOverflowBehavior, + microseconds_precision: MicrosecondsPrecisionOverflowBehavior, } impl BuildValidator for TimeValidator { @@ -86,9 +86,14 @@ impl Validator for TimeValidator { } } -fn convert_pytime(schema: &Bound<'_, PyDict>, field: &Bound<'_, PyString>) -> PyResult> { - match schema.get_as(field)? { - Some(date) => Ok(Some(EitherTime::Py(date).as_raw()?)), +fn convert_pytime(schema: &Bound<'_, PyDict>, key: &Bound<'_, PyString>) -> PyResult> { + match schema.get_item(key)? { + Some(value) => match value.validate_time(false, MicrosecondsPrecisionOverflowBehavior::default()) { + Ok(v) => Ok(Some(v.into_inner().as_raw()?)), + Err(_) => Err(PyValueError::new_err(format!( + "'{key}' must be coercible to a time instance", + ))), + }, None => Ok(None), } } diff --git a/src/validators/typed_dict.rs b/src/validators/typed_dict.rs index 013db4d69..eb4394e39 100644 --- a/src/validators/typed_dict.rs +++ b/src/validators/typed_dict.rs @@ -218,6 +218,9 @@ impl Validator for TypedDictValidator { true => allow_partial, false => false.into(), }; + let state = + &mut state.rebind_extra(|extra| extra.field_name = Some(field.name_py.bind(py).clone())); + match field.validator.validate(py, value.borrow_input(), state) { Ok(value) => { output_dict.set_item(&field.name_py, value)?; @@ -252,7 +255,7 @@ impl Validator for TypedDictValidator { )); } } - Err(ValError::Omit) => continue, + Err(ValError::Omit) => {} Err(ValError::LineErrors(line_errors)) => { for err in line_errors { // Note: this will always use the field name even if there is an alias @@ -347,7 +350,7 @@ impl Validator for TypedDictValidator { } } else { self.output_dict.set_item(py_key, value.to_object(self.py)?)?; - }; + } } } } diff --git a/src/validators/union.rs b/src/validators/union.rs index dccc09ce7..f293a9976 100644 --- a/src/validators/union.rs +++ b/src/validators/union.rs @@ -193,7 +193,7 @@ impl UnionValidator { match validator.validate(py, input, state) { Err(ValError::LineErrors(lines)) => errors.push(validator, label.as_deref(), lines), otherwise => return otherwise, - }; + } } Err(errors.into_val_error(input)) diff --git a/src/validators/url.rs b/src/validators/url.rs index fd386074f..d220d60ed 100644 --- a/src/validators/url.rs +++ b/src/validators/url.rs @@ -392,7 +392,7 @@ fn parse_multihost_url<'py>( '\t' | '\n' | '\r' => (), c if c <= &' ' => (), _ => break, - }; + } chars.next(); } else { break; diff --git a/src/validators/uuid.rs b/src/validators/uuid.rs index 995f2d183..9ad4eb3b9 100644 --- a/src/validators/uuid.rs +++ b/src/validators/uuid.rs @@ -215,7 +215,7 @@ impl UuidValidator { input, )); } - }; + } Ok(uuid) } diff --git a/tests/benchmarks/complete_schema.py b/tests/benchmarks/complete_schema.py index e12cdb298..300c841fa 100644 --- a/tests/benchmarks/complete_schema.py +++ b/tests/benchmarks/complete_schema.py @@ -1,7 +1,13 @@ +from __future__ import annotations + from decimal import Decimal +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from pydantic_core import CoreSchema -def schema(*, strict: bool = False) -> dict: +def schema(*, strict: bool = False) -> CoreSchema: class MyModel: # __slots__ is not required, but it avoids __pydantic_fields_set__ falling into __dict__ __slots__ = '__dict__', '__pydantic_fields_set__', '__pydantic_extra__', '__pydantic_private__' @@ -12,7 +18,7 @@ def append_func(input_value, info): def wrap_function(input_value, validator, info): return f'Input {validator(input_value)} Changed' - return { + return { # type: ignore 'type': 'model', 'cls': MyModel, 'config': {'strict': strict}, @@ -342,7 +348,7 @@ def input_data_wrong(): } -def wrap_schema_in_root_model(schema: dict) -> dict: +def wrap_schema_in_root_model(schema: CoreSchema) -> CoreSchema: class MyRootModel: # __slots__ is not required, but it avoids __pydantic_fields_set__ falling into __dict__ __slots__ = '__dict__', '__pydantic_fields_set__', '__pydantic_extra__', '__pydantic_private__' diff --git a/tests/benchmarks/test_complete_benchmark.py b/tests/benchmarks/test_complete_benchmark.py index 5552e43cc..6ef046529 100644 --- a/tests/benchmarks/test_complete_benchmark.py +++ b/tests/benchmarks/test_complete_benchmark.py @@ -9,7 +9,7 @@ import pytest -from pydantic_core import SchemaSerializer, SchemaValidator, ValidationError, validate_core_schema +from pydantic_core import SchemaSerializer, SchemaValidator, ValidationError from .complete_schema import input_data_lax, input_data_strict, input_data_wrong, schema, wrap_schema_in_root_model @@ -17,7 +17,7 @@ def test_complete_valid(): lax_schema = schema() cls = lax_schema['cls'] - lax_validator = SchemaValidator(validate_core_schema(lax_schema)) + lax_validator = SchemaValidator(lax_schema) output = lax_validator.validate_python(input_data_lax()) assert isinstance(output, cls) assert len(output.__pydantic_fields_set__) == 41 @@ -74,14 +74,14 @@ def test_complete_valid(): }, } - strict_validator = SchemaValidator(validate_core_schema(schema(strict=True))) + strict_validator = SchemaValidator(schema(strict=True)) output2 = strict_validator.validate_python(input_data_strict()) assert output_dict == output2.__dict__ def test_complete_invalid(): lax_schema = schema() - lax_validator = SchemaValidator(validate_core_schema(lax_schema)) + lax_validator = SchemaValidator(lax_schema) with pytest.raises(ValidationError) as exc_info: lax_validator.validate_python(input_data_wrong()) assert len(exc_info.value.errors(include_url=False)) == 739 @@ -89,25 +89,25 @@ def test_complete_invalid(): @pytest.mark.benchmark(group='complete') def test_complete_core_lax(benchmark): - v = SchemaValidator(validate_core_schema(schema())) + v = SchemaValidator(schema()) benchmark(v.validate_python, input_data_lax()) @pytest.mark.benchmark(group='complete') def test_complete_core_strict(benchmark): - v = SchemaValidator(validate_core_schema(schema(strict=True))) + v = SchemaValidator(schema(strict=True)) benchmark(v.validate_python, input_data_strict()) @pytest.mark.benchmark(group='complete') def test_complete_core_root(benchmark): - v = SchemaValidator(validate_core_schema(wrap_schema_in_root_model(schema()))) + v = SchemaValidator(wrap_schema_in_root_model(schema())) benchmark(v.validate_python, {'root': input_data_lax()}) @pytest.mark.benchmark(group='complete-to-python') def test_complete_core_serializer_to_python(benchmark): - core_schema = validate_core_schema(schema()) + core_schema = schema() v = SchemaValidator(core_schema) model = v.validate_python(input_data_lax()) serializer = SchemaSerializer(core_schema) @@ -117,7 +117,7 @@ def test_complete_core_serializer_to_python(benchmark): @pytest.mark.benchmark(group='complete-to-json') def test_complete_core_serializer_to_json(benchmark): - core_schema = validate_core_schema(schema()) + core_schema = schema() v = SchemaValidator(core_schema) model = v.validate_python(input_data_lax()) serializer = SchemaSerializer(core_schema) @@ -126,7 +126,7 @@ def test_complete_core_serializer_to_json(benchmark): @pytest.mark.benchmark(group='complete-wrong') def test_complete_core_error(benchmark): - v = SchemaValidator(validate_core_schema(schema())) + v = SchemaValidator(schema()) data = input_data_wrong() @benchmark @@ -141,7 +141,7 @@ def f(): @pytest.mark.benchmark(group='complete-wrong') def test_complete_core_isinstance(benchmark): - v = SchemaValidator(validate_core_schema(schema())) + v = SchemaValidator(schema()) data = input_data_wrong() assert v.isinstance_python(data) is False @@ -161,14 +161,14 @@ def default_json_encoder(obj): @pytest.mark.benchmark(group='complete-json') def test_complete_core_json(benchmark): - v = SchemaValidator(validate_core_schema(schema())) + v = SchemaValidator(schema()) json_data = json.dumps(input_data_lax(), default=default_json_encoder) benchmark(v.validate_json, json_data) @pytest.mark.benchmark(group='complete-json') def test_complete_core_root_json(benchmark): - v = SchemaValidator(validate_core_schema(wrap_schema_in_root_model(schema()))) + v = SchemaValidator(wrap_schema_in_root_model(schema())) json_data = json.dumps({'root': input_data_lax()}, default=default_json_encoder) benchmark(v.validate_json, json_data) @@ -176,4 +176,4 @@ def test_complete_core_root_json(benchmark): @pytest.mark.benchmark(group='build') def test_build_schema(benchmark): lax_schema = schema() - benchmark(lambda s: SchemaValidator(validate_core_schema(s)), lax_schema) + benchmark(SchemaValidator, lax_schema) diff --git a/tests/benchmarks/test_micro_benchmarks.py b/tests/benchmarks/test_micro_benchmarks.py index 5640431ae..6d36ffa8d 100644 --- a/tests/benchmarks/test_micro_benchmarks.py +++ b/tests/benchmarks/test_micro_benchmarks.py @@ -1348,7 +1348,7 @@ def f(v: int, info: core_schema.ValidationInfo) -> int: limit = pydantic_core._pydantic_core._recursion_limit - 3 for _ in range(limit): - schema = core_schema.with_info_after_validator_function(f, schema, field_name='x') + schema = core_schema.with_info_after_validator_function(f, schema) schema = core_schema.typed_dict_schema({'x': core_schema.typed_dict_field(schema)}) diff --git a/tests/conftest.py b/tests/conftest.py index 226ace018..b1c1e8fb0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -6,6 +6,7 @@ import json import os import re +import sys from dataclasses import dataclass from pathlib import Path from time import sleep, time @@ -14,15 +15,20 @@ import hypothesis import pytest -from pydantic_core import ArgsKwargs, CoreSchema, SchemaValidator, ValidationError, validate_core_schema +from pydantic_core import ArgsKwargs, CoreSchema, SchemaValidator, ValidationError from pydantic_core.core_schema import CoreConfig -__all__ = 'Err', 'PyAndJson', 'plain_repr', 'infinite_generator' +__all__ = 'Err', 'PyAndJson', 'assert_gc', 'is_free_threaded', 'plain_repr', 'infinite_generator' hypothesis.settings.register_profile('fast', max_examples=2) hypothesis.settings.register_profile('slow', max_examples=1_000) hypothesis.settings.load_profile(os.getenv('HYPOTHESIS_PROFILE', 'fast')) +try: + is_free_threaded = not sys._is_gil_enabled() +except AttributeError: + is_free_threaded = False + def plain_repr(obj): r = repr(obj) @@ -58,7 +64,7 @@ def __init__( *, validator_type: Literal['json', 'python'] | None = None, ): - self.validator = SchemaValidator(validate_core_schema(schema), config) + self.validator = SchemaValidator(schema, config) self.validator_type = validator_type def validate_python(self, py_input, strict: bool | None = None, context: Any = None): diff --git a/tests/emscripten_runner.js b/tests/emscripten_runner.js index ab1583da3..c527f86f8 100644 --- a/tests/emscripten_runner.js +++ b/tests/emscripten_runner.js @@ -106,6 +106,7 @@ await micropip.install([ 'tzdata', 'file:${wheel_path}', 'typing-extensions', + 'typing-inspection', ]) importlib.invalidate_caches() diff --git a/tests/serializers/test_definitions.py b/tests/serializers/test_definitions.py index d45398097..456b0ab1d 100644 --- a/tests/serializers/test_definitions.py +++ b/tests/serializers/test_definitions.py @@ -1,6 +1,6 @@ import pytest -from pydantic_core import SchemaError, SchemaSerializer, core_schema, validate_core_schema +from pydantic_core import SchemaError, SchemaSerializer, core_schema def test_custom_ser(): @@ -23,20 +23,6 @@ def test_ignored_def(): assert s.to_python([1, 2, 3]) == [1, 2, 3] -def test_def_error(): - with pytest.raises(SchemaError) as exc_info: - validate_core_schema( - core_schema.definitions_schema( - core_schema.list_schema(core_schema.definition_reference_schema('foobar')), - [core_schema.int_schema(ref='foobar'), {'type': 'wrong'}], - ) - ) - - assert str(exc_info.value).startswith( - "Invalid Schema:\ndefinitions.definitions.1\n Input tag 'wrong' found using 'type'" - ) - - def test_repeated_ref(): with pytest.raises(SchemaError, match='SchemaError: Duplicate ref: `foobar`'): SchemaSerializer( diff --git a/tests/serializers/test_dict.py b/tests/serializers/test_dict.py index cc1b56091..dcd7f6acc 100644 --- a/tests/serializers/test_dict.py +++ b/tests/serializers/test_dict.py @@ -3,7 +3,7 @@ import pytest from dirty_equals import IsStrictDict -from pydantic_core import SchemaError, SchemaSerializer, core_schema, validate_core_schema +from pydantic_core import SchemaSerializer, core_schema def test_dict_str_int(): @@ -143,18 +143,3 @@ def test_filter_runtime_int(): core_schema.dict_schema(core_schema.any_schema(), serialization=core_schema.filter_dict_schema(exclude={0, 1})) ) assert s.to_python({0: 0, 1: 1, 2: 2, 3: 3}, include={1, 2}) == {1: 1, 2: 2} - - -@pytest.mark.parametrize( - 'include_value,error_msg', - [ - ('foobar', 'Input should be a valid set'), - ({'a': 'dict'}, 'Input should be a valid set'), - ({4.2}, 'Input should be a valid integer, got a number with a fractional part'), - ], -) -def test_include_error(include_value, error_msg): - with pytest.raises(SchemaError, match=error_msg): - validate_core_schema( - core_schema.dict_schema(serialization=core_schema.filter_dict_schema(include=include_value)) - ) diff --git a/tests/serializers/test_list_tuple.py b/tests/serializers/test_list_tuple.py index 7473ee261..ec475be24 100644 --- a/tests/serializers/test_list_tuple.py +++ b/tests/serializers/test_list_tuple.py @@ -5,10 +5,8 @@ from pydantic_core import ( PydanticSerializationError, - SchemaError, SchemaSerializer, core_schema, - validate_core_schema, ) @@ -162,13 +160,10 @@ def test_exclude(schema_func, seq_f): assert v.to_json(seq_f('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'), exclude={-1, -2}) == b'["a","c","e"]' -@pytest.mark.parametrize('include,exclude', [({1, 3, 5}, {5, 6}), ([1, 3, 5], [5, 6])]) -def test_filter(include, exclude): +def test_filter(): v = SchemaSerializer( - validate_core_schema( - core_schema.list_schema( - core_schema.any_schema(), serialization=core_schema.filter_seq_schema(include=include, exclude=exclude) - ) + core_schema.list_schema( + core_schema.any_schema(), serialization=core_schema.filter_seq_schema(include={1, 3, 5}, exclude={5, 6}) ) ) assert v.to_python([0, 1, 2, 3, 4, 5, 6, 7]) == [1, 3] @@ -197,23 +192,6 @@ class RemovedContains(ImplicitContains): __contains__ = None # This might be done to explicitly force the `x in RemovedContains()` check to not be allowed -@pytest.mark.parametrize( - 'include_value,error_msg', - [ - ('foobar', 'Input should be a valid set'), - ({'a': 'dict'}, 'Input should be a valid set'), - ({4.2}, 'Input should be a valid integer, got a number with a fractional part'), - ({'a'}, 'Input should be a valid integer, unable to parse string as an integer'), - ], -) -@pytest.mark.parametrize('schema_func', [core_schema.list_schema, core_schema.tuple_variable_schema]) -def test_include_error(schema_func, include_value, error_msg): - with pytest.raises(SchemaError, match=error_msg): - validate_core_schema( - schema_func(core_schema.any_schema(), serialization=core_schema.filter_seq_schema(include=include_value)) - ) - - @pytest.mark.parametrize( 'include,exclude,expected', [ diff --git a/tests/serializers/test_misc.py b/tests/serializers/test_misc.py deleted file mode 100644 index 7753f1948..000000000 --- a/tests/serializers/test_misc.py +++ /dev/null @@ -1,15 +0,0 @@ -import pytest - -from pydantic_core import SchemaError, core_schema, validate_core_schema - - -@pytest.mark.parametrize( - 'ser_schema,msg', - [ - ({'invalid': 'schema'}, "Unable to extract tag using discriminator 'type'"), - ({'type': 'unknown'}, "Input tag 'unknown' found using 'type' does not match any of the expected tags:"), - ], -) -def test_invalid_ser_schema(ser_schema, msg): - with pytest.raises(SchemaError, match=msg): - validate_core_schema(core_schema.any_schema(serialization=ser_schema)) diff --git a/tests/serializers/test_pickling.py b/tests/serializers/test_pickling.py index 2ca230313..208cafbd9 100644 --- a/tests/serializers/test_pickling.py +++ b/tests/serializers/test_pickling.py @@ -48,3 +48,26 @@ def test_schema_serializer_containing_config(): assert s.to_python(timedelta(seconds=4, microseconds=500_000)) == timedelta(seconds=4, microseconds=500_000) assert s.to_python(timedelta(seconds=4, microseconds=500_000), mode='json') == 4.5 assert s.to_json(timedelta(seconds=4, microseconds=500_000)) == b'4.5' + + +# Should be defined at the module level for pickling to work: +class Model: + __pydantic_serializer__: SchemaSerializer + __pydantic_complete__ = True + + +def test_schema_serializer_not_reused_when_unpickling() -> None: + s = SchemaSerializer( + core_schema.model_schema( + cls=Model, + schema=core_schema.model_fields_schema(fields={}, model_name='Model'), + config={'title': 'Model'}, + ref='Model:123', + ) + ) + + Model.__pydantic_serializer__ = s + assert 'Prebuilt' not in str(Model.__pydantic_serializer__) + + reconstructed = pickle.loads(pickle.dumps(Model.__pydantic_serializer__)) + assert 'Prebuilt' not in str(reconstructed) diff --git a/tests/serializers/test_serialize_as_any.py b/tests/serializers/test_serialize_as_any.py index 1d1be238b..ee841ffa8 100644 --- a/tests/serializers/test_serialize_as_any.py +++ b/tests/serializers/test_serialize_as_any.py @@ -1,4 +1,5 @@ from dataclasses import dataclass +from typing import Optional from typing_extensions import TypedDict @@ -155,3 +156,217 @@ class Other: 'x': 1, 'y': 'hopefully not a secret', } + + +def test_serialize_as_any_with_nested_models() -> None: + class Parent: + x: int + + class Other(Parent): + y: str + + class Outer: + p: Parent + + Parent.__pydantic_core_schema__ = core_schema.model_schema( + Parent, + core_schema.model_fields_schema( + { + 'x': core_schema.model_field(core_schema.int_schema()), + } + ), + ref='Parent', + ) + Parent.__pydantic_validator__ = SchemaValidator(Parent.__pydantic_core_schema__) + Parent.__pydantic_serializer__ = SchemaSerializer(Parent.__pydantic_core_schema__) + + Other.__pydantic_core_schema__ = core_schema.model_schema( + Other, + core_schema.model_fields_schema( + { + 'x': core_schema.model_field(core_schema.int_schema()), + 'y': core_schema.model_field(core_schema.str_schema()), + } + ), + config=core_schema.CoreConfig(extra_fields_behavior='allow'), + ) + Other.__pydantic_validator__ = SchemaValidator(Other.__pydantic_core_schema__) + Other.__pydantic_serializer__ = SchemaSerializer(Other.__pydantic_core_schema__) + + Outer.__pydantic_core_schema__ = core_schema.definitions_schema( + core_schema.model_schema( + Outer, + core_schema.model_fields_schema( + { + 'p': core_schema.model_field(core_schema.definition_reference_schema('Parent')), + } + ), + ), + [ + Parent.__pydantic_core_schema__, + ], + ) + Outer.__pydantic_validator__ = SchemaValidator(Outer.__pydantic_core_schema__) + Outer.__pydantic_serializer__ = SchemaSerializer(Outer.__pydantic_core_schema__) + + other = Other.__pydantic_validator__.validate_python({'x': 1, 'y': 'hopefully not a secret'}) + outer = Outer() + outer.p = other + + assert Outer.__pydantic_serializer__.to_python(outer, serialize_as_any=False) == { + 'p': {'x': 1}, + } + assert Outer.__pydantic_serializer__.to_python(outer, serialize_as_any=True) == { + 'p': { + 'x': 1, + 'y': 'hopefully not a secret', + } + } + + assert Outer.__pydantic_serializer__.to_json(outer, serialize_as_any=False) == b'{"p":{"x":1}}' + assert ( + Outer.__pydantic_serializer__.to_json(outer, serialize_as_any=True) + == b'{"p":{"x":1,"y":"hopefully not a secret"}}' + ) + + +def test_serialize_with_recursive_models() -> None: + class Node: + next: Optional['Node'] = None + value: int = 42 + + schema = core_schema.definitions_schema( + core_schema.definition_reference_schema('Node'), + [ + core_schema.model_schema( + Node, + core_schema.model_fields_schema( + { + 'value': core_schema.model_field( + core_schema.with_default_schema(core_schema.int_schema(), default=42) + ), + 'next': core_schema.model_field( + core_schema.with_default_schema( + core_schema.nullable_schema(core_schema.definition_reference_schema('Node')), + default=None, + ) + ), + } + ), + ref='Node', + ) + ], + ) + + Node.__pydantic_core_schema__ = schema + Node.__pydantic_validator__ = SchemaValidator(Node.__pydantic_core_schema__) + Node.__pydantic_serializer__ = SchemaSerializer(Node.__pydantic_core_schema__) + other = Node.__pydantic_validator__.validate_python({'next': {'value': 4}}) + + assert Node.__pydantic_serializer__.to_python(other, serialize_as_any=False) == { + 'next': {'next': None, 'value': 4}, + 'value': 42, + } + assert Node.__pydantic_serializer__.to_python(other, serialize_as_any=True) == { + 'next': {'next': None, 'value': 4}, + 'value': 42, + } + + +def test_serialize_with_custom_type_and_subclasses(): + class Node: + x: int + + Node.__pydantic_core_schema__ = core_schema.model_schema( + Node, + core_schema.model_fields_schema( + { + 'x': core_schema.model_field(core_schema.int_schema()), + } + ), + ref='Node', + ) + Node.__pydantic_validator__ = SchemaValidator(Node.__pydantic_core_schema__) + Node.__pydantic_serializer__ = SchemaSerializer(Node.__pydantic_core_schema__) + + class NodeSubClass(Node): + y: int + + NodeSubClass.__pydantic_core_schema__ = core_schema.model_schema( + NodeSubClass, + core_schema.model_fields_schema( + { + 'x': core_schema.model_field(core_schema.int_schema()), + 'y': core_schema.model_field(core_schema.int_schema()), + } + ), + ) + NodeSubClass.__pydantic_validator__ = SchemaValidator(NodeSubClass.__pydantic_core_schema__) + NodeSubClass.__pydantic_serializer__ = SchemaSerializer(NodeSubClass.__pydantic_core_schema__) + + class CustomType: + values: list[Node] + + CustomType.__pydantic_core_schema__ = core_schema.model_schema( + CustomType, + core_schema.definitions_schema( + core_schema.model_fields_schema( + { + 'values': core_schema.model_field( + core_schema.list_schema(core_schema.definition_reference_schema('Node')) + ), + } + ), + [ + Node.__pydantic_core_schema__, + ], + ), + ) + CustomType.__pydantic_validator__ = SchemaValidator(CustomType.__pydantic_core_schema__) + CustomType.__pydantic_serializer__ = SchemaSerializer(CustomType.__pydantic_core_schema__) + + value = CustomType.__pydantic_validator__.validate_python({'values': [{'x': 1}, {'x': 2}]}) + value.values.append(NodeSubClass.__pydantic_validator__.validate_python({'x': 3, 'y': 4})) + + assert CustomType.__pydantic_serializer__.to_python(value, serialize_as_any=False) == { + 'values': [{'x': 1}, {'x': 2}, {'x': 3}], + } + assert CustomType.__pydantic_serializer__.to_python(value, serialize_as_any=True) == { + 'values': [{'x': 1}, {'x': 2}, {'x': 3, 'y': 4}], + } + + +def test_serialize_as_any_wrap_serializer_applied_once() -> None: + # https://github.com/pydantic/pydantic/issues/11139 + + class InnerModel: + an_inner_field: int + + InnerModel.__pydantic_core_schema__ = core_schema.model_schema( + InnerModel, + core_schema.model_fields_schema({'an_inner_field': core_schema.model_field(core_schema.int_schema())}), + ) + InnerModel.__pydantic_validator__ = SchemaValidator(InnerModel.__pydantic_core_schema__) + InnerModel.__pydantic_serializer__ = SchemaSerializer(InnerModel.__pydantic_core_schema__) + + class MyModel: + a_field: InnerModel + + def a_model_serializer(self, handler, info): + return {k + '_wrapped': v for k, v in handler(self).items()} + + MyModel.__pydantic_core_schema__ = core_schema.model_schema( + MyModel, + core_schema.model_fields_schema({'a_field': core_schema.model_field(InnerModel.__pydantic_core_schema__)}), + serialization=core_schema.wrap_serializer_function_ser_schema( + MyModel.a_model_serializer, + info_arg=True, + ), + ) + MyModel.__pydantic_validator__ = SchemaValidator(MyModel.__pydantic_core_schema__) + MyModel.__pydantic_serializer__ = SchemaSerializer(MyModel.__pydantic_core_schema__) + + instance = MyModel.__pydantic_validator__.validate_python({'a_field': {'an_inner_field': 1}}) + assert MyModel.__pydantic_serializer__.to_python(instance, serialize_as_any=True) == { + 'a_field_wrapped': {'an_inner_field': 1}, + } diff --git a/tests/serializers/test_string.py b/tests/serializers/test_string.py index f547d49b2..555edf1d2 100644 --- a/tests/serializers/test_string.py +++ b/tests/serializers/test_string.py @@ -23,6 +23,38 @@ def test_str(): assert json.loads(json_emoji) == 'emoji 💩' +# Tests borrowed from: +# - https://github.com/python/cpython/blob/d87e7f35/Lib/test/test_json/test_encode_basestring_ascii.py +# - https://github.com/python/cpython/blob/d87e7f35/Lib/test/test_json/test_unicode.py +@pytest.mark.parametrize( + ['input', 'expected'], + [ + ( + '/\\"\ucafe\ubabe\uab98\ufcde\ubcda\uef4a\x08\x0c\n\r\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?', + '"/\\\\\\"\\ucafe\\ubabe\\uab98\\ufcde\\ubcda\\uef4a\\b\\f\\n\\r\\t`1~!@#$%^&*()_+-=[]{}|;:\',./<>?"', + ), + ('\u0123\u4567\u89ab\ucdef\uabcd\uef4a', '"\\u0123\\u4567\\u89ab\\ucdef\\uabcd\\uef4a"'), + ('controls', '"controls"'), + ('\x08\x0c\n\r\t', '"\\b\\f\\n\\r\\t"'), + ( + '{"object with 1 member":["array with 1 element"]}', + '"{\\"object with 1 member\\":[\\"array with 1 element\\"]}"', + ), + (' s p a c e d ', '" s p a c e d "'), + ('\U0001d120', '"\\ud834\\udd20"'), + ('\u03b1\u03a9', '"\\u03b1\\u03a9"'), + ("`1~!@#$%^&*()_+-={':[,]}|;.?", '"`1~!@#$%^&*()_+-={\':[,]}|;.?"'), + ('\x08\x0c\n\r\t', '"\\b\\f\\n\\r\\t"'), + ('\u0123\u4567\u89ab\ucdef\uabcd\uef4a', '"\\u0123\\u4567\\u89ab\\ucdef\\uabcd\\uef4a"'), + ('\N{GREEK SMALL LETTER ALPHA}\N{GREEK CAPITAL LETTER OMEGA}', '"\\u03b1\\u03a9"'), + ('\U0001d120', '"\\ud834\\udd20"'), + ], +) +def test_str_ensure_ascii(input: str, expected: str) -> None: + v = SchemaSerializer(core_schema.str_schema()) + assert v.to_json(input, ensure_ascii=True).decode('utf-8') == expected + + def test_huge_str(): v = SchemaSerializer(core_schema.int_schema()) msg = r"Expected `int` - serialized value may not be as expected \[input_value='123456789012345678901234...89012345678901234567890', input_type=str\]" diff --git a/tests/test.rs b/tests/test.rs index 58e2904f5..6ca066c91 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -93,6 +93,7 @@ a = A() py, &a, None, + Some(false), None, None, Some(true), @@ -201,6 +202,7 @@ dump_json_input_2 = {'a': 'something'} py, &dump_json_input_1, None, + Some(false), None, None, Some(false), @@ -222,6 +224,7 @@ dump_json_input_2 = {'a': 'something'} py, &dump_json_input_2, None, + Some(false), None, None, Some(false), diff --git a/tests/test_build.py b/tests/test_build.py index b20a58530..c0579f934 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -2,55 +2,15 @@ import pytest -from pydantic_core import SchemaError, SchemaValidator, validate_core_schema +from pydantic_core import SchemaValidator from pydantic_core import core_schema as cs -def test_build_error_type(): - with pytest.raises(SchemaError, match="Input tag 'foobar' found using 'type' does not match any of the"): - validate_core_schema({'type': 'foobar', 'title': 'TestModel'}) - - -def test_build_error_internal(): - with pytest.raises(SchemaError, match='Input should be a valid integer, unable to parse string as an integer'): - validate_core_schema({'type': 'str', 'min_length': 'xxx', 'title': 'TestModel'}) - - -def test_build_error_deep(): - with pytest.raises(SchemaError, match='Input should be a valid integer, unable to parse string as an integer'): - validate_core_schema( - { - 'title': 'MyTestModel', - 'type': 'typed-dict', - 'fields': {'age': {'schema': {'type': 'int', 'ge': 'not-int'}}}, - } - ) - - def test_schema_as_string(): v = SchemaValidator(cs.bool_schema()) assert v.validate_python('tRuE') is True -def test_schema_wrong_type(pydantic_version): - with pytest.raises(SchemaError) as exc_info: - validate_core_schema(1) - assert str(exc_info.value) == ( - 'Invalid Schema:\n Input should be a valid dictionary or object to' - ' extract fields from [type=model_attributes_type, input_value=1, input_type=int]\n' - f' For further information visit https://errors.pydantic.dev/{pydantic_version}/v/model_attributes_type' - ) - assert exc_info.value.errors() == [ - { - 'input': 1, - 'loc': (), - 'msg': 'Input should be a valid dictionary or object to extract fields from', - 'type': 'model_attributes_type', - } - ] - assert exc_info.value.error_count() == 1 - - @pytest.mark.parametrize('pickle_protocol', range(1, pickle.HIGHEST_PROTOCOL + 1)) def test_pickle(pickle_protocol: int) -> None: v1 = SchemaValidator(cs.bool_schema()) @@ -61,14 +21,6 @@ def test_pickle(pickle_protocol: int) -> None: assert repr(v1) == repr(v2) -@pytest.mark.skip -def test_schema_definition_error(): - schema = {'type': 'union', 'choices': []} - schema['choices'].append({'type': 'nullable', 'schema': schema}) - with pytest.raises(SchemaError, match='Recursion error - cyclic reference detected'): - validate_core_schema(schema) - - def test_not_schema_definition_error(): schema = { 'type': 'typed-dict', @@ -81,21 +33,6 @@ def test_not_schema_definition_error(): assert repr(v).count('TypedDictField') == 101 -def test_no_type(): - with pytest.raises(SchemaError, match="Unable to extract tag using discriminator 'type'"): - validate_core_schema({}) - - -def test_wrong_type(): - with pytest.raises(SchemaError, match="Input tag 'unknown' found using 'type' does not match any of the"): - validate_core_schema({'type': 'unknown'}) - - -def test_function_no_mode(): - with pytest.raises(SchemaError, match="Input tag 'function' found using 'type' does not match any of the"): - validate_core_schema({'type': 'function'}) - - def test_try_self_schema_discriminator(): """Trying to use self-schema when it shouldn't be used""" v = SchemaValidator(cs.tagged_union_schema(choices={'int': cs.int_schema()}, discriminator='self-schema')) diff --git a/tests/test_garbage_collection.py b/tests/test_garbage_collection.py index 2213f7cfb..3b5bb3c4f 100644 --- a/tests/test_garbage_collection.py +++ b/tests/test_garbage_collection.py @@ -1,4 +1,5 @@ import platform +import sys from collections.abc import Iterable from typing import Any from weakref import WeakValueDictionary @@ -7,7 +8,7 @@ from pydantic_core import SchemaSerializer, SchemaValidator, core_schema -from .conftest import assert_gc +from .conftest import assert_gc, is_free_threaded GC_TEST_SCHEMA_INNER = core_schema.definitions_schema( core_schema.definition_reference_schema(schema_ref='model'), @@ -20,6 +21,7 @@ ) +@pytest.mark.xfail(is_free_threaded and sys.version_info < (3, 14), reason='GC leaks on free-threaded (<3.14)') @pytest.mark.xfail( condition=platform.python_implementation() == 'PyPy', reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899' ) @@ -47,6 +49,7 @@ class MyModel(BaseModel): assert_gc(lambda: len(cache) == 0) +@pytest.mark.xfail(is_free_threaded and sys.version_info < (3, 14), reason='GC leaks on free-threaded (<3.14)') @pytest.mark.xfail( condition=platform.python_implementation() == 'PyPy', reason='https://foss.heptapod.net/pypy/pypy/-/issues/3899' ) diff --git a/tests/test_json.py b/tests/test_json.py index 4d40ceb16..dab2207f9 100644 --- a/tests/test_json.py +++ b/tests/test_json.py @@ -218,6 +218,9 @@ def test_to_json(): assert to_json([1, 2]) == b'[1,2]' assert to_json([1, 2], indent=2) == b'[\n 1,\n 2\n]' assert to_json([1, b'x']) == b'[1,"x"]' + assert to_json(['à', 'é']).decode('utf-8') == '["à","é"]' + assert to_json(['à', 'é'], indent=2).decode('utf-8') == '[\n "à",\n "é"\n]' + assert to_json(['à', 'é'], indent=2, ensure_ascii=True).decode('utf-8') == '[\n "\\u00e0",\n "\\u00e9"\n]' # kwargs required with pytest.raises(TypeError, match=r'to_json\(\) takes 1 positional arguments but 2 were given'): diff --git a/tests/test_misc.py b/tests/test_misc.py index 50162c24b..722362fa6 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -1,9 +1,14 @@ import copy import pickle -import re import pytest -from typing_extensions import get_args +from typing_extensions import ( # noqa: UP035 (https://github.com/astral-sh/ruff/pull/18476) + get_args, + get_origin, + get_type_hints, +) +from typing_inspection import typing_objects +from typing_inspection.introspection import UNKNOWN, AnnotationSource, inspect_annotation from pydantic_core import CoreConfig, CoreSchema, CoreSchemaType, PydanticUndefined, core_schema from pydantic_core._pydantic_core import ( @@ -159,13 +164,26 @@ class MyModel: def test_core_schema_type_literal(): - def get_type_value(schema): - type_ = schema.__annotations__['type'] - m = re.search(r"Literal\['(.+?)']", type_.__forward_arg__) - assert m, f'Unknown schema type: {type_}' - return m.group(1) + def get_type_value(schema_typeddict) -> str: + annotation = get_type_hints(schema_typeddict, include_extras=True)['type'] + inspected_ann = inspect_annotation(annotation, annotation_source=AnnotationSource.TYPED_DICT) + annotation = inspected_ann.type + assert annotation is not UNKNOWN + assert typing_objects.is_literal(get_origin(annotation)), ( + f"The 'type' key of core schemas must be a Literal form, got {get_origin(annotation)}" + ) + args = get_args(annotation) + assert len(args) == 1, ( + f"The 'type' key of core schemas must be a Literal form with a single element, got {len(args)} elements" + ) + type_ = args[0] + assert isinstance(type_, str), ( + f"The 'type' key of core schemas must be a Literal form with a single string element, got element of type {type(type_)}" + ) + + return type_ - schema_types = tuple(get_type_value(x) for x in CoreSchema.__args__) + schema_types = (get_type_value(x) for x in CoreSchema.__args__) schema_types = tuple(dict.fromkeys(schema_types)) # remove duplicates while preserving order if get_args(CoreSchemaType) != schema_types: literal = ''.join(f'\n {e!r},' for e in schema_types) diff --git a/tests/test_schema_functions.py b/tests/test_schema_functions.py index a9cb358ff..c8a24b307 100644 --- a/tests/test_schema_functions.py +++ b/tests/test_schema_functions.py @@ -1,10 +1,11 @@ import dataclasses -import re from datetime import date from enum import Enum from typing import Any import pytest +from typing_extensions import get_args, get_type_hints # noqa: UP035 (https://github.com/astral-sh/ruff/pull/18476) +from typing_inspection.introspection import UNKNOWN, AnnotationSource, inspect_annotation from pydantic_core import SchemaError, SchemaSerializer, SchemaValidator, ValidationError, core_schema @@ -332,10 +333,14 @@ def test_schema_functions(function, args_kwargs, expected_schema): def test_all_schema_functions_used(): - all_types = { - re.sub(r".+'(.+?)'.+", r'\1', s.__annotations__['type'].__forward_arg__) - for s in core_schema.CoreSchema.__args__ - } + all_types: set[str] = set() + for schema_typeddict in core_schema.CoreSchema.__args__: + annotation = get_type_hints(schema_typeddict, include_extras=True)['type'] + inspected_ann = inspect_annotation(annotation, annotation_source=AnnotationSource.TYPED_DICT) + annotation = inspected_ann.type + assert annotation is not UNKNOWN + all_types.add(get_args(annotation)[0]) + types_used = {args['type'] for _, _, args in all_schema_functions if 'type' in args} # isn't a CoreSchema type diff --git a/tests/test_validation_context.py b/tests/test_validation_context.py index 5d71f5b55..fd5ae75c2 100644 --- a/tests/test_validation_context.py +++ b/tests/test_validation_context.py @@ -72,11 +72,10 @@ def f(input_value, validator, info): assert v.validate_python('foobar', None, {}) == 'foobar' - # internal error!, use generic bit of error message to match both cpython and pypy - with pytest.raises(TypeError, match='is not iterable'): + with pytest.raises(TypeError): v.validate_test('foobar') - with pytest.raises(TypeError, match='is not iterable'): + with pytest.raises(TypeError): v.isinstance_test('foobar') with pytest.raises(ValidationError, match=r'Value error, wrong \[type=value_error,'): @@ -84,7 +83,7 @@ def f(input_value, validator, info): assert v.isinstance_test('foobar', None, {}) is True - with pytest.raises(TypeError, match='is not iterable'): + with pytest.raises(TypeError): v.isinstance_test('foobar') assert v.isinstance_test('foobar', None, {'error'}) is False diff --git a/tests/validators/test_arguments.py b/tests/validators/test_arguments.py index ec7c409bb..5a147cc40 100644 --- a/tests/validators/test_arguments.py +++ b/tests/validators/test_arguments.py @@ -1,3 +1,4 @@ +import platform import re import sys from functools import wraps @@ -1137,6 +1138,9 @@ def test_invalid_schema(): ) +@pytest.mark.xfail( + platform.python_implementation() == 'PyPy' and sys.version_info[:2] == (3, 11), reason='pypy 3.11 type formatting' +) def test_error_display(pydantic_version): v = SchemaValidator( core_schema.arguments_schema( diff --git a/tests/validators/test_custom_error.py b/tests/validators/test_custom_error.py index ada4aef47..3839b5313 100644 --- a/tests/validators/test_custom_error.py +++ b/tests/validators/test_custom_error.py @@ -1,6 +1,6 @@ import pytest -from pydantic_core import SchemaError, SchemaValidator, ValidationError, core_schema, validate_core_schema +from pydantic_core import SchemaError, SchemaValidator, ValidationError, core_schema from ..conftest import PyAndJson @@ -31,11 +31,6 @@ def test_custom_error_type(py_and_json: PyAndJson): ] -def test_custom_error_error(): - with pytest.raises(SchemaError, match=r'custom_error_type\s+Field required \[type=missing'): - validate_core_schema({'type': 'custom-error', 'schema': {'type': 'int'}}) - - def test_custom_error_invalid(): msg = "custom_error_message should not be provided if 'custom_error_type' matches a known error" with pytest.raises(SchemaError, match=msg): diff --git a/tests/validators/test_dataclasses.py b/tests/validators/test_dataclasses.py index cfead4423..6ae9f54f9 100644 --- a/tests/validators/test_dataclasses.py +++ b/tests/validators/test_dataclasses.py @@ -506,9 +506,7 @@ def validate_b(cls, v: str, info: core_schema.ValidationInfo) -> str: core_schema.dataclass_field(name='a', schema=core_schema.int_schema()), core_schema.dataclass_field( name='b', - schema=core_schema.with_info_after_validator_function( - Foo.validate_b, core_schema.str_schema(), field_name='b' - ), + schema=core_schema.with_info_after_validator_function(Foo.validate_b, core_schema.str_schema()), ), ], ), @@ -540,7 +538,7 @@ def validate_b(cls, v: bytes, info: core_schema.ValidationInfo) -> str: [ core_schema.dataclass_field(name='a', schema=core_schema.int_schema()), core_schema.dataclass_field( - name='b', schema=core_schema.with_info_plain_validator_function(Foo.validate_b, field_name='b') + name='b', schema=core_schema.with_info_plain_validator_function(Foo.validate_b) ), ], ), @@ -573,9 +571,7 @@ def validate_b(cls, v: bytes, info: core_schema.ValidationInfo) -> bytes: core_schema.dataclass_field(name='a', schema=core_schema.int_schema()), core_schema.dataclass_field( name='b', - schema=core_schema.with_info_before_validator_function( - Foo.validate_b, core_schema.str_schema(), field_name='b' - ), + schema=core_schema.with_info_before_validator_function(Foo.validate_b, core_schema.str_schema()), ), ], ), @@ -612,9 +608,7 @@ def validate_b( core_schema.dataclass_field(name='a', schema=core_schema.int_schema()), core_schema.dataclass_field( name='b', - schema=core_schema.with_info_wrap_validator_function( - Foo.validate_b, core_schema.str_schema(), field_name='b' - ), + schema=core_schema.with_info_wrap_validator_function(Foo.validate_b, core_schema.str_schema()), ), ], ), @@ -649,9 +643,7 @@ def validate_b( core_schema.dataclass_field(name='a', schema=core_schema.int_schema()), core_schema.dataclass_field( name='b', - schema=core_schema.with_info_wrap_validator_function( - Foo.validate_b, core_schema.str_schema(), field_name='b' - ), + schema=core_schema.with_info_wrap_validator_function(Foo.validate_b, core_schema.str_schema()), ), ], ), @@ -878,9 +870,7 @@ def func(x, info): core_schema.dataclass_field('field_a', core_schema.str_schema()), core_schema.dataclass_field( 'field_b', - core_schema.with_info_after_validator_function( - func, core_schema.int_schema(), field_name='field_b' - ), + core_schema.with_info_after_validator_function(func, core_schema.int_schema()), ), core_schema.dataclass_field('field_c', core_schema.int_schema()), ], @@ -1295,9 +1285,7 @@ def validate_b(cls, v: bytes, info: core_schema.ValidationInfo) -> bytes: core_schema.dataclass_field(name='a', schema=core_schema.int_schema()), core_schema.dataclass_field( name='b', - schema=core_schema.with_info_before_validator_function( - Foo.validate_b, core_schema.str_schema(), field_name='b' - ), + schema=core_schema.with_info_before_validator_function(Foo.validate_b, core_schema.str_schema()), ), ], ), @@ -1332,9 +1320,7 @@ def validate_b(cls, v: str, info: core_schema.ValidationInfo) -> str: core_schema.dataclass_field(name='a', schema=core_schema.int_schema()), core_schema.dataclass_field( name='b', - schema=core_schema.with_info_after_validator_function( - Foo.validate_b, core_schema.str_schema(), field_name='b' - ), + schema=core_schema.with_info_after_validator_function(Foo.validate_b, core_schema.str_schema()), ), ], ), @@ -1550,15 +1536,9 @@ def _wrap_validator(cls, v, validator, info): field_schema = core_schema.int_schema() if validator == 'field': - field_schema = core_schema.with_info_before_validator_function( - Dataclass._validator, field_schema, field_name='a' - ) - field_schema = core_schema.with_info_wrap_validator_function( - Dataclass._wrap_validator, field_schema, field_name='a' - ) - field_schema = core_schema.with_info_after_validator_function( - Dataclass._validator, field_schema, field_name='a' - ) + field_schema = core_schema.with_info_before_validator_function(Dataclass._validator, field_schema) + field_schema = core_schema.with_info_wrap_validator_function(Dataclass._wrap_validator, field_schema) + field_schema = core_schema.with_info_after_validator_function(Dataclass._validator, field_schema) dataclass_schema = core_schema.dataclass_schema( Dataclass, diff --git a/tests/validators/test_date.py b/tests/validators/test_date.py index 161f115d9..8300a15ad 100644 --- a/tests/validators/test_date.py +++ b/tests/validators/test_date.py @@ -7,7 +7,7 @@ import pytest -from pydantic_core import SchemaError, SchemaValidator, ValidationError, core_schema, validate_core_schema +from pydantic_core import SchemaError, SchemaValidator, ValidationError, core_schema from pydantic_core import core_schema as cs from ..conftest import Err, PyAndJson @@ -229,11 +229,6 @@ def test_date_kwargs(kwargs: dict[str, Any], input_value: date, expected: Err | assert output == expected -def test_invalid_constraint(): - with pytest.raises(SchemaError, match=r'date\.gt\n Input should be a valid date or datetime'): - validate_core_schema({'type': 'date', 'gt': 'foobar'}) - - def test_dict_py(): v = SchemaValidator(cs.dict_schema(keys_schema=cs.date_schema(), values_schema=cs.int_schema())) assert v.validate_python({date(2000, 1, 1): 2, date(2000, 1, 2): 4}) == {date(2000, 1, 1): 2, date(2000, 1, 2): 4} @@ -308,8 +303,3 @@ def test_date_past_future_today(): assert v.isinstance_python(today) is False assert v.isinstance_python(today - timedelta(days=1)) is False assert v.isinstance_python(today + timedelta(days=1)) is True - - -def test_offset_too_large(): - with pytest.raises(SchemaError, match=r'Input should be less than 86400 \[type=less_than,'): - validate_core_schema(core_schema.date_schema(now_op='past', now_utc_offset=24 * 3600)) diff --git a/tests/validators/test_datetime.py b/tests/validators/test_datetime.py index 21b0db61e..5e319dc23 100644 --- a/tests/validators/test_datetime.py +++ b/tests/validators/test_datetime.py @@ -8,7 +8,7 @@ import pytest -from pydantic_core import SchemaError, SchemaValidator, ValidationError, core_schema, validate_core_schema +from pydantic_core import SchemaError, SchemaValidator, ValidationError, core_schema from pydantic_core import core_schema as cs from ..conftest import Err, PyAndJson @@ -198,7 +198,7 @@ def test_custom_timezone_repr(): assert output.tzinfo.dst(output) is None assert output.tzinfo.tzname(output) == '-12:15' assert str(output.tzinfo) == '-12:15' - assert repr(output.tzinfo) == 'TzInfo(-12:15)' + assert repr(output.tzinfo) == 'TzInfo(-44100)' def test_custom_timezone_utc_repr(): @@ -208,7 +208,7 @@ def test_custom_timezone_utc_repr(): assert output.tzinfo.dst(output) is None assert output.tzinfo.tzname(output) == 'UTC' assert str(output.tzinfo) == 'UTC' - assert repr(output.tzinfo) == 'TzInfo(UTC)' + assert repr(output.tzinfo) == 'TzInfo(0)' def test_tz_comparison(): @@ -230,16 +230,16 @@ def test_tz_comparison(): def test_tz_info_deepcopy(): output = SchemaValidator(cs.datetime_schema()).validate_python('2023-02-15T16:23:44.037Z') c = copy.deepcopy(output) - assert repr(output.tzinfo) == 'TzInfo(UTC)' - assert repr(c.tzinfo) == 'TzInfo(UTC)' + assert repr(output.tzinfo) == 'TzInfo(0)' + assert repr(c.tzinfo) == 'TzInfo(0)' assert c == output def test_tz_info_copy(): output = SchemaValidator(cs.datetime_schema()).validate_python('2023-02-15T16:23:44.037Z') c = copy.copy(output) - assert repr(output.tzinfo) == 'TzInfo(UTC)' - assert repr(c.tzinfo) == 'TzInfo(UTC)' + assert repr(output.tzinfo) == 'TzInfo(0)' + assert repr(c.tzinfo) == 'TzInfo(0)' assert c == output @@ -318,11 +318,6 @@ def test_union(): assert v.validate_python(datetime(2022, 1, 2)) == datetime(2022, 1, 2) -def test_invalid_constraint(): - with pytest.raises(SchemaError, match=r'datetime\.gt\n Input should be a valid datetime'): - validate_core_schema({'type': 'datetime', 'gt': 'foobar'}) - - @pytest.mark.parametrize( 'input_value,expected', [ @@ -421,19 +416,6 @@ def test_mock_utc_offset_8_hours(mocker): assert not v.isinstance_python(future) -def test_offset_too_large(): - with pytest.raises(SchemaError, match=r'Input should be greater than -86400 \[type=greater_than,'): - validate_core_schema(core_schema.datetime_schema(now_op='past', now_utc_offset=-24 * 3600)) - - -def test_raises_schema_error_for_unknown_constraint_kind(): - with pytest.raises( - SchemaError, - match=(r'Input should be \'aware\' or \'naive\' \[type=literal_error, input_value=\'foo\', input_type=str\]'), - ): - validate_core_schema({'type': 'datetime', 'tz_constraint': 'foo'}) - - def test_aware(): v = SchemaValidator(core_schema.datetime_schema(tz_constraint='aware')) value = datetime.now(tz=timezone.utc) @@ -511,11 +493,6 @@ def test_tz_constraint_too_high(): SchemaValidator(core_schema.datetime_schema(tz_constraint=2**64)) -def test_tz_constraint_wrong(): - with pytest.raises(SchemaError, match="Input should be 'aware' or 'naive"): - validate_core_schema(core_schema.datetime_schema(tz_constraint='wrong')) - - def test_tz_hash() -> None: v = SchemaValidator(core_schema.datetime_schema()) lookup: dict[datetime, str] = {} diff --git a/tests/validators/test_definitions.py b/tests/validators/test_definitions.py index 1c730ee6f..967eeae2d 100644 --- a/tests/validators/test_definitions.py +++ b/tests/validators/test_definitions.py @@ -1,6 +1,6 @@ import pytest -from pydantic_core import SchemaError, SchemaValidator, core_schema, validate_core_schema +from pydantic_core import SchemaError, SchemaValidator, core_schema from ..conftest import plain_repr @@ -45,20 +45,6 @@ def test_check_ref_used_ignores_metadata(): # assert plain_repr(v).endswith('definitions=[])') -def test_def_error(): - with pytest.raises(SchemaError) as exc_info: - validate_core_schema( - core_schema.definitions_schema( - core_schema.list_schema(core_schema.definition_reference_schema('foobar')), - [core_schema.int_schema(ref='foobar'), {'type': 'wrong'}], - ) - ) - assert str(exc_info.value).startswith( - "Invalid Schema:\ndefinitions.definitions.1\n Input tag 'wrong' found using 'type'" - ) - assert exc_info.value.error_count() == 1 - - def test_dict_repeat(): v = SchemaValidator( core_schema.definitions_schema( diff --git a/tests/validators/test_definitions_recursive.py b/tests/validators/test_definitions_recursive.py index 34b8ca445..b36d4aa07 100644 --- a/tests/validators/test_definitions_recursive.py +++ b/tests/validators/test_definitions_recursive.py @@ -1,5 +1,6 @@ import datetime import platform +import sys from dataclasses import dataclass from typing import Optional @@ -752,6 +753,9 @@ def test_many_uses_of_ref(): assert v.validate_python(long_input) == long_input +@pytest.mark.xfail( + platform.python_implementation() == 'PyPy' and sys.version_info[:2] == (3, 11), reason='pypy 3.11 type formatting' +) def test_error_inside_definition_wrapper(): with pytest.raises(SchemaError) as exc_info: SchemaValidator( diff --git a/tests/validators/test_float.py b/tests/validators/test_float.py index 8a0235ed5..dd78e8499 100644 --- a/tests/validators/test_float.py +++ b/tests/validators/test_float.py @@ -1,5 +1,6 @@ import math import re +import sys from decimal import Decimal from typing import Any @@ -11,7 +12,8 @@ from ..conftest import Err, PyAndJson, plain_repr -f64_max = 1.7976931348623157e308 +i64_max = (2**63) - 1 +f64_max = sys.float_info.max @pytest.mark.parametrize( @@ -20,6 +22,8 @@ (0, 0), (1, 1), (42, 42), + (i64_max + 1, i64_max + 1), + (f64_max, f64_max), ('42', 42), (' 42.1 ', 42.1), ('42.123', 42.123), diff --git a/tests/validators/test_function.py b/tests/validators/test_function.py index 562687268..8d138d16c 100644 --- a/tests/validators/test_function.py +++ b/tests/validators/test_function.py @@ -2,12 +2,13 @@ import platform import re from copy import deepcopy +from dataclasses import dataclass from typing import Any import pytest from dirty_equals import HasRepr -from pydantic_core import CoreConfig, SchemaError, SchemaValidator, ValidationError, core_schema, validate_core_schema +from pydantic_core import CoreConfig, SchemaValidator, ValidationError, core_schema from pydantic_core import core_schema as cs from ..conftest import plain_repr @@ -209,14 +210,6 @@ def f(input_value, validator, info): ) -def test_function_wrap_not_callable(): - with pytest.raises(SchemaError, match='function-wrap.function.typed-dict.function\n Input should be callable'): - validate_core_schema(core_schema.with_info_wrap_validator_function([], core_schema.str_schema())) - - with pytest.raises(SchemaError, match='function-wrap.function\n Field required'): - validate_core_schema({'type': 'function-wrap', 'schema': {'type': 'str'}}) - - def test_wrap_error(): def f(input_value, validator, info): try: @@ -425,17 +418,6 @@ def f(input_value): assert v.validate_python('x') == 'xx' -def test_plain_with_schema(): - with pytest.raises(SchemaError, match='function-plain.schema\n Extra inputs are not permitted'): - validate_core_schema( - { - 'type': 'function-plain', - 'function': {'type': 'with-info', 'function': lambda x: x}, - 'schema': {'type': 'str'}, - } - ) - - def test_validate_assignment(): def f(input_value): input_value.more = 'foobar' @@ -604,7 +586,7 @@ def f(input_value: Any, info: core_schema.ValidationInfo) -> Any: core_schema.model_fields_schema( { 'x': core_schema.model_field( - core_schema.with_info_before_validator_function(f, core_schema.str_schema(), field_name='x') + core_schema.with_info_before_validator_function(f, core_schema.str_schema()) ) } ), @@ -630,7 +612,7 @@ def f(input_value: str, info: core_schema.ValidationInfo) -> Any: core_schema.model_fields_schema( { 'x': core_schema.model_field( - core_schema.with_info_after_validator_function(f, core_schema.str_schema(), field_name='x') + core_schema.with_info_after_validator_function(f, core_schema.str_schema()) ) } ), @@ -654,7 +636,7 @@ def f(input_value: Any, info: core_schema.ValidationInfo) -> Any: core_schema.model_schema( Model, core_schema.model_fields_schema( - {'x': core_schema.model_field(core_schema.with_info_plain_validator_function(f, field_name='x'))} + {'x': core_schema.model_field(core_schema.with_info_plain_validator_function(f))} ), ) ) @@ -662,6 +644,39 @@ def f(input_value: Any, info: core_schema.ValidationInfo) -> Any: assert v.validate_python({'x': b'foo'}).x == 'input: foo' +def test_model_field_validator_reuse() -> None: + class Model: + x: str + y: str + + def f(input_value: Any, info: core_schema.ValidationInfo) -> Any: + return f'{info.field_name}: {input_value}' + + # When a type alias with a validator function is used on multiple fields, + # its core schema is only generated once (with the first field_name) and reused. + # See https://github.com/pydantic/pydantic/issues/11737 + with pytest.warns( + DeprecationWarning, match='`field_name` argument on `with_info_plain_validator_function` is deprecated' + ): + validator = core_schema.with_info_plain_validator_function(f, field_name='x') + + v = SchemaValidator( + core_schema.model_schema( + Model, + core_schema.model_fields_schema( + { + 'x': core_schema.model_field(validator), + 'y': core_schema.model_field(validator), + } + ), + ) + ) + + m = v.validate_python({'x': 'foo', 'y': 'bar'}) + assert m.x == 'x: foo' + assert m.y == 'y: bar' + + def test_model_field_wrap_validator() -> None: class Model: x: str @@ -678,7 +693,7 @@ def f(input_value: Any, val: core_schema.ValidatorFunctionWrapHandler, info: cor core_schema.model_fields_schema( { 'x': core_schema.model_field( - core_schema.with_info_wrap_validator_function(f, core_schema.str_schema(), field_name='x') + core_schema.with_info_wrap_validator_function(f, core_schema.str_schema()) ) } ), @@ -688,17 +703,13 @@ def f(input_value: Any, val: core_schema.ValidatorFunctionWrapHandler, info: cor assert v.validate_python({'x': b'foo'}).x == 'input: foo' -def check_info_field_name_none(info: core_schema.ValidationInfo) -> None: - assert info.field_name is None - assert info.data == {} - - -def test_non_model_field_before_validator_tries_to_access_field_info() -> None: +def test_non_model_field_before_validator_field_info() -> None: class Model: x: str def f(input_value: Any, info: core_schema.ValidationInfo) -> Any: - check_info_field_name_none(info) + assert info.field_name == 'x' + assert info.data == {} assert isinstance(input_value, bytes) return f'input: {input_value.decode()}' @@ -718,12 +729,13 @@ def f(input_value: Any, info: core_schema.ValidationInfo) -> Any: assert v.validate_python({'x': b'foo'}).x == 'input: foo' -def test_non_model_field_after_validator_tries_to_access_field_info() -> None: +def test_non_model_field_after_validator_field_info() -> None: class Model: x: str def f(input_value: Any, info: core_schema.ValidationInfo) -> Any: - check_info_field_name_none(info) + assert info.field_name == 'x' + assert info.data == {} return f'input: {input_value}' v = SchemaValidator( @@ -742,12 +754,13 @@ def f(input_value: Any, info: core_schema.ValidationInfo) -> Any: assert v.validate_python({'x': b'foo'}).x == 'input: foo' -def test_non_model_field_plain_validator_tries_to_access_field_info() -> None: +def test_non_model_field_plain_validator_field_info() -> None: class Model: x: str def f(input_value: Any, info: core_schema.ValidationInfo) -> Any: - check_info_field_name_none(info) + assert info.field_name == 'x' + assert info.data == {} assert isinstance(input_value, bytes) return f'input: {input_value.decode()}' @@ -763,13 +776,14 @@ def f(input_value: Any, info: core_schema.ValidationInfo) -> Any: assert v.validate_python({'x': b'foo'}).x == 'input: foo' -def test_non_model_field_wrap_validator_tries_to_access_field_info() -> None: +def test_non_model_field_wrap_validator_field_info() -> None: class Model: __slots__ = '__dict__', '__pydantic_fields_set__', '__pydantic_extra__', '__pydantic_private__' x: str def f(input_value: Any, val: core_schema.ValidatorFunctionWrapHandler, info: core_schema.ValidationInfo) -> Any: - check_info_field_name_none(info) + assert info.field_name == 'x' + assert info.data == {} return f'input: {val(input_value)}' v = SchemaValidator( @@ -803,7 +817,7 @@ def f(input_value: Any, info: core_schema.ValidationInfo) -> Any: 'a': core_schema.typed_dict_field(core_schema.int_schema()), 'b': core_schema.typed_dict_field(core_schema.int_schema()), 'c': core_schema.typed_dict_field( - core_schema.with_info_after_validator_function(f, core_schema.str_schema(), field_name='c') + core_schema.with_info_after_validator_function(f, core_schema.str_schema()) ), } ) @@ -821,6 +835,68 @@ def f(input_value: Any, info: core_schema.ValidationInfo) -> Any: assert info_stuff == {'field_name': 'c', 'data': {'a': 1}} +def test_typed_dict_validator_reuse() -> None: + def f(input_value: Any, info: core_schema.ValidationInfo) -> Any: + return f'{info.field_name}: {input_value}' + + # When a type alias with a validator function is used on multiple fields, + # its core schema is only generated once (with the first field_name) and reused. + # See https://github.com/pydantic/pydantic/issues/11737 + with pytest.warns( + DeprecationWarning, match='`field_name` argument on `with_info_plain_validator_function` is deprecated' + ): + validator = core_schema.with_info_plain_validator_function(f, field_name='x') + + v = SchemaValidator( + core_schema.typed_dict_schema( + { + 'x': core_schema.model_field(validator), + 'y': core_schema.model_field(validator), + } + ) + ) + + data = v.validate_python({'x': 'foo', 'y': 'bar'}) + assert data['x'] == 'x: foo' + assert data['y'] == 'y: bar' + + +def test_dataclass_validator_reuse() -> None: + @dataclass + class Model: + x: str + y: str + + def f(input_value: Any, info: core_schema.ValidationInfo) -> Any: + return f'{info.field_name}: {input_value}' + + # When a type alias with a validator function is used on multiple fields, + # its core schema is only generated once (with the first field_name) and reused. + # See https://github.com/pydantic/pydantic/issues/11737 + with pytest.warns( + DeprecationWarning, match='`field_name` argument on `with_info_plain_validator_function` is deprecated' + ): + validator = core_schema.with_info_plain_validator_function(f, field_name='x') + + v = SchemaValidator( + core_schema.dataclass_schema( + Model, + core_schema.dataclass_args_schema( + 'Model', + [ + core_schema.dataclass_field(name='x', schema=validator), + core_schema.dataclass_field(name='y', schema=validator), + ], + ), + ['x', 'y'], + ) + ) + + m = v.validate_python({'x': 'foo', 'y': 'bar'}) + assert m.x == 'x: foo' + assert m.y == 'y: bar' + + @pytest.mark.parametrize( 'mode,calls1,calls2', [ @@ -916,35 +992,6 @@ def f_w(v: Any, handler: core_schema.ValidatorFunctionWrapHandler, info: core_sc calls.clear() -def test_reprs() -> None: - reprs: list[str] = [] - - def sample_repr(v: Any, info: core_schema.ValidationInfo) -> Any: - reprs.append(repr(info)) - return v - - v = SchemaValidator( - core_schema.chain_schema( - [ - core_schema.with_info_plain_validator_function(sample_repr), - core_schema.with_info_plain_validator_function(sample_repr, field_name='x'), - ] - ) - ) - - class Foo: - def __repr__(self) -> str: - return 'This is Foo!' - - v.validate_python(Foo()) - - # insert_assert(reprs) - assert reprs == [ - 'ValidationInfo(config=None, context=None, data=None, field_name=None)', - "ValidationInfo(config=None, context=None, data=None, field_name='x')", - ] - - def test_function_after_doesnt_change_mode() -> None: # https://github.com/pydantic/pydantic/issues/7468 - function-after was # incorrectly forcing Python validation mode diff --git a/tests/validators/test_int.py b/tests/validators/test_int.py index 4db426032..1de2e0f0a 100644 --- a/tests/validators/test_int.py +++ b/tests/validators/test_int.py @@ -11,7 +11,7 @@ from ..conftest import Err, PyAndJson, plain_repr -i64_max = 9_223_372_036_854_775_807 +i64_max = (2**63) - 1 @pytest.mark.parametrize( diff --git a/tests/validators/test_model.py b/tests/validators/test_model.py index 2ce2c0a56..253b8a734 100644 --- a/tests/validators/test_model.py +++ b/tests/validators/test_model.py @@ -1054,9 +1054,7 @@ def func(x, info): { 'field_a': core_schema.model_field(core_schema.str_schema()), 'field_b': core_schema.model_field( - core_schema.with_info_after_validator_function( - func, core_schema.int_schema(), field_name='field_b' - ) + core_schema.with_info_after_validator_function(func, core_schema.int_schema()) ), 'field_c': core_schema.model_field(core_schema.int_schema()), } @@ -1145,17 +1143,17 @@ class MyModel: ( core_schema.with_info_after_validator_function, (({'a': 1, 'b': 2}, None, {'b'}), 'ValidationInfo(config=None, context=None, data=None, field_name=None)'), - (({'a': 10, 'b': 2}, None, {'a'}), 'ValidationInfo(config=None, context=None, data=None, field_name=None)'), + (({'a': 10, 'b': 2}, None, {'a'}), "ValidationInfo(config=None, context=None, data=None, field_name='a')"), ), ( core_schema.with_info_before_validator_function, ({'b': 2}, 'ValidationInfo(config=None, context=None, data=None, field_name=None)'), - ({'a': 10, 'b': 2}, 'ValidationInfo(config=None, context=None, data=None, field_name=None)'), + ({'a': 10, 'b': 2}, "ValidationInfo(config=None, context=None, data=None, field_name='a')"), ), ( core_schema.with_info_wrap_validator_function, ({'b': 2}, 'ValidationInfo(config=None, context=None, data=None, field_name=None)'), - ({'a': 10, 'b': 2}, 'ValidationInfo(config=None, context=None, data=None, field_name=None)'), + ({'a': 10, 'b': 2}, "ValidationInfo(config=None, context=None, data=None, field_name='a')"), ), ], ) diff --git a/tests/validators/test_model_fields.py b/tests/validators/test_model_fields.py index cc04f07c1..e288f2fd8 100644 --- a/tests/validators/test_model_fields.py +++ b/tests/validators/test_model_fields.py @@ -9,7 +9,7 @@ import pytest from dirty_equals import FunctionCheck, HasRepr, IsStr -from pydantic_core import CoreConfig, SchemaError, SchemaValidator, ValidationError, core_schema, validate_core_schema +from pydantic_core import CoreConfig, SchemaError, SchemaValidator, ValidationError, core_schema from ..conftest import Err, PyAndJson @@ -430,11 +430,6 @@ def test_json_error(): ] -def test_missing_schema_key(): - with pytest.raises(SchemaError, match='model-fields.fields.x.schema\n Field required'): - validate_core_schema({'type': 'model-fields', 'fields': {'x': {'type': 'str'}}}) - - def test_fields_required_by_default(): """By default all fields should be required""" v = SchemaValidator( @@ -739,11 +734,9 @@ def test_paths_allow_by_name(py_and_json: PyAndJson, input_value): @pytest.mark.parametrize( 'alias_schema,error', [ - ({'validation_alias': ['foo', ['bar']]}, 'Input should be a valid string'), ({'validation_alias': []}, 'Lookup paths should have at least one element'), ({'validation_alias': [[]]}, 'Each alias path should have at least one element'), ({'validation_alias': [123]}, "TypeError: 'int' object cannot be converted to 'PyList'"), - ({'validation_alias': [[[]]]}, 'Input should be a valid string'), ({'validation_alias': [[1, 'foo']]}, 'TypeError: The first item in an alias path should be a string'), ], ids=repr, @@ -751,12 +744,10 @@ def test_paths_allow_by_name(py_and_json: PyAndJson, input_value): def test_alias_build_error(alias_schema, error): with pytest.raises(SchemaError, match=error): SchemaValidator( - schema=validate_core_schema( - { - 'type': 'model-fields', - 'fields': {'field_a': {'type': 'model-field', 'schema': {'type': 'int'}, **alias_schema}}, - } - ) + schema={ + 'type': 'model-fields', + 'fields': {'field_a': {'type': 'model-field', 'schema': {'type': 'int'}, **alias_schema}}, + } ) @@ -1478,20 +1469,6 @@ def test_bad_default_factory(default_factory, error_message): class TestOnError: - def test_on_error_bad_name(self): - with pytest.raises(SchemaError, match="Input should be 'raise', 'omit' or 'default'"): - validate_core_schema( - { - 'type': 'model-fields', - 'fields': { - 'x': { - 'type': 'model-field', - 'schema': {'type': 'default', 'schema': {'type': 'str'}, 'on_error': 'rais'}, - } - }, - } - ) - def test_on_error_bad_default(self): with pytest.raises(SchemaError, match="'on_error = default' requires a `default` or `default_factory`"): SchemaValidator( diff --git a/tests/validators/test_model_init.py b/tests/validators/test_model_init.py index 08f13ac54..463a9a48a 100644 --- a/tests/validators/test_model_init.py +++ b/tests/validators/test_model_init.py @@ -430,15 +430,9 @@ def _wrap_validator(cls, v, validator, info): field_schema = core_schema.int_schema() if validator == 'field': - field_schema = core_schema.with_info_before_validator_function( - Model._validator, field_schema, field_name='a' - ) - field_schema = core_schema.with_info_wrap_validator_function( - Model._wrap_validator, field_schema, field_name='a' - ) - field_schema = core_schema.with_info_after_validator_function( - Model._validator, field_schema, field_name='a' - ) + field_schema = core_schema.with_info_before_validator_function(Model._validator, field_schema) + field_schema = core_schema.with_info_wrap_validator_function(Model._wrap_validator, field_schema) + field_schema = core_schema.with_info_after_validator_function(Model._validator, field_schema) model_schema = core_schema.model_schema( Model, core_schema.model_fields_schema({'a': core_schema.model_field(field_schema)}) diff --git a/tests/validators/test_model_root.py b/tests/validators/test_model_root.py index 4e0a55048..96e492c4d 100644 --- a/tests/validators/test_model_root.py +++ b/tests/validators/test_model_root.py @@ -138,7 +138,7 @@ def f(input_value: str, info): v = SchemaValidator( core_schema.model_schema( RootModel, - core_schema.with_info_after_validator_function(f, core_schema.str_schema(), field_name='root'), + core_schema.with_info_after_validator_function(f, core_schema.str_schema()), root_model=True, ) ) diff --git a/tests/validators/test_pickling.py b/tests/validators/test_pickling.py index 2037ab8c9..0ddaf5991 100644 --- a/tests/validators/test_pickling.py +++ b/tests/validators/test_pickling.py @@ -4,15 +4,13 @@ import pytest -from pydantic_core import core_schema, validate_core_schema +from pydantic_core import core_schema from pydantic_core._pydantic_core import SchemaValidator, ValidationError def test_basic_schema_validator(): v = SchemaValidator( - validate_core_schema( - {'type': 'dict', 'strict': True, 'keys_schema': {'type': 'int'}, 'values_schema': {'type': 'int'}} - ) + {'type': 'dict', 'strict': True, 'keys_schema': {'type': 'int'}, 'values_schema': {'type': 'int'}} ) v = pickle.loads(pickle.dumps(v)) assert v.validate_python({'1': 2, '3': 4}) == {1: 2, 3: 4} @@ -51,3 +49,26 @@ def test_schema_validator_tz_pickle() -> None: validated = v.validate_python('2022-06-08T12:13:14-12:15') assert validated == original assert pickle.loads(pickle.dumps(validated)) == validated == original + + +# Should be defined at the module level for pickling to work: +class Model: + __pydantic_validator__: SchemaValidator + __pydantic_complete__ = True + + +def test_schema_validator_not_reused_when_unpickling() -> None: + s = SchemaValidator( + core_schema.model_schema( + cls=Model, + schema=core_schema.model_fields_schema(fields={}, model_name='Model'), + config={'title': 'Model'}, + ref='Model:123', + ) + ) + + Model.__pydantic_validator__ = s + assert 'Prebuilt' not in str(Model.__pydantic_validator__) + + reconstructed = pickle.loads(pickle.dumps(Model.__pydantic_validator__)) + assert 'Prebuilt' not in str(reconstructed) diff --git a/tests/validators/test_string.py b/tests/validators/test_string.py index 4f295056b..0ea5c23a3 100644 --- a/tests/validators/test_string.py +++ b/tests/validators/test_string.py @@ -1,3 +1,4 @@ +import platform import re import sys from decimal import Decimal @@ -172,6 +173,10 @@ def test_str_constrained_config(): @pytest.mark.parametrize('engine', [None, 'rust-regex', 'python-re']) def test_invalid_regex(engine): + if platform.python_implementation() == 'PyPy' and sys.version_info[:2] == (3, 11): + # pypy 3.11 type formatting + pytest.xfail() + # TODO uncomment and fix once #150 is done # with pytest.raises(SchemaError) as exc_info: # SchemaValidator({'type': 'str', 'pattern': 123}) @@ -343,6 +348,9 @@ def test_coerce_numbers_to_str_from_json(number: str, expected_str: str) -> None @pytest.mark.parametrize('mode', (None, 'schema', 'config')) +@pytest.mark.xfail( + platform.python_implementation() == 'PyPy' and sys.version_info[:2] == (3, 11), reason='pypy 3.11 type formatting' +) def test_backtracking_regex_rust_unsupported(mode) -> None: pattern = r'r(#*)".*?"\1' diff --git a/tests/validators/test_time.py b/tests/validators/test_time.py index 069e359ad..9a643acfb 100644 --- a/tests/validators/test_time.py +++ b/tests/validators/test_time.py @@ -5,11 +5,20 @@ import pytest -from pydantic_core import SchemaError, SchemaValidator, ValidationError, core_schema, validate_core_schema +from pydantic_core import SchemaError, SchemaValidator, ValidationError, core_schema from ..conftest import Err, PyAndJson +@pytest.mark.parametrize( + 'constraint', + ['le', 'lt', 'ge', 'gt'], +) +def test_constraints_schema_validation_error(constraint: str) -> None: + with pytest.raises(SchemaError, match=f"'{constraint}' must be coercible to a time instance"): + SchemaValidator(core_schema.time_schema(**{constraint: 'bad_value'})) + + @pytest.mark.parametrize( 'input_value,expected', [ @@ -189,11 +198,6 @@ def test_time_bound_ctx(): ] -def test_invalid_constraint(): - with pytest.raises(SchemaError, match='Input should be in a valid time format'): - validate_core_schema({'type': 'time', 'gt': 'foobar'}) - - def test_dict_py(): v = SchemaValidator( core_schema.dict_schema(keys_schema=core_schema.time_schema(), values_schema=core_schema.int_schema()) @@ -291,8 +295,3 @@ def test_neg_7200(): def test_tz_constraint_too_high(): with pytest.raises(SchemaError, match='OverflowError: Python int too large to convert to C long'): SchemaValidator(core_schema.time_schema(tz_constraint=2**64)) - - -def test_tz_constraint_wrong(): - with pytest.raises(SchemaError, match="Input should be 'aware' or 'naive"): - validate_core_schema(core_schema.time_schema(tz_constraint='wrong')) diff --git a/tests/validators/test_timedelta.py b/tests/validators/test_timedelta.py index c10a2d592..243fbfb95 100644 --- a/tests/validators/test_timedelta.py +++ b/tests/validators/test_timedelta.py @@ -5,7 +5,7 @@ import pytest -from pydantic_core import SchemaError, SchemaValidator, ValidationError, core_schema, validate_core_schema +from pydantic_core import SchemaError, SchemaValidator, ValidationError, core_schema from ..conftest import Err, PyAndJson @@ -209,20 +209,6 @@ def test_timedelta_kwargs_strict(): assert output == timedelta(days=2, hours=1) -def test_invalid_constraint(): - with pytest.raises( - SchemaError, - match='Invalid Schema:\ntimedelta.gt\n Input should be a valid timedelta, invalid character in hour', - ): - validate_core_schema({'type': 'timedelta', 'gt': 'foobar'}) - - with pytest.raises( - SchemaError, - match='Invalid Schema:\ntimedelta.le\n Input should be a valid timedelta, invalid character in hour', - ): - validate_core_schema({'type': 'timedelta', 'le': 'foobar'}) - - def test_dict_py(): v = SchemaValidator( core_schema.dict_schema(keys_schema=core_schema.timedelta_schema(), values_schema=core_schema.int_schema()) diff --git a/tests/validators/test_typed_dict.py b/tests/validators/test_typed_dict.py index b224b65ea..3d96d40e0 100644 --- a/tests/validators/test_typed_dict.py +++ b/tests/validators/test_typed_dict.py @@ -8,7 +8,7 @@ import pytest from dirty_equals import FunctionCheck -from pydantic_core import CoreConfig, SchemaError, SchemaValidator, ValidationError, core_schema, validate_core_schema +from pydantic_core import CoreConfig, SchemaError, SchemaValidator, ValidationError, core_schema from ..conftest import Err, PyAndJson, assert_gc @@ -190,11 +190,6 @@ def test_allow_extra_invalid(): ) -def test_allow_extra_wrong(): - with pytest.raises(SchemaError, match="Input should be 'allow', 'forbid' or 'ignore'"): - validate_core_schema({'type': 'typed-dict', 'fields': {}, 'config': {'extra_fields_behavior': 'wrong'}}) - - def test_str_config(): v = SchemaValidator( core_schema.typed_dict_schema( @@ -231,11 +226,6 @@ def test_json_error(): ] -def test_missing_schema_key(): - with pytest.raises(SchemaError, match='typed-dict.fields.x.schema\n Field required'): - validate_core_schema({'type': 'typed-dict', 'fields': {'x': {'type': 'str'}}}) - - def test_fields_required_by_default(): """By default all fields should be required""" v = SchemaValidator( @@ -629,11 +619,9 @@ def test_paths_allow_by_name(py_and_json: PyAndJson, input_value): @pytest.mark.parametrize( 'alias_schema,error', [ - ({'validation_alias': ['foo', ['bar']]}, 'Input should be a valid string'), ({'validation_alias': []}, 'Lookup paths should have at least one element'), ({'validation_alias': [[]]}, 'Each alias path should have at least one element'), ({'validation_alias': [123]}, "TypeError: 'int' object cannot be converted to 'PyList'"), - ({'validation_alias': [[[]]]}, 'Input should be a valid string'), ({'validation_alias': [[1, 'foo']]}, 'TypeError: The first item in an alias path should be a string'), ], ids=repr, @@ -641,12 +629,10 @@ def test_paths_allow_by_name(py_and_json: PyAndJson, input_value): def test_alias_build_error(alias_schema, error): with pytest.raises(SchemaError, match=error): SchemaValidator( - schema=validate_core_schema( - { - 'type': 'typed-dict', - 'fields': {'field_a': {'type': 'typed-dict-field', 'schema': {'type': 'int'}, **alias_schema}}, - } - ) + schema={ + 'type': 'typed-dict', + 'fields': {'field_a': {'type': 'typed-dict-field', 'schema': {'type': 'int'}, **alias_schema}}, + } ) @@ -906,20 +892,6 @@ def test_bad_default_factory(default_factory, error_message): class TestOnError: - def test_on_error_bad_name(self): - with pytest.raises(SchemaError, match="Input should be 'raise', 'omit' or 'default'"): - validate_core_schema( - { - 'type': 'typed-dict', - 'fields': { - 'x': { - 'type': 'typed-dict-field', - 'schema': {'type': 'default', 'schema': {'type': 'str'}, 'on_error': 'rais'}, - } - }, - } - ) - def test_on_error_bad_omit(self): with pytest.raises(SchemaError, match="Field 'x': 'on_error = omit' cannot be set for required fields"): SchemaValidator( diff --git a/tests/validators/test_union.py b/tests/validators/test_union.py index f35ebfec0..ad785921d 100644 --- a/tests/validators/test_union.py +++ b/tests/validators/test_union.py @@ -1,3 +1,5 @@ +import platform +import sys from dataclasses import dataclass from datetime import date, time from enum import Enum, IntEnum @@ -8,7 +10,7 @@ import pytest from dirty_equals import IsFloat, IsInt -from pydantic_core import CoreConfig, SchemaError, SchemaValidator, ValidationError, core_schema, validate_core_schema +from pydantic_core import CoreConfig, SchemaError, SchemaValidator, ValidationError, core_schema from ..conftest import plain_repr @@ -231,22 +233,9 @@ def test_union_list_bool_int(): ] -def test_no_choices(pydantic_version): - with pytest.raises(SchemaError) as exc_info: - validate_core_schema({'type': 'union'}) - - assert str(exc_info.value) == ( - 'Invalid Schema:\n' - 'union.choices\n' - " Field required [type=missing, input_value={'type': 'union'}, input_type=dict]\n" - f' For further information visit https://errors.pydantic.dev/{pydantic_version}/v/missing' - ) - assert exc_info.value.error_count() == 1 - assert exc_info.value.errors() == [ - {'input': {'type': 'union'}, 'loc': ('union', 'choices'), 'msg': 'Field required', 'type': 'missing'} - ] - - +@pytest.mark.xfail( + platform.python_implementation() == 'PyPy' and sys.version_info[:2] == (3, 11), reason='pypy 3.11 type formatting' +) def test_empty_choices(): msg = r'Error building "union" validator:\s+SchemaError: One or more union choices required' with pytest.raises(SchemaError, match=msg): @@ -1358,3 +1347,83 @@ class Model: assert isinstance(validator.validate_python({'x': {'foo': 'foo'}}).x, Foo) assert isinstance(validator.validate_python({'x': {'bar': 'bar'}}).x, Bar) + + +def test_smart_union_wrap_validator_should_not_change_nested_model_field_counts() -> None: + """Adding a wrap validator on a union member should not affect smart union behavior""" + + class SubModel: + x: str = 'x' + + class ModelA: + type: str = 'A' + sub: SubModel + + class ModelB: + type: str = 'B' + sub: SubModel + + submodel_schema = core_schema.model_schema( + SubModel, + core_schema.model_fields_schema(fields={'x': core_schema.model_field(core_schema.str_schema())}), + ) + + wrapped_submodel_schema = core_schema.no_info_wrap_validator_function( + lambda v, handler: handler(v), submodel_schema + ) + + model_a_schema = core_schema.model_schema( + ModelA, + core_schema.model_fields_schema( + fields={ + 'type': core_schema.model_field( + core_schema.with_default_schema(core_schema.literal_schema(['A']), default='A'), + ), + 'sub': core_schema.model_field(wrapped_submodel_schema), + }, + ), + ) + + model_b_schema = core_schema.model_schema( + ModelB, + core_schema.model_fields_schema( + fields={ + 'type': core_schema.model_field( + core_schema.with_default_schema(core_schema.literal_schema(['B']), default='B'), + ), + 'sub': core_schema.model_field(submodel_schema), + }, + ), + ) + + for choices in permute_choices([model_a_schema, model_b_schema]): + schema = core_schema.union_schema(choices) + validator = SchemaValidator(schema) + + assert isinstance(validator.validate_python({'type': 'A', 'sub': {'x': 'x'}}), ModelA) + assert isinstance(validator.validate_python({'type': 'B', 'sub': {'x': 'x'}}), ModelB) + + # defaults to leftmost choice if there's a tie + assert isinstance(validator.validate_python({'sub': {'x': 'x'}}), choices[0]['cls']) + + # test validate_assignment + class RootModel: + ab: Union[ModelA, ModelB] + + root_model = core_schema.model_schema( + RootModel, + core_schema.model_fields_schema( + fields={'ab': core_schema.model_field(core_schema.union_schema([model_a_schema, model_b_schema]))} + ), + ) + + validator = SchemaValidator(root_model) + m = validator.validate_python({'ab': {'type': 'B', 'sub': {'x': 'x'}}}) + assert isinstance(m, RootModel) + assert isinstance(m.ab, ModelB) + assert m.ab.sub.x == 'x' + + m = validator.validate_assignment(m, 'ab', {'sub': {'x': 'y'}}) + assert isinstance(m, RootModel) + assert isinstance(m.ab, ModelA) + assert m.ab.sub.x == 'y' diff --git a/tests/validators/test_with_default.py b/tests/validators/test_with_default.py index 2b092d066..bb8775305 100644 --- a/tests/validators/test_with_default.py +++ b/tests/validators/test_with_default.py @@ -627,12 +627,18 @@ def val_func(v: Any, handler: core_schema.ValidatorFunctionWrapHandler) -> Any: validator = SchemaValidator( core_schema.with_default_schema(core_schema.no_info_wrap_validator_function(val_func, core_schema.int_schema())) ) - with pytest.raises(SchemaError, match='Uncaught UseDefault error, please check your usage of `default` validators'): + with pytest.raises( + SchemaError, + match='Uncaught `PydanticUseDefault` exception: the error was raised in a field validator and no default value is available for that field.', + ): validator.validate_python('') # same if there is no WithDefault validator validator = SchemaValidator(core_schema.no_info_wrap_validator_function(val_func, core_schema.int_schema())) - with pytest.raises(SchemaError, match='Uncaught UseDefault error, please check your usage of `default` validators'): + with pytest.raises( + SchemaError, + match='Uncaught `PydanticUseDefault` exception: the error was raised in a field validator and no default value is available for that field.', + ): validator.validate_python('') diff --git a/uv.lock b/uv.lock index 7ad8e1c5a..de11e849a 100644 --- a/uv.lock +++ b/uv.lock @@ -1,8 +1,10 @@ version = 1 +revision = 2 requires-python = ">=3.9" resolution-markers = [ "python_full_version == '3.13.*' and implementation_name == 'cpython'", - "(python_full_version >= '3.12' and implementation_name != 'cpython') or (python_full_version == '3.12.*' and implementation_name == 'cpython') or (python_full_version >= '3.14' and implementation_name == 'cpython')", + "python_full_version == '3.14.*' and implementation_name == 'cpython'", + "(python_full_version >= '3.12' and implementation_name != 'cpython') or (python_full_version == '3.12.*' and implementation_name == 'cpython') or (python_full_version >= '3.15' and implementation_name == 'cpython')", "python_full_version == '3.11.*'", "python_full_version == '3.10.*'", "python_full_version < '3.10'", @@ -12,18 +14,18 @@ resolution-markers = [ name = "asttokens" version = "3.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4a/e7/82da0a03e7ba5141f05cce0d302e6eed121ae055e0456ca228bf693984bc/asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7", size = 61978 } +sdist = { url = "https://files.pythonhosted.org/packages/4a/e7/82da0a03e7ba5141f05cce0d302e6eed121ae055e0456ca228bf693984bc/asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7", size = 61978, upload-time = "2024-11-30T04:30:14.439Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2", size = 26918 }, + { url = "https://files.pythonhosted.org/packages/25/8a/c46dcc25341b5bce5472c718902eb3d38600a903b14fa6aeecef3f21a46f/asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2", size = 26918, upload-time = "2024-11-30T04:30:10.946Z" }, ] [[package]] name = "attrs" version = "24.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/48/c8/6260f8ccc11f0917360fc0da435c5c9c7504e3db174d5a12a1494887b045/attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff", size = 805984 } +sdist = { url = "https://files.pythonhosted.org/packages/48/c8/6260f8ccc11f0917360fc0da435c5c9c7504e3db174d5a12a1494887b045/attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff", size = 805984, upload-time = "2024-12-16T06:59:29.899Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/89/aa/ab0f7891a01eeb2d2e338ae8fecbe57fcebea1a24dbb64d45801bfab481d/attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308", size = 63397 }, + { url = "https://files.pythonhosted.org/packages/89/aa/ab0f7891a01eeb2d2e338ae8fecbe57fcebea1a24dbb64d45801bfab481d/attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308", size = 63397, upload-time = "2024-12-16T06:59:26.977Z" }, ] [[package]] @@ -39,24 +41,24 @@ dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/d8/0d/cc2fb42b8c50d80143221515dd7e4766995bd07c56c9a3ed30baf080b6dc/black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875", size = 645813 } +sdist = { url = "https://files.pythonhosted.org/packages/d8/0d/cc2fb42b8c50d80143221515dd7e4766995bd07c56c9a3ed30baf080b6dc/black-24.10.0.tar.gz", hash = "sha256:846ea64c97afe3bc677b761787993be4991810ecc7a4a937816dd6bddedc4875", size = 645813, upload-time = "2024-10-07T19:20:50.361Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/f3/465c0eb5cddf7dbbfe1fecd9b875d1dcf51b88923cd2c1d7e9ab95c6336b/black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812", size = 1623211 }, - { url = "https://files.pythonhosted.org/packages/6e/c5/9023b7673904a5188f9be81f5e129fff69f51f5515655fbd1d5a4e80a47b/black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f", size = 1753774 }, - { url = "https://files.pythonhosted.org/packages/e1/32/df7f18bd0e724e0d9748829765455d6643ec847b3f87e77456fc99d0edab/black-24.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e", size = 1414209 }, - { url = "https://files.pythonhosted.org/packages/c2/cc/7496bb63a9b06a954d3d0ac9fe7a73f3bf1cd92d7a58877c27f4ad1e9d41/black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad", size = 1607468 }, - { url = "https://files.pythonhosted.org/packages/c9/9b/2db8045b45844665c720dcfe292fdaf2e49825810c0103e1191515fc101a/black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392", size = 1737061 }, - { url = "https://files.pythonhosted.org/packages/a3/95/17d4a09a5be5f8c65aa4a361444d95edc45def0de887810f508d3f65db7a/black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175", size = 1423293 }, - { url = "https://files.pythonhosted.org/packages/90/04/bf74c71f592bcd761610bbf67e23e6a3cff824780761f536512437f1e655/black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3", size = 1644256 }, - { url = "https://files.pythonhosted.org/packages/4e/3e/443ef8bc1fbda78e61f79157f303893f3fddf19ca3c8989b163eb3469a12/black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f", size = 1761892 }, - { url = "https://files.pythonhosted.org/packages/52/93/eac95ff229049a6901bc84fec6908a5124b8a0b7c26ea766b3b8a5debd22/black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8", size = 1434796 }, - { url = "https://files.pythonhosted.org/packages/d0/a0/a993f58d4ecfba035e61fca4e9f64a2ecae838fc9f33ab798c62173ed75c/black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981", size = 1643986 }, - { url = "https://files.pythonhosted.org/packages/47/6d/a3a239e938960df1a662b93d6230d4f3e9b4a22982d060fc38c42f45a56b/black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2", size = 1760928 }, - { url = "https://files.pythonhosted.org/packages/dd/cf/af018e13b0eddfb434df4d9cd1b2b7892bab119f7a20123e93f6910982e8/black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b", size = 1436875 }, - { url = "https://files.pythonhosted.org/packages/fe/02/f408c804e0ee78c367dcea0a01aedde4f1712af93b8b6e60df981e0228c7/black-24.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd", size = 1622516 }, - { url = "https://files.pythonhosted.org/packages/0a/1c/314d7f17434a5375682ad097f6f4cc0e3f414f3c95a9b1bb4df14a0f11f9/black-24.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800", size = 1752801 }, - { url = "https://files.pythonhosted.org/packages/39/a7/20e5cd9237d28ad0b31438de5d9f01c8b99814576f4c0cda1edd62caf4b0/black-24.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7", size = 1413626 }, - { url = "https://files.pythonhosted.org/packages/8d/a7/4b27c50537ebca8bec139b872861f9d2bf501c5ec51fcf897cb924d9e264/black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d", size = 206898 }, + { url = "https://files.pythonhosted.org/packages/a3/f3/465c0eb5cddf7dbbfe1fecd9b875d1dcf51b88923cd2c1d7e9ab95c6336b/black-24.10.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e6668650ea4b685440857138e5fe40cde4d652633b1bdffc62933d0db4ed9812", size = 1623211, upload-time = "2024-10-07T19:26:12.43Z" }, + { url = "https://files.pythonhosted.org/packages/6e/c5/9023b7673904a5188f9be81f5e129fff69f51f5515655fbd1d5a4e80a47b/black-24.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:649fff99a20bd06c6f727d2a27f401331dc0cc861fb69cde910fe95b01b5928f", size = 1753774, upload-time = "2024-10-07T19:23:58.47Z" }, + { url = "https://files.pythonhosted.org/packages/e1/32/df7f18bd0e724e0d9748829765455d6643ec847b3f87e77456fc99d0edab/black-24.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:fe4d6476887de70546212c99ac9bd803d90b42fc4767f058a0baa895013fbb3e", size = 1414209, upload-time = "2024-10-07T19:24:42.54Z" }, + { url = "https://files.pythonhosted.org/packages/c2/cc/7496bb63a9b06a954d3d0ac9fe7a73f3bf1cd92d7a58877c27f4ad1e9d41/black-24.10.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5a2221696a8224e335c28816a9d331a6c2ae15a2ee34ec857dcf3e45dbfa99ad", size = 1607468, upload-time = "2024-10-07T19:26:14.966Z" }, + { url = "https://files.pythonhosted.org/packages/c9/9b/2db8045b45844665c720dcfe292fdaf2e49825810c0103e1191515fc101a/black-24.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4007b1393d902b48b36958a216c20c4482f601569d19ed1df294a496eb366392", size = 1737061, upload-time = "2024-10-07T19:23:52.18Z" }, + { url = "https://files.pythonhosted.org/packages/a3/95/17d4a09a5be5f8c65aa4a361444d95edc45def0de887810f508d3f65db7a/black-24.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:394d4ddc64782e51153eadcaaca95144ac4c35e27ef9b0a42e121ae7e57a9175", size = 1423293, upload-time = "2024-10-07T19:24:41.7Z" }, + { url = "https://files.pythonhosted.org/packages/90/04/bf74c71f592bcd761610bbf67e23e6a3cff824780761f536512437f1e655/black-24.10.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b5e39e0fae001df40f95bd8cc36b9165c5e2ea88900167bddf258bacef9bbdc3", size = 1644256, upload-time = "2024-10-07T19:27:53.355Z" }, + { url = "https://files.pythonhosted.org/packages/4e/3e/443ef8bc1fbda78e61f79157f303893f3fddf19ca3c8989b163eb3469a12/black-24.10.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:14b3502784f09ce2443830e3133dacf2c0110d45191ed470ecb04d0f5f6fcb0f", size = 1761892, upload-time = "2024-10-07T19:24:10.264Z" }, + { url = "https://files.pythonhosted.org/packages/52/93/eac95ff229049a6901bc84fec6908a5124b8a0b7c26ea766b3b8a5debd22/black-24.10.0-cp312-cp312-win_amd64.whl", hash = "sha256:30d2c30dc5139211dda799758559d1b049f7f14c580c409d6ad925b74a4208a8", size = 1434796, upload-time = "2024-10-07T19:25:06.239Z" }, + { url = "https://files.pythonhosted.org/packages/d0/a0/a993f58d4ecfba035e61fca4e9f64a2ecae838fc9f33ab798c62173ed75c/black-24.10.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1cbacacb19e922a1d75ef2b6ccaefcd6e93a2c05ede32f06a21386a04cedb981", size = 1643986, upload-time = "2024-10-07T19:28:50.684Z" }, + { url = "https://files.pythonhosted.org/packages/47/6d/a3a239e938960df1a662b93d6230d4f3e9b4a22982d060fc38c42f45a56b/black-24.10.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ddacb691cdcdf77b96f549cf9591701d8db36b2f19519373d60d31746068dbf2", size = 1760928, upload-time = "2024-10-07T19:24:15.233Z" }, + { url = "https://files.pythonhosted.org/packages/dd/cf/af018e13b0eddfb434df4d9cd1b2b7892bab119f7a20123e93f6910982e8/black-24.10.0-cp313-cp313-win_amd64.whl", hash = "sha256:680359d932801c76d2e9c9068d05c6b107f2584b2a5b88831c83962eb9984c1b", size = 1436875, upload-time = "2024-10-07T19:24:42.762Z" }, + { url = "https://files.pythonhosted.org/packages/fe/02/f408c804e0ee78c367dcea0a01aedde4f1712af93b8b6e60df981e0228c7/black-24.10.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:17374989640fbca88b6a448129cd1745c5eb8d9547b464f281b251dd00155ccd", size = 1622516, upload-time = "2024-10-07T19:29:40.629Z" }, + { url = "https://files.pythonhosted.org/packages/0a/1c/314d7f17434a5375682ad097f6f4cc0e3f414f3c95a9b1bb4df14a0f11f9/black-24.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ccfa1d0cb6200857f1923b602f978386a3a2758a65b52e0950299ea014be6800", size = 1752801, upload-time = "2024-10-07T19:23:56.594Z" }, + { url = "https://files.pythonhosted.org/packages/39/a7/20e5cd9237d28ad0b31438de5d9f01c8b99814576f4c0cda1edd62caf4b0/black-24.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:2cd9c95431d94adc56600710f8813ee27eea544dd118d45896bb734e9d7a0dc7", size = 1413626, upload-time = "2024-10-07T19:24:46.133Z" }, + { url = "https://files.pythonhosted.org/packages/8d/a7/4b27c50537ebca8bec139b872861f9d2bf501c5ec51fcf897cb924d9e264/black-24.10.0-py3-none-any.whl", hash = "sha256:3bb2b7a1f7b685f85b11fed1ef10f8a9148bceb49853e47a294a3dd963c1dd7d", size = 206898, upload-time = "2024-10-07T19:20:48.317Z" }, ] [[package]] @@ -66,66 +68,66 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pycparser", marker = "python_full_version == '3.13.*' and implementation_name == 'cpython'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/90/07/f44ca684db4e4f08a3fdc6eeb9a0d15dc6883efc7b8c90357fdbf74e186c/cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", size = 182191 }, - { url = "https://files.pythonhosted.org/packages/08/fd/cc2fedbd887223f9f5d170c96e57cbf655df9831a6546c1727ae13fa977a/cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", size = 178592 }, - { url = "https://files.pythonhosted.org/packages/de/cc/4635c320081c78d6ffc2cab0a76025b691a91204f4aa317d568ff9280a2d/cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", size = 426024 }, - { url = "https://files.pythonhosted.org/packages/b6/7b/3b2b250f3aab91abe5f8a51ada1b717935fdaec53f790ad4100fe2ec64d1/cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", size = 448188 }, - { url = "https://files.pythonhosted.org/packages/d3/48/1b9283ebbf0ec065148d8de05d647a986c5f22586b18120020452fff8f5d/cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", size = 455571 }, - { url = "https://files.pythonhosted.org/packages/40/87/3b8452525437b40f39ca7ff70276679772ee7e8b394934ff60e63b7b090c/cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", size = 436687 }, - { url = "https://files.pythonhosted.org/packages/8d/fb/4da72871d177d63649ac449aec2e8a29efe0274035880c7af59101ca2232/cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", size = 446211 }, - { url = "https://files.pythonhosted.org/packages/ab/a0/62f00bcb411332106c02b663b26f3545a9ef136f80d5df746c05878f8c4b/cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", size = 461325 }, - { url = "https://files.pythonhosted.org/packages/36/83/76127035ed2e7e27b0787604d99da630ac3123bfb02d8e80c633f218a11d/cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", size = 438784 }, - { url = "https://files.pythonhosted.org/packages/21/81/a6cd025db2f08ac88b901b745c163d884641909641f9b826e8cb87645942/cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", size = 461564 }, - { url = "https://files.pythonhosted.org/packages/f8/fe/4d41c2f200c4a457933dbd98d3cf4e911870877bd94d9656cc0fcb390681/cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", size = 171804 }, - { url = "https://files.pythonhosted.org/packages/d1/b6/0b0f5ab93b0df4acc49cae758c81fe4e5ef26c3ae2e10cc69249dfd8b3ab/cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", size = 181299 }, - { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264 }, - { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651 }, - { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259 }, - { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200 }, - { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235 }, - { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721 }, - { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242 }, - { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999 }, - { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242 }, - { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604 }, - { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727 }, - { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400 }, - { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 }, - { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 }, - { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 }, - { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850 }, - { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729 }, - { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256 }, - { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424 }, - { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568 }, - { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736 }, - { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 }, - { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 }, - { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989 }, - { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802 }, - { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792 }, - { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893 }, - { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810 }, - { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200 }, - { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447 }, - { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358 }, - { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469 }, - { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 }, - { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 }, - { url = "https://files.pythonhosted.org/packages/b9/ea/8bb50596b8ffbc49ddd7a1ad305035daa770202a6b782fc164647c2673ad/cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16", size = 182220 }, - { url = "https://files.pythonhosted.org/packages/ae/11/e77c8cd24f58285a82c23af484cf5b124a376b32644e445960d1a4654c3a/cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36", size = 178605 }, - { url = "https://files.pythonhosted.org/packages/ed/65/25a8dc32c53bf5b7b6c2686b42ae2ad58743f7ff644844af7cdb29b49361/cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8", size = 424910 }, - { url = "https://files.pythonhosted.org/packages/42/7a/9d086fab7c66bd7c4d0f27c57a1b6b068ced810afc498cc8c49e0088661c/cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576", size = 447200 }, - { url = "https://files.pythonhosted.org/packages/da/63/1785ced118ce92a993b0ec9e0d0ac8dc3e5dbfbcaa81135be56c69cabbb6/cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87", size = 454565 }, - { url = "https://files.pythonhosted.org/packages/74/06/90b8a44abf3556599cdec107f7290277ae8901a58f75e6fe8f970cd72418/cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0", size = 435635 }, - { url = "https://files.pythonhosted.org/packages/bd/62/a1f468e5708a70b1d86ead5bab5520861d9c7eacce4a885ded9faa7729c3/cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3", size = 445218 }, - { url = "https://files.pythonhosted.org/packages/5b/95/b34462f3ccb09c2594aa782d90a90b045de4ff1f70148ee79c69d37a0a5a/cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595", size = 460486 }, - { url = "https://files.pythonhosted.org/packages/fc/fc/a1e4bebd8d680febd29cf6c8a40067182b64f00c7d105f8f26b5bc54317b/cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a", size = 437911 }, - { url = "https://files.pythonhosted.org/packages/e6/c3/21cab7a6154b6a5ea330ae80de386e7665254835b9e98ecc1340b3a7de9a/cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e", size = 460632 }, - { url = "https://files.pythonhosted.org/packages/cb/b5/fd9f8b5a84010ca169ee49f4e4ad6f8c05f4e3545b72ee041dbbcb159882/cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7", size = 171820 }, - { url = "https://files.pythonhosted.org/packages/8c/52/b08750ce0bce45c143e1b5d7357ee8c55341b52bdef4b0f081af1eb248c2/cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662", size = 181290 }, +sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621, upload-time = "2024-09-04T20:45:21.852Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/90/07/f44ca684db4e4f08a3fdc6eeb9a0d15dc6883efc7b8c90357fdbf74e186c/cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", size = 182191, upload-time = "2024-09-04T20:43:30.027Z" }, + { url = "https://files.pythonhosted.org/packages/08/fd/cc2fedbd887223f9f5d170c96e57cbf655df9831a6546c1727ae13fa977a/cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", size = 178592, upload-time = "2024-09-04T20:43:32.108Z" }, + { url = "https://files.pythonhosted.org/packages/de/cc/4635c320081c78d6ffc2cab0a76025b691a91204f4aa317d568ff9280a2d/cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", size = 426024, upload-time = "2024-09-04T20:43:34.186Z" }, + { url = "https://files.pythonhosted.org/packages/b6/7b/3b2b250f3aab91abe5f8a51ada1b717935fdaec53f790ad4100fe2ec64d1/cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", size = 448188, upload-time = "2024-09-04T20:43:36.286Z" }, + { url = "https://files.pythonhosted.org/packages/d3/48/1b9283ebbf0ec065148d8de05d647a986c5f22586b18120020452fff8f5d/cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", size = 455571, upload-time = "2024-09-04T20:43:38.586Z" }, + { url = "https://files.pythonhosted.org/packages/40/87/3b8452525437b40f39ca7ff70276679772ee7e8b394934ff60e63b7b090c/cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", size = 436687, upload-time = "2024-09-04T20:43:40.084Z" }, + { url = "https://files.pythonhosted.org/packages/8d/fb/4da72871d177d63649ac449aec2e8a29efe0274035880c7af59101ca2232/cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", size = 446211, upload-time = "2024-09-04T20:43:41.526Z" }, + { url = "https://files.pythonhosted.org/packages/ab/a0/62f00bcb411332106c02b663b26f3545a9ef136f80d5df746c05878f8c4b/cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", size = 461325, upload-time = "2024-09-04T20:43:43.117Z" }, + { url = "https://files.pythonhosted.org/packages/36/83/76127035ed2e7e27b0787604d99da630ac3123bfb02d8e80c633f218a11d/cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", size = 438784, upload-time = "2024-09-04T20:43:45.256Z" }, + { url = "https://files.pythonhosted.org/packages/21/81/a6cd025db2f08ac88b901b745c163d884641909641f9b826e8cb87645942/cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", size = 461564, upload-time = "2024-09-04T20:43:46.779Z" }, + { url = "https://files.pythonhosted.org/packages/f8/fe/4d41c2f200c4a457933dbd98d3cf4e911870877bd94d9656cc0fcb390681/cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", size = 171804, upload-time = "2024-09-04T20:43:48.186Z" }, + { url = "https://files.pythonhosted.org/packages/d1/b6/0b0f5ab93b0df4acc49cae758c81fe4e5ef26c3ae2e10cc69249dfd8b3ab/cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", size = 181299, upload-time = "2024-09-04T20:43:49.812Z" }, + { url = "https://files.pythonhosted.org/packages/6b/f4/927e3a8899e52a27fa57a48607ff7dc91a9ebe97399b357b85a0c7892e00/cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", size = 182264, upload-time = "2024-09-04T20:43:51.124Z" }, + { url = "https://files.pythonhosted.org/packages/6c/f5/6c3a8efe5f503175aaddcbea6ad0d2c96dad6f5abb205750d1b3df44ef29/cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", size = 178651, upload-time = "2024-09-04T20:43:52.872Z" }, + { url = "https://files.pythonhosted.org/packages/94/dd/a3f0118e688d1b1a57553da23b16bdade96d2f9bcda4d32e7d2838047ff7/cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", size = 445259, upload-time = "2024-09-04T20:43:56.123Z" }, + { url = "https://files.pythonhosted.org/packages/2e/ea/70ce63780f096e16ce8588efe039d3c4f91deb1dc01e9c73a287939c79a6/cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", size = 469200, upload-time = "2024-09-04T20:43:57.891Z" }, + { url = "https://files.pythonhosted.org/packages/1c/a0/a4fa9f4f781bda074c3ddd57a572b060fa0df7655d2a4247bbe277200146/cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", size = 477235, upload-time = "2024-09-04T20:44:00.18Z" }, + { url = "https://files.pythonhosted.org/packages/62/12/ce8710b5b8affbcdd5c6e367217c242524ad17a02fe5beec3ee339f69f85/cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", size = 459721, upload-time = "2024-09-04T20:44:01.585Z" }, + { url = "https://files.pythonhosted.org/packages/ff/6b/d45873c5e0242196f042d555526f92aa9e0c32355a1be1ff8c27f077fd37/cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", size = 467242, upload-time = "2024-09-04T20:44:03.467Z" }, + { url = "https://files.pythonhosted.org/packages/1a/52/d9a0e523a572fbccf2955f5abe883cfa8bcc570d7faeee06336fbd50c9fc/cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", size = 477999, upload-time = "2024-09-04T20:44:05.023Z" }, + { url = "https://files.pythonhosted.org/packages/44/74/f2a2460684a1a2d00ca799ad880d54652841a780c4c97b87754f660c7603/cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", size = 454242, upload-time = "2024-09-04T20:44:06.444Z" }, + { url = "https://files.pythonhosted.org/packages/f8/4a/34599cac7dfcd888ff54e801afe06a19c17787dfd94495ab0c8d35fe99fb/cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b", size = 478604, upload-time = "2024-09-04T20:44:08.206Z" }, + { url = "https://files.pythonhosted.org/packages/34/33/e1b8a1ba29025adbdcda5fb3a36f94c03d771c1b7b12f726ff7fef2ebe36/cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", size = 171727, upload-time = "2024-09-04T20:44:09.481Z" }, + { url = "https://files.pythonhosted.org/packages/3d/97/50228be003bb2802627d28ec0627837ac0bf35c90cf769812056f235b2d1/cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", size = 181400, upload-time = "2024-09-04T20:44:10.873Z" }, + { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178, upload-time = "2024-09-04T20:44:12.232Z" }, + { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840, upload-time = "2024-09-04T20:44:13.739Z" }, + { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803, upload-time = "2024-09-04T20:44:15.231Z" }, + { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850, upload-time = "2024-09-04T20:44:17.188Z" }, + { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729, upload-time = "2024-09-04T20:44:18.688Z" }, + { url = "https://files.pythonhosted.org/packages/91/2b/9a1ddfa5c7f13cab007a2c9cc295b70fbbda7cb10a286aa6810338e60ea1/cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", size = 471256, upload-time = "2024-09-04T20:44:20.248Z" }, + { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424, upload-time = "2024-09-04T20:44:21.673Z" }, + { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568, upload-time = "2024-09-04T20:44:23.245Z" }, + { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736, upload-time = "2024-09-04T20:44:24.757Z" }, + { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448, upload-time = "2024-09-04T20:44:26.208Z" }, + { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976, upload-time = "2024-09-04T20:44:27.578Z" }, + { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989, upload-time = "2024-09-04T20:44:28.956Z" }, + { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802, upload-time = "2024-09-04T20:44:30.289Z" }, + { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792, upload-time = "2024-09-04T20:44:32.01Z" }, + { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893, upload-time = "2024-09-04T20:44:33.606Z" }, + { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810, upload-time = "2024-09-04T20:44:35.191Z" }, + { url = "https://files.pythonhosted.org/packages/c7/8a/1d0e4a9c26e54746dc08c2c6c037889124d4f59dffd853a659fa545f1b40/cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", size = 471200, upload-time = "2024-09-04T20:44:36.743Z" }, + { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447, upload-time = "2024-09-04T20:44:38.492Z" }, + { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358, upload-time = "2024-09-04T20:44:40.046Z" }, + { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469, upload-time = "2024-09-04T20:44:41.616Z" }, + { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475, upload-time = "2024-09-04T20:44:43.733Z" }, + { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009, upload-time = "2024-09-04T20:44:45.309Z" }, + { url = "https://files.pythonhosted.org/packages/b9/ea/8bb50596b8ffbc49ddd7a1ad305035daa770202a6b782fc164647c2673ad/cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16", size = 182220, upload-time = "2024-09-04T20:45:01.577Z" }, + { url = "https://files.pythonhosted.org/packages/ae/11/e77c8cd24f58285a82c23af484cf5b124a376b32644e445960d1a4654c3a/cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36", size = 178605, upload-time = "2024-09-04T20:45:03.837Z" }, + { url = "https://files.pythonhosted.org/packages/ed/65/25a8dc32c53bf5b7b6c2686b42ae2ad58743f7ff644844af7cdb29b49361/cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8", size = 424910, upload-time = "2024-09-04T20:45:05.315Z" }, + { url = "https://files.pythonhosted.org/packages/42/7a/9d086fab7c66bd7c4d0f27c57a1b6b068ced810afc498cc8c49e0088661c/cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576", size = 447200, upload-time = "2024-09-04T20:45:06.903Z" }, + { url = "https://files.pythonhosted.org/packages/da/63/1785ced118ce92a993b0ec9e0d0ac8dc3e5dbfbcaa81135be56c69cabbb6/cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87", size = 454565, upload-time = "2024-09-04T20:45:08.975Z" }, + { url = "https://files.pythonhosted.org/packages/74/06/90b8a44abf3556599cdec107f7290277ae8901a58f75e6fe8f970cd72418/cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0", size = 435635, upload-time = "2024-09-04T20:45:10.64Z" }, + { url = "https://files.pythonhosted.org/packages/bd/62/a1f468e5708a70b1d86ead5bab5520861d9c7eacce4a885ded9faa7729c3/cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3", size = 445218, upload-time = "2024-09-04T20:45:12.366Z" }, + { url = "https://files.pythonhosted.org/packages/5b/95/b34462f3ccb09c2594aa782d90a90b045de4ff1f70148ee79c69d37a0a5a/cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595", size = 460486, upload-time = "2024-09-04T20:45:13.935Z" }, + { url = "https://files.pythonhosted.org/packages/fc/fc/a1e4bebd8d680febd29cf6c8a40067182b64f00c7d105f8f26b5bc54317b/cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a", size = 437911, upload-time = "2024-09-04T20:45:15.696Z" }, + { url = "https://files.pythonhosted.org/packages/e6/c3/21cab7a6154b6a5ea330ae80de386e7665254835b9e98ecc1340b3a7de9a/cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e", size = 460632, upload-time = "2024-09-04T20:45:17.284Z" }, + { url = "https://files.pythonhosted.org/packages/cb/b5/fd9f8b5a84010ca169ee49f4e4ad6f8c05f4e3545b72ee041dbbcb159882/cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7", size = 171820, upload-time = "2024-09-04T20:45:18.762Z" }, + { url = "https://files.pythonhosted.org/packages/8c/52/b08750ce0bce45c143e1b5d7357ee8c55341b52bdef4b0f081af1eb248c2/cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662", size = 181290, upload-time = "2024-09-04T20:45:20.226Z" }, ] [[package]] @@ -135,114 +137,114 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "sys_platform == 'win32'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } +sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593, upload-time = "2024-12-21T18:38:44.339Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 }, + { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188, upload-time = "2024-12-21T18:38:41.666Z" }, ] [[package]] name = "colorama" version = "0.4.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] [[package]] name = "coverage" version = "7.6.10" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/84/ba/ac14d281f80aab516275012e8875991bb06203957aa1e19950139238d658/coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23", size = 803868 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c5/12/2a2a923edf4ddabdffed7ad6da50d96a5c126dae7b80a33df7310e329a1e/coverage-7.6.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5c912978f7fbf47ef99cec50c4401340436d200d41d714c7a4766f377c5b7b78", size = 207982 }, - { url = "https://files.pythonhosted.org/packages/ca/49/6985dbca9c7be3f3cb62a2e6e492a0c88b65bf40579e16c71ae9c33c6b23/coverage-7.6.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a01ec4af7dfeb96ff0078ad9a48810bb0cc8abcb0115180c6013a6b26237626c", size = 208414 }, - { url = "https://files.pythonhosted.org/packages/35/93/287e8f1d1ed2646f4e0b2605d14616c9a8a2697d0d1b453815eb5c6cebdb/coverage-7.6.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3b204c11e2b2d883946fe1d97f89403aa1811df28ce0447439178cc7463448a", size = 236860 }, - { url = "https://files.pythonhosted.org/packages/de/e1/cfdb5627a03567a10031acc629b75d45a4ca1616e54f7133ca1fa366050a/coverage-7.6.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32ee6d8491fcfc82652a37109f69dee9a830e9379166cb73c16d8dc5c2915165", size = 234758 }, - { url = "https://files.pythonhosted.org/packages/6d/85/fc0de2bcda3f97c2ee9fe8568f7d48f7279e91068958e5b2cc19e0e5f600/coverage-7.6.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675cefc4c06e3b4c876b85bfb7c59c5e2218167bbd4da5075cbe3b5790a28988", size = 235920 }, - { url = "https://files.pythonhosted.org/packages/79/73/ef4ea0105531506a6f4cf4ba571a214b14a884630b567ed65b3d9c1975e1/coverage-7.6.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f4f620668dbc6f5e909a0946a877310fb3d57aea8198bde792aae369ee1c23b5", size = 234986 }, - { url = "https://files.pythonhosted.org/packages/c6/4d/75afcfe4432e2ad0405c6f27adeb109ff8976c5e636af8604f94f29fa3fc/coverage-7.6.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4eea95ef275de7abaef630c9b2c002ffbc01918b726a39f5a4353916ec72d2f3", size = 233446 }, - { url = "https://files.pythonhosted.org/packages/86/5b/efee56a89c16171288cafff022e8af44f8f94075c2d8da563c3935212871/coverage-7.6.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e2f0280519e42b0a17550072861e0bc8a80a0870de260f9796157d3fca2733c5", size = 234566 }, - { url = "https://files.pythonhosted.org/packages/f2/db/67770cceb4a64d3198bf2aa49946f411b85ec6b0a9b489e61c8467a4253b/coverage-7.6.10-cp310-cp310-win32.whl", hash = "sha256:bc67deb76bc3717f22e765ab3e07ee9c7a5e26b9019ca19a3b063d9f4b874244", size = 210675 }, - { url = "https://files.pythonhosted.org/packages/8d/27/e8bfc43f5345ec2c27bc8a1fa77cdc5ce9dcf954445e11f14bb70b889d14/coverage-7.6.10-cp310-cp310-win_amd64.whl", hash = "sha256:0f460286cb94036455e703c66988851d970fdfd8acc2a1122ab7f4f904e4029e", size = 211518 }, - { url = "https://files.pythonhosted.org/packages/85/d2/5e175fcf6766cf7501a8541d81778fd2f52f4870100e791f5327fd23270b/coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3", size = 208088 }, - { url = "https://files.pythonhosted.org/packages/4b/6f/06db4dc8fca33c13b673986e20e466fd936235a6ec1f0045c3853ac1b593/coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43", size = 208536 }, - { url = "https://files.pythonhosted.org/packages/0d/62/c6a0cf80318c1c1af376d52df444da3608eafc913b82c84a4600d8349472/coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132", size = 240474 }, - { url = "https://files.pythonhosted.org/packages/a3/59/750adafc2e57786d2e8739a46b680d4fb0fbc2d57fbcb161290a9f1ecf23/coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f", size = 237880 }, - { url = "https://files.pythonhosted.org/packages/2c/f8/ef009b3b98e9f7033c19deb40d629354aab1d8b2d7f9cfec284dbedf5096/coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994", size = 239750 }, - { url = "https://files.pythonhosted.org/packages/a6/e2/6622f3b70f5f5b59f705e680dae6db64421af05a5d1e389afd24dae62e5b/coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99", size = 238642 }, - { url = "https://files.pythonhosted.org/packages/2d/10/57ac3f191a3c95c67844099514ff44e6e19b2915cd1c22269fb27f9b17b6/coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd", size = 237266 }, - { url = "https://files.pythonhosted.org/packages/ee/2d/7016f4ad9d553cabcb7333ed78ff9d27248ec4eba8dd21fa488254dff894/coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377", size = 238045 }, - { url = "https://files.pythonhosted.org/packages/a7/fe/45af5c82389a71e0cae4546413266d2195c3744849669b0bab4b5f2c75da/coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8", size = 210647 }, - { url = "https://files.pythonhosted.org/packages/db/11/3f8e803a43b79bc534c6a506674da9d614e990e37118b4506faf70d46ed6/coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609", size = 211508 }, - { url = "https://files.pythonhosted.org/packages/86/77/19d09ea06f92fdf0487499283b1b7af06bc422ea94534c8fe3a4cd023641/coverage-7.6.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27c6e64726b307782fa5cbe531e7647aee385a29b2107cd87ba7c0105a5d3853", size = 208281 }, - { url = "https://files.pythonhosted.org/packages/b6/67/5479b9f2f99fcfb49c0d5cf61912a5255ef80b6e80a3cddba39c38146cf4/coverage-7.6.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c56e097019e72c373bae32d946ecf9858fda841e48d82df7e81c63ac25554078", size = 208514 }, - { url = "https://files.pythonhosted.org/packages/15/d1/febf59030ce1c83b7331c3546d7317e5120c5966471727aa7ac157729c4b/coverage-7.6.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7827a5bc7bdb197b9e066cdf650b2887597ad124dd99777332776f7b7c7d0d0", size = 241537 }, - { url = "https://files.pythonhosted.org/packages/4b/7e/5ac4c90192130e7cf8b63153fe620c8bfd9068f89a6d9b5f26f1550f7a26/coverage-7.6.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204a8238afe787323a8b47d8be4df89772d5c1e4651b9ffa808552bdf20e1d50", size = 238572 }, - { url = "https://files.pythonhosted.org/packages/dc/03/0334a79b26ecf59958f2fe9dd1f5ab3e2f88db876f5071933de39af09647/coverage-7.6.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67926f51821b8e9deb6426ff3164870976fe414d033ad90ea75e7ed0c2e5022", size = 240639 }, - { url = "https://files.pythonhosted.org/packages/d7/45/8a707f23c202208d7b286d78ad6233f50dcf929319b664b6cc18a03c1aae/coverage-7.6.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e78b270eadb5702938c3dbe9367f878249b5ef9a2fcc5360ac7bff694310d17b", size = 240072 }, - { url = "https://files.pythonhosted.org/packages/66/02/603ce0ac2d02bc7b393279ef618940b4a0535b0868ee791140bda9ecfa40/coverage-7.6.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:714f942b9c15c3a7a5fe6876ce30af831c2ad4ce902410b7466b662358c852c0", size = 238386 }, - { url = "https://files.pythonhosted.org/packages/04/62/4e6887e9be060f5d18f1dd58c2838b2d9646faf353232dec4e2d4b1c8644/coverage-7.6.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:abb02e2f5a3187b2ac4cd46b8ced85a0858230b577ccb2c62c81482ca7d18852", size = 240054 }, - { url = "https://files.pythonhosted.org/packages/5c/74/83ae4151c170d8bd071924f212add22a0e62a7fe2b149edf016aeecad17c/coverage-7.6.10-cp312-cp312-win32.whl", hash = "sha256:55b201b97286cf61f5e76063f9e2a1d8d2972fc2fcfd2c1272530172fd28c359", size = 210904 }, - { url = "https://files.pythonhosted.org/packages/c3/54/de0893186a221478f5880283119fc40483bc460b27c4c71d1b8bba3474b9/coverage-7.6.10-cp312-cp312-win_amd64.whl", hash = "sha256:e4ae5ac5e0d1e4edfc9b4b57b4cbecd5bc266a6915c500f358817a8496739247", size = 211692 }, - { url = "https://files.pythonhosted.org/packages/25/6d/31883d78865529257bf847df5789e2ae80e99de8a460c3453dbfbe0db069/coverage-7.6.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05fca8ba6a87aabdd2d30d0b6c838b50510b56cdcfc604d40760dae7153b73d9", size = 208308 }, - { url = "https://files.pythonhosted.org/packages/70/22/3f2b129cc08de00c83b0ad6252e034320946abfc3e4235c009e57cfeee05/coverage-7.6.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9e80eba8801c386f72e0712a0453431259c45c3249f0009aff537a517b52942b", size = 208565 }, - { url = "https://files.pythonhosted.org/packages/97/0a/d89bc2d1cc61d3a8dfe9e9d75217b2be85f6c73ebf1b9e3c2f4e797f4531/coverage-7.6.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a372c89c939d57abe09e08c0578c1d212e7a678135d53aa16eec4430adc5e690", size = 241083 }, - { url = "https://files.pythonhosted.org/packages/4c/81/6d64b88a00c7a7aaed3a657b8eaa0931f37a6395fcef61e53ff742b49c97/coverage-7.6.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec22b5e7fe7a0fa8509181c4aac1db48f3dd4d3a566131b313d1efc102892c18", size = 238235 }, - { url = "https://files.pythonhosted.org/packages/9a/0b/7797d4193f5adb4b837207ed87fecf5fc38f7cc612b369a8e8e12d9fa114/coverage-7.6.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26bcf5c4df41cad1b19c84af71c22cbc9ea9a547fc973f1f2cc9a290002c8b3c", size = 240220 }, - { url = "https://files.pythonhosted.org/packages/65/4d/6f83ca1bddcf8e51bf8ff71572f39a1c73c34cf50e752a952c34f24d0a60/coverage-7.6.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e4630c26b6084c9b3cb53b15bd488f30ceb50b73c35c5ad7871b869cb7365fd", size = 239847 }, - { url = "https://files.pythonhosted.org/packages/30/9d/2470df6aa146aff4c65fee0f87f58d2164a67533c771c9cc12ffcdb865d5/coverage-7.6.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2396e8116db77789f819d2bc8a7e200232b7a282c66e0ae2d2cd84581a89757e", size = 237922 }, - { url = "https://files.pythonhosted.org/packages/08/dd/723fef5d901e6a89f2507094db66c091449c8ba03272861eaefa773ad95c/coverage-7.6.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79109c70cc0882e4d2d002fe69a24aa504dec0cc17169b3c7f41a1d341a73694", size = 239783 }, - { url = "https://files.pythonhosted.org/packages/3d/f7/64d3298b2baf261cb35466000628706ce20a82d42faf9b771af447cd2b76/coverage-7.6.10-cp313-cp313-win32.whl", hash = "sha256:9e1747bab246d6ff2c4f28b4d186b205adced9f7bd9dc362051cc37c4a0c7bd6", size = 210965 }, - { url = "https://files.pythonhosted.org/packages/d5/58/ec43499a7fc681212fe7742fe90b2bc361cdb72e3181ace1604247a5b24d/coverage-7.6.10-cp313-cp313-win_amd64.whl", hash = "sha256:254f1a3b1eef5f7ed23ef265eaa89c65c8c5b6b257327c149db1ca9d4a35f25e", size = 211719 }, - { url = "https://files.pythonhosted.org/packages/ab/c9/f2857a135bcff4330c1e90e7d03446b036b2363d4ad37eb5e3a47bbac8a6/coverage-7.6.10-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ccf240eb719789cedbb9fd1338055de2761088202a9a0b73032857e53f612fe", size = 209050 }, - { url = "https://files.pythonhosted.org/packages/aa/b3/f840e5bd777d8433caa9e4a1eb20503495709f697341ac1a8ee6a3c906ad/coverage-7.6.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0c807ca74d5a5e64427c8805de15b9ca140bba13572d6d74e262f46f50b13273", size = 209321 }, - { url = "https://files.pythonhosted.org/packages/85/7d/125a5362180fcc1c03d91850fc020f3831d5cda09319522bcfa6b2b70be7/coverage-7.6.10-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bcfa46d7709b5a7ffe089075799b902020b62e7ee56ebaed2f4bdac04c508d8", size = 252039 }, - { url = "https://files.pythonhosted.org/packages/a9/9c/4358bf3c74baf1f9bddd2baf3756b54c07f2cfd2535f0a47f1e7757e54b3/coverage-7.6.10-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e0de1e902669dccbf80b0415fb6b43d27edca2fbd48c74da378923b05316098", size = 247758 }, - { url = "https://files.pythonhosted.org/packages/cf/c7/de3eb6fc5263b26fab5cda3de7a0f80e317597a4bad4781859f72885f300/coverage-7.6.10-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b444c42bbc533aaae6b5a2166fd1a797cdb5eb58ee51a92bee1eb94a1e1cb", size = 250119 }, - { url = "https://files.pythonhosted.org/packages/3e/e6/43de91f8ba2ec9140c6a4af1102141712949903dc732cf739167cfa7a3bc/coverage-7.6.10-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b330368cb99ef72fcd2dc3ed260adf67b31499584dc8a20225e85bfe6f6cfed0", size = 249597 }, - { url = "https://files.pythonhosted.org/packages/08/40/61158b5499aa2adf9e37bc6d0117e8f6788625b283d51e7e0c53cf340530/coverage-7.6.10-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9a7cfb50515f87f7ed30bc882f68812fd98bc2852957df69f3003d22a2aa0abf", size = 247473 }, - { url = "https://files.pythonhosted.org/packages/50/69/b3f2416725621e9f112e74e8470793d5b5995f146f596f133678a633b77e/coverage-7.6.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f93531882a5f68c28090f901b1d135de61b56331bba82028489bc51bdd818d2", size = 248737 }, - { url = "https://files.pythonhosted.org/packages/3c/6e/fe899fb937657db6df31cc3e61c6968cb56d36d7326361847440a430152e/coverage-7.6.10-cp313-cp313t-win32.whl", hash = "sha256:89d76815a26197c858f53c7f6a656686ec392b25991f9e409bcef020cd532312", size = 211611 }, - { url = "https://files.pythonhosted.org/packages/1c/55/52f5e66142a9d7bc93a15192eba7a78513d2abf6b3558d77b4ca32f5f424/coverage-7.6.10-cp313-cp313t-win_amd64.whl", hash = "sha256:54a5f0f43950a36312155dae55c505a76cd7f2b12d26abeebbe7a0b36dbc868d", size = 212781 }, - { url = "https://files.pythonhosted.org/packages/40/41/473617aadf9a1c15bc2d56be65d90d7c29bfa50a957a67ef96462f7ebf8e/coverage-7.6.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:656c82b8a0ead8bba147de9a89bda95064874c91a3ed43a00e687f23cc19d53a", size = 207978 }, - { url = "https://files.pythonhosted.org/packages/10/f6/480586607768b39a30e6910a3c4522139094ac0f1677028e1f4823688957/coverage-7.6.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccc2b70a7ed475c68ceb548bf69cec1e27305c1c2606a5eb7c3afff56a1b3b27", size = 208415 }, - { url = "https://files.pythonhosted.org/packages/f1/af/439bb760f817deff6f4d38fe7da08d9dd7874a560241f1945bc3b4446550/coverage-7.6.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5e37dc41d57ceba70956fa2fc5b63c26dba863c946ace9705f8eca99daecdc4", size = 236452 }, - { url = "https://files.pythonhosted.org/packages/d0/13/481f4ceffcabe29ee2332e60efb52e4694f54a402f3ada2bcec10bb32e43/coverage-7.6.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0aa9692b4fdd83a4647eeb7db46410ea1322b5ed94cd1715ef09d1d5922ba87f", size = 234374 }, - { url = "https://files.pythonhosted.org/packages/c5/59/4607ea9d6b1b73e905c7656da08d0b00cdf6e59f2293ec259e8914160025/coverage-7.6.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa744da1820678b475e4ba3dfd994c321c5b13381d1041fe9c608620e6676e25", size = 235505 }, - { url = "https://files.pythonhosted.org/packages/85/60/d66365723b9b7f29464b11d024248ed3523ce5aab958e4ad8c43f3f4148b/coverage-7.6.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c0b1818063dc9e9d838c09e3a473c1422f517889436dd980f5d721899e66f315", size = 234616 }, - { url = "https://files.pythonhosted.org/packages/74/f8/2cf7a38e7d81b266f47dfcf137fecd8fa66c7bdbd4228d611628d8ca3437/coverage-7.6.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:59af35558ba08b758aec4d56182b222976330ef8d2feacbb93964f576a7e7a90", size = 233099 }, - { url = "https://files.pythonhosted.org/packages/50/2b/bff6c1c6b63c4396ea7ecdbf8db1788b46046c681b8fcc6ec77db9f4ea49/coverage-7.6.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7ed2f37cfce1ce101e6dffdfd1c99e729dd2ffc291d02d3e2d0af8b53d13840d", size = 234089 }, - { url = "https://files.pythonhosted.org/packages/bf/b5/baace1c754d546a67779358341aa8d2f7118baf58cac235db457e1001d1b/coverage-7.6.10-cp39-cp39-win32.whl", hash = "sha256:4bcc276261505d82f0ad426870c3b12cb177752834a633e737ec5ee79bbdff18", size = 210701 }, - { url = "https://files.pythonhosted.org/packages/b1/bf/9e1e95b8b20817398ecc5a1e8d3e05ff404e1b9fb2185cd71561698fe2a2/coverage-7.6.10-cp39-cp39-win_amd64.whl", hash = "sha256:457574f4599d2b00f7f637a0700a6422243b3565509457b2dbd3f50703e11f59", size = 211482 }, - { url = "https://files.pythonhosted.org/packages/a1/70/de81bfec9ed38a64fc44a77c7665e20ca507fc3265597c28b0d989e4082e/coverage-7.6.10-pp39.pp310-none-any.whl", hash = "sha256:fd34e7b3405f0cc7ab03d54a334c17a9e802897580d964bd8c2001f4b9fd488f", size = 200223 }, +sdist = { url = "https://files.pythonhosted.org/packages/84/ba/ac14d281f80aab516275012e8875991bb06203957aa1e19950139238d658/coverage-7.6.10.tar.gz", hash = "sha256:7fb105327c8f8f0682e29843e2ff96af9dcbe5bab8eeb4b398c6a33a16d80a23", size = 803868, upload-time = "2024-12-26T16:59:18.734Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/12/2a2a923edf4ddabdffed7ad6da50d96a5c126dae7b80a33df7310e329a1e/coverage-7.6.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5c912978f7fbf47ef99cec50c4401340436d200d41d714c7a4766f377c5b7b78", size = 207982, upload-time = "2024-12-26T16:57:00.767Z" }, + { url = "https://files.pythonhosted.org/packages/ca/49/6985dbca9c7be3f3cb62a2e6e492a0c88b65bf40579e16c71ae9c33c6b23/coverage-7.6.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a01ec4af7dfeb96ff0078ad9a48810bb0cc8abcb0115180c6013a6b26237626c", size = 208414, upload-time = "2024-12-26T16:57:03.826Z" }, + { url = "https://files.pythonhosted.org/packages/35/93/287e8f1d1ed2646f4e0b2605d14616c9a8a2697d0d1b453815eb5c6cebdb/coverage-7.6.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a3b204c11e2b2d883946fe1d97f89403aa1811df28ce0447439178cc7463448a", size = 236860, upload-time = "2024-12-26T16:57:06.509Z" }, + { url = "https://files.pythonhosted.org/packages/de/e1/cfdb5627a03567a10031acc629b75d45a4ca1616e54f7133ca1fa366050a/coverage-7.6.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:32ee6d8491fcfc82652a37109f69dee9a830e9379166cb73c16d8dc5c2915165", size = 234758, upload-time = "2024-12-26T16:57:09.089Z" }, + { url = "https://files.pythonhosted.org/packages/6d/85/fc0de2bcda3f97c2ee9fe8568f7d48f7279e91068958e5b2cc19e0e5f600/coverage-7.6.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675cefc4c06e3b4c876b85bfb7c59c5e2218167bbd4da5075cbe3b5790a28988", size = 235920, upload-time = "2024-12-26T16:57:10.445Z" }, + { url = "https://files.pythonhosted.org/packages/79/73/ef4ea0105531506a6f4cf4ba571a214b14a884630b567ed65b3d9c1975e1/coverage-7.6.10-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f4f620668dbc6f5e909a0946a877310fb3d57aea8198bde792aae369ee1c23b5", size = 234986, upload-time = "2024-12-26T16:57:13.298Z" }, + { url = "https://files.pythonhosted.org/packages/c6/4d/75afcfe4432e2ad0405c6f27adeb109ff8976c5e636af8604f94f29fa3fc/coverage-7.6.10-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:4eea95ef275de7abaef630c9b2c002ffbc01918b726a39f5a4353916ec72d2f3", size = 233446, upload-time = "2024-12-26T16:57:14.742Z" }, + { url = "https://files.pythonhosted.org/packages/86/5b/efee56a89c16171288cafff022e8af44f8f94075c2d8da563c3935212871/coverage-7.6.10-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e2f0280519e42b0a17550072861e0bc8a80a0870de260f9796157d3fca2733c5", size = 234566, upload-time = "2024-12-26T16:57:17.368Z" }, + { url = "https://files.pythonhosted.org/packages/f2/db/67770cceb4a64d3198bf2aa49946f411b85ec6b0a9b489e61c8467a4253b/coverage-7.6.10-cp310-cp310-win32.whl", hash = "sha256:bc67deb76bc3717f22e765ab3e07ee9c7a5e26b9019ca19a3b063d9f4b874244", size = 210675, upload-time = "2024-12-26T16:57:18.775Z" }, + { url = "https://files.pythonhosted.org/packages/8d/27/e8bfc43f5345ec2c27bc8a1fa77cdc5ce9dcf954445e11f14bb70b889d14/coverage-7.6.10-cp310-cp310-win_amd64.whl", hash = "sha256:0f460286cb94036455e703c66988851d970fdfd8acc2a1122ab7f4f904e4029e", size = 211518, upload-time = "2024-12-26T16:57:21.415Z" }, + { url = "https://files.pythonhosted.org/packages/85/d2/5e175fcf6766cf7501a8541d81778fd2f52f4870100e791f5327fd23270b/coverage-7.6.10-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ea3c8f04b3e4af80e17bab607c386a830ffc2fb88a5484e1df756478cf70d1d3", size = 208088, upload-time = "2024-12-26T16:57:22.833Z" }, + { url = "https://files.pythonhosted.org/packages/4b/6f/06db4dc8fca33c13b673986e20e466fd936235a6ec1f0045c3853ac1b593/coverage-7.6.10-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:507a20fc863cae1d5720797761b42d2d87a04b3e5aeb682ef3b7332e90598f43", size = 208536, upload-time = "2024-12-26T16:57:25.578Z" }, + { url = "https://files.pythonhosted.org/packages/0d/62/c6a0cf80318c1c1af376d52df444da3608eafc913b82c84a4600d8349472/coverage-7.6.10-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d37a84878285b903c0fe21ac8794c6dab58150e9359f1aaebbeddd6412d53132", size = 240474, upload-time = "2024-12-26T16:57:28.659Z" }, + { url = "https://files.pythonhosted.org/packages/a3/59/750adafc2e57786d2e8739a46b680d4fb0fbc2d57fbcb161290a9f1ecf23/coverage-7.6.10-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a534738b47b0de1995f85f582d983d94031dffb48ab86c95bdf88dc62212142f", size = 237880, upload-time = "2024-12-26T16:57:30.095Z" }, + { url = "https://files.pythonhosted.org/packages/2c/f8/ef009b3b98e9f7033c19deb40d629354aab1d8b2d7f9cfec284dbedf5096/coverage-7.6.10-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d7a2bf79378d8fb8afaa994f91bfd8215134f8631d27eba3e0e2c13546ce994", size = 239750, upload-time = "2024-12-26T16:57:31.48Z" }, + { url = "https://files.pythonhosted.org/packages/a6/e2/6622f3b70f5f5b59f705e680dae6db64421af05a5d1e389afd24dae62e5b/coverage-7.6.10-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6713ba4b4ebc330f3def51df1d5d38fad60b66720948112f114968feb52d3f99", size = 238642, upload-time = "2024-12-26T16:57:34.09Z" }, + { url = "https://files.pythonhosted.org/packages/2d/10/57ac3f191a3c95c67844099514ff44e6e19b2915cd1c22269fb27f9b17b6/coverage-7.6.10-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:ab32947f481f7e8c763fa2c92fd9f44eeb143e7610c4ca9ecd6a36adab4081bd", size = 237266, upload-time = "2024-12-26T16:57:35.48Z" }, + { url = "https://files.pythonhosted.org/packages/ee/2d/7016f4ad9d553cabcb7333ed78ff9d27248ec4eba8dd21fa488254dff894/coverage-7.6.10-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7bbd8c8f1b115b892e34ba66a097b915d3871db7ce0e6b9901f462ff3a975377", size = 238045, upload-time = "2024-12-26T16:57:36.952Z" }, + { url = "https://files.pythonhosted.org/packages/a7/fe/45af5c82389a71e0cae4546413266d2195c3744849669b0bab4b5f2c75da/coverage-7.6.10-cp311-cp311-win32.whl", hash = "sha256:299e91b274c5c9cdb64cbdf1b3e4a8fe538a7a86acdd08fae52301b28ba297f8", size = 210647, upload-time = "2024-12-26T16:57:39.84Z" }, + { url = "https://files.pythonhosted.org/packages/db/11/3f8e803a43b79bc534c6a506674da9d614e990e37118b4506faf70d46ed6/coverage-7.6.10-cp311-cp311-win_amd64.whl", hash = "sha256:489a01f94aa581dbd961f306e37d75d4ba16104bbfa2b0edb21d29b73be83609", size = 211508, upload-time = "2024-12-26T16:57:41.234Z" }, + { url = "https://files.pythonhosted.org/packages/86/77/19d09ea06f92fdf0487499283b1b7af06bc422ea94534c8fe3a4cd023641/coverage-7.6.10-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:27c6e64726b307782fa5cbe531e7647aee385a29b2107cd87ba7c0105a5d3853", size = 208281, upload-time = "2024-12-26T16:57:42.968Z" }, + { url = "https://files.pythonhosted.org/packages/b6/67/5479b9f2f99fcfb49c0d5cf61912a5255ef80b6e80a3cddba39c38146cf4/coverage-7.6.10-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c56e097019e72c373bae32d946ecf9858fda841e48d82df7e81c63ac25554078", size = 208514, upload-time = "2024-12-26T16:57:45.747Z" }, + { url = "https://files.pythonhosted.org/packages/15/d1/febf59030ce1c83b7331c3546d7317e5120c5966471727aa7ac157729c4b/coverage-7.6.10-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c7827a5bc7bdb197b9e066cdf650b2887597ad124dd99777332776f7b7c7d0d0", size = 241537, upload-time = "2024-12-26T16:57:48.647Z" }, + { url = "https://files.pythonhosted.org/packages/4b/7e/5ac4c90192130e7cf8b63153fe620c8bfd9068f89a6d9b5f26f1550f7a26/coverage-7.6.10-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:204a8238afe787323a8b47d8be4df89772d5c1e4651b9ffa808552bdf20e1d50", size = 238572, upload-time = "2024-12-26T16:57:51.668Z" }, + { url = "https://files.pythonhosted.org/packages/dc/03/0334a79b26ecf59958f2fe9dd1f5ab3e2f88db876f5071933de39af09647/coverage-7.6.10-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e67926f51821b8e9deb6426ff3164870976fe414d033ad90ea75e7ed0c2e5022", size = 240639, upload-time = "2024-12-26T16:57:53.175Z" }, + { url = "https://files.pythonhosted.org/packages/d7/45/8a707f23c202208d7b286d78ad6233f50dcf929319b664b6cc18a03c1aae/coverage-7.6.10-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e78b270eadb5702938c3dbe9367f878249b5ef9a2fcc5360ac7bff694310d17b", size = 240072, upload-time = "2024-12-26T16:57:56.087Z" }, + { url = "https://files.pythonhosted.org/packages/66/02/603ce0ac2d02bc7b393279ef618940b4a0535b0868ee791140bda9ecfa40/coverage-7.6.10-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:714f942b9c15c3a7a5fe6876ce30af831c2ad4ce902410b7466b662358c852c0", size = 238386, upload-time = "2024-12-26T16:57:57.572Z" }, + { url = "https://files.pythonhosted.org/packages/04/62/4e6887e9be060f5d18f1dd58c2838b2d9646faf353232dec4e2d4b1c8644/coverage-7.6.10-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:abb02e2f5a3187b2ac4cd46b8ced85a0858230b577ccb2c62c81482ca7d18852", size = 240054, upload-time = "2024-12-26T16:57:58.967Z" }, + { url = "https://files.pythonhosted.org/packages/5c/74/83ae4151c170d8bd071924f212add22a0e62a7fe2b149edf016aeecad17c/coverage-7.6.10-cp312-cp312-win32.whl", hash = "sha256:55b201b97286cf61f5e76063f9e2a1d8d2972fc2fcfd2c1272530172fd28c359", size = 210904, upload-time = "2024-12-26T16:58:00.688Z" }, + { url = "https://files.pythonhosted.org/packages/c3/54/de0893186a221478f5880283119fc40483bc460b27c4c71d1b8bba3474b9/coverage-7.6.10-cp312-cp312-win_amd64.whl", hash = "sha256:e4ae5ac5e0d1e4edfc9b4b57b4cbecd5bc266a6915c500f358817a8496739247", size = 211692, upload-time = "2024-12-26T16:58:02.35Z" }, + { url = "https://files.pythonhosted.org/packages/25/6d/31883d78865529257bf847df5789e2ae80e99de8a460c3453dbfbe0db069/coverage-7.6.10-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:05fca8ba6a87aabdd2d30d0b6c838b50510b56cdcfc604d40760dae7153b73d9", size = 208308, upload-time = "2024-12-26T16:58:04.487Z" }, + { url = "https://files.pythonhosted.org/packages/70/22/3f2b129cc08de00c83b0ad6252e034320946abfc3e4235c009e57cfeee05/coverage-7.6.10-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9e80eba8801c386f72e0712a0453431259c45c3249f0009aff537a517b52942b", size = 208565, upload-time = "2024-12-26T16:58:06.774Z" }, + { url = "https://files.pythonhosted.org/packages/97/0a/d89bc2d1cc61d3a8dfe9e9d75217b2be85f6c73ebf1b9e3c2f4e797f4531/coverage-7.6.10-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a372c89c939d57abe09e08c0578c1d212e7a678135d53aa16eec4430adc5e690", size = 241083, upload-time = "2024-12-26T16:58:10.27Z" }, + { url = "https://files.pythonhosted.org/packages/4c/81/6d64b88a00c7a7aaed3a657b8eaa0931f37a6395fcef61e53ff742b49c97/coverage-7.6.10-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ec22b5e7fe7a0fa8509181c4aac1db48f3dd4d3a566131b313d1efc102892c18", size = 238235, upload-time = "2024-12-26T16:58:12.497Z" }, + { url = "https://files.pythonhosted.org/packages/9a/0b/7797d4193f5adb4b837207ed87fecf5fc38f7cc612b369a8e8e12d9fa114/coverage-7.6.10-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26bcf5c4df41cad1b19c84af71c22cbc9ea9a547fc973f1f2cc9a290002c8b3c", size = 240220, upload-time = "2024-12-26T16:58:15.619Z" }, + { url = "https://files.pythonhosted.org/packages/65/4d/6f83ca1bddcf8e51bf8ff71572f39a1c73c34cf50e752a952c34f24d0a60/coverage-7.6.10-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4e4630c26b6084c9b3cb53b15bd488f30ceb50b73c35c5ad7871b869cb7365fd", size = 239847, upload-time = "2024-12-26T16:58:17.126Z" }, + { url = "https://files.pythonhosted.org/packages/30/9d/2470df6aa146aff4c65fee0f87f58d2164a67533c771c9cc12ffcdb865d5/coverage-7.6.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2396e8116db77789f819d2bc8a7e200232b7a282c66e0ae2d2cd84581a89757e", size = 237922, upload-time = "2024-12-26T16:58:20.198Z" }, + { url = "https://files.pythonhosted.org/packages/08/dd/723fef5d901e6a89f2507094db66c091449c8ba03272861eaefa773ad95c/coverage-7.6.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:79109c70cc0882e4d2d002fe69a24aa504dec0cc17169b3c7f41a1d341a73694", size = 239783, upload-time = "2024-12-26T16:58:23.614Z" }, + { url = "https://files.pythonhosted.org/packages/3d/f7/64d3298b2baf261cb35466000628706ce20a82d42faf9b771af447cd2b76/coverage-7.6.10-cp313-cp313-win32.whl", hash = "sha256:9e1747bab246d6ff2c4f28b4d186b205adced9f7bd9dc362051cc37c4a0c7bd6", size = 210965, upload-time = "2024-12-26T16:58:26.765Z" }, + { url = "https://files.pythonhosted.org/packages/d5/58/ec43499a7fc681212fe7742fe90b2bc361cdb72e3181ace1604247a5b24d/coverage-7.6.10-cp313-cp313-win_amd64.whl", hash = "sha256:254f1a3b1eef5f7ed23ef265eaa89c65c8c5b6b257327c149db1ca9d4a35f25e", size = 211719, upload-time = "2024-12-26T16:58:28.781Z" }, + { url = "https://files.pythonhosted.org/packages/ab/c9/f2857a135bcff4330c1e90e7d03446b036b2363d4ad37eb5e3a47bbac8a6/coverage-7.6.10-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2ccf240eb719789cedbb9fd1338055de2761088202a9a0b73032857e53f612fe", size = 209050, upload-time = "2024-12-26T16:58:31.616Z" }, + { url = "https://files.pythonhosted.org/packages/aa/b3/f840e5bd777d8433caa9e4a1eb20503495709f697341ac1a8ee6a3c906ad/coverage-7.6.10-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0c807ca74d5a5e64427c8805de15b9ca140bba13572d6d74e262f46f50b13273", size = 209321, upload-time = "2024-12-26T16:58:34.509Z" }, + { url = "https://files.pythonhosted.org/packages/85/7d/125a5362180fcc1c03d91850fc020f3831d5cda09319522bcfa6b2b70be7/coverage-7.6.10-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2bcfa46d7709b5a7ffe089075799b902020b62e7ee56ebaed2f4bdac04c508d8", size = 252039, upload-time = "2024-12-26T16:58:36.072Z" }, + { url = "https://files.pythonhosted.org/packages/a9/9c/4358bf3c74baf1f9bddd2baf3756b54c07f2cfd2535f0a47f1e7757e54b3/coverage-7.6.10-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4e0de1e902669dccbf80b0415fb6b43d27edca2fbd48c74da378923b05316098", size = 247758, upload-time = "2024-12-26T16:58:39.458Z" }, + { url = "https://files.pythonhosted.org/packages/cf/c7/de3eb6fc5263b26fab5cda3de7a0f80e317597a4bad4781859f72885f300/coverage-7.6.10-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f7b444c42bbc533aaae6b5a2166fd1a797cdb5eb58ee51a92bee1eb94a1e1cb", size = 250119, upload-time = "2024-12-26T16:58:41.018Z" }, + { url = "https://files.pythonhosted.org/packages/3e/e6/43de91f8ba2ec9140c6a4af1102141712949903dc732cf739167cfa7a3bc/coverage-7.6.10-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b330368cb99ef72fcd2dc3ed260adf67b31499584dc8a20225e85bfe6f6cfed0", size = 249597, upload-time = "2024-12-26T16:58:42.827Z" }, + { url = "https://files.pythonhosted.org/packages/08/40/61158b5499aa2adf9e37bc6d0117e8f6788625b283d51e7e0c53cf340530/coverage-7.6.10-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:9a7cfb50515f87f7ed30bc882f68812fd98bc2852957df69f3003d22a2aa0abf", size = 247473, upload-time = "2024-12-26T16:58:44.486Z" }, + { url = "https://files.pythonhosted.org/packages/50/69/b3f2416725621e9f112e74e8470793d5b5995f146f596f133678a633b77e/coverage-7.6.10-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:6f93531882a5f68c28090f901b1d135de61b56331bba82028489bc51bdd818d2", size = 248737, upload-time = "2024-12-26T16:58:45.919Z" }, + { url = "https://files.pythonhosted.org/packages/3c/6e/fe899fb937657db6df31cc3e61c6968cb56d36d7326361847440a430152e/coverage-7.6.10-cp313-cp313t-win32.whl", hash = "sha256:89d76815a26197c858f53c7f6a656686ec392b25991f9e409bcef020cd532312", size = 211611, upload-time = "2024-12-26T16:58:47.883Z" }, + { url = "https://files.pythonhosted.org/packages/1c/55/52f5e66142a9d7bc93a15192eba7a78513d2abf6b3558d77b4ca32f5f424/coverage-7.6.10-cp313-cp313t-win_amd64.whl", hash = "sha256:54a5f0f43950a36312155dae55c505a76cd7f2b12d26abeebbe7a0b36dbc868d", size = 212781, upload-time = "2024-12-26T16:58:50.822Z" }, + { url = "https://files.pythonhosted.org/packages/40/41/473617aadf9a1c15bc2d56be65d90d7c29bfa50a957a67ef96462f7ebf8e/coverage-7.6.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:656c82b8a0ead8bba147de9a89bda95064874c91a3ed43a00e687f23cc19d53a", size = 207978, upload-time = "2024-12-26T16:58:52.834Z" }, + { url = "https://files.pythonhosted.org/packages/10/f6/480586607768b39a30e6910a3c4522139094ac0f1677028e1f4823688957/coverage-7.6.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ccc2b70a7ed475c68ceb548bf69cec1e27305c1c2606a5eb7c3afff56a1b3b27", size = 208415, upload-time = "2024-12-26T16:58:56.317Z" }, + { url = "https://files.pythonhosted.org/packages/f1/af/439bb760f817deff6f4d38fe7da08d9dd7874a560241f1945bc3b4446550/coverage-7.6.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5e37dc41d57ceba70956fa2fc5b63c26dba863c946ace9705f8eca99daecdc4", size = 236452, upload-time = "2024-12-26T16:58:59.158Z" }, + { url = "https://files.pythonhosted.org/packages/d0/13/481f4ceffcabe29ee2332e60efb52e4694f54a402f3ada2bcec10bb32e43/coverage-7.6.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0aa9692b4fdd83a4647eeb7db46410ea1322b5ed94cd1715ef09d1d5922ba87f", size = 234374, upload-time = "2024-12-26T16:59:00.809Z" }, + { url = "https://files.pythonhosted.org/packages/c5/59/4607ea9d6b1b73e905c7656da08d0b00cdf6e59f2293ec259e8914160025/coverage-7.6.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa744da1820678b475e4ba3dfd994c321c5b13381d1041fe9c608620e6676e25", size = 235505, upload-time = "2024-12-26T16:59:03.869Z" }, + { url = "https://files.pythonhosted.org/packages/85/60/d66365723b9b7f29464b11d024248ed3523ce5aab958e4ad8c43f3f4148b/coverage-7.6.10-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c0b1818063dc9e9d838c09e3a473c1422f517889436dd980f5d721899e66f315", size = 234616, upload-time = "2024-12-26T16:59:05.876Z" }, + { url = "https://files.pythonhosted.org/packages/74/f8/2cf7a38e7d81b266f47dfcf137fecd8fa66c7bdbd4228d611628d8ca3437/coverage-7.6.10-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:59af35558ba08b758aec4d56182b222976330ef8d2feacbb93964f576a7e7a90", size = 233099, upload-time = "2024-12-26T16:59:08.927Z" }, + { url = "https://files.pythonhosted.org/packages/50/2b/bff6c1c6b63c4396ea7ecdbf8db1788b46046c681b8fcc6ec77db9f4ea49/coverage-7.6.10-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7ed2f37cfce1ce101e6dffdfd1c99e729dd2ffc291d02d3e2d0af8b53d13840d", size = 234089, upload-time = "2024-12-26T16:59:10.574Z" }, + { url = "https://files.pythonhosted.org/packages/bf/b5/baace1c754d546a67779358341aa8d2f7118baf58cac235db457e1001d1b/coverage-7.6.10-cp39-cp39-win32.whl", hash = "sha256:4bcc276261505d82f0ad426870c3b12cb177752834a633e737ec5ee79bbdff18", size = 210701, upload-time = "2024-12-26T16:59:12.212Z" }, + { url = "https://files.pythonhosted.org/packages/b1/bf/9e1e95b8b20817398ecc5a1e8d3e05ff404e1b9fb2185cd71561698fe2a2/coverage-7.6.10-cp39-cp39-win_amd64.whl", hash = "sha256:457574f4599d2b00f7f637a0700a6422243b3565509457b2dbd3f50703e11f59", size = 211482, upload-time = "2024-12-26T16:59:15.165Z" }, + { url = "https://files.pythonhosted.org/packages/a1/70/de81bfec9ed38a64fc44a77c7665e20ca507fc3265597c28b0d989e4082e/coverage-7.6.10-pp39.pp310-none-any.whl", hash = "sha256:fd34e7b3405f0cc7ab03d54a334c17a9e802897580d964bd8c2001f4b9fd488f", size = 200223, upload-time = "2024-12-26T16:59:16.968Z" }, ] [[package]] name = "dirty-equals" version = "0.9.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b0/99/133892f401ced5a27e641a473c547d5fbdb39af8f85dac8a9d633ea3e7a7/dirty_equals-0.9.0.tar.gz", hash = "sha256:17f515970b04ed7900b733c95fd8091f4f85e52f1fb5f268757f25c858eb1f7b", size = 50412 } +sdist = { url = "https://files.pythonhosted.org/packages/b0/99/133892f401ced5a27e641a473c547d5fbdb39af8f85dac8a9d633ea3e7a7/dirty_equals-0.9.0.tar.gz", hash = "sha256:17f515970b04ed7900b733c95fd8091f4f85e52f1fb5f268757f25c858eb1f7b", size = 50412, upload-time = "2025-01-11T23:23:40.491Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/77/0c/03cc99bf3b6328604b10829de3460f2b2ad3373200c45665c38508e550c6/dirty_equals-0.9.0-py3-none-any.whl", hash = "sha256:ff4d027f5cfa1b69573af00f7ba9043ea652dbdce3fe5cbe828e478c7346db9c", size = 28226 }, + { url = "https://files.pythonhosted.org/packages/77/0c/03cc99bf3b6328604b10829de3460f2b2ad3373200c45665c38508e550c6/dirty_equals-0.9.0-py3-none-any.whl", hash = "sha256:ff4d027f5cfa1b69573af00f7ba9043ea652dbdce3fe5cbe828e478c7346db9c", size = 28226, upload-time = "2025-01-11T23:23:37.489Z" }, ] [[package]] name = "exceptiongroup" version = "1.2.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 } +sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883, upload-time = "2024-07-12T22:26:00.161Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 }, + { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453, upload-time = "2024-07-12T22:25:58.476Z" }, ] [[package]] name = "executing" version = "2.2.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/91/50/a9d80c47ff289c611ff12e63f7c5d13942c65d68125160cefd768c73e6e4/executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755", size = 978693 } +sdist = { url = "https://files.pythonhosted.org/packages/91/50/a9d80c47ff289c611ff12e63f7c5d13942c65d68125160cefd768c73e6e4/executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755", size = 978693, upload-time = "2025-01-22T15:41:29.403Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702 }, + { url = "https://files.pythonhosted.org/packages/7b/8f/c4d9bafc34ad7ad5d8dc16dd1347ee0e507a52c3adb6bfa8887e1c6a26ba/executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", size = 26702, upload-time = "2025-01-22T15:41:25.929Z" }, ] [[package]] @@ -252,9 +254,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/5c/74/cd35a98cb11f79de0581e8e1e6fbd738aeeed1f2d90e9b5106728b63f5f7/griffe-1.5.5.tar.gz", hash = "sha256:35ee5b38b93d6a839098aad0f92207e6ad6b70c3e8866c08ca669275b8cba585", size = 391124 } +sdist = { url = "https://files.pythonhosted.org/packages/5c/74/cd35a98cb11f79de0581e8e1e6fbd738aeeed1f2d90e9b5106728b63f5f7/griffe-1.5.5.tar.gz", hash = "sha256:35ee5b38b93d6a839098aad0f92207e6ad6b70c3e8866c08ca669275b8cba585", size = 391124, upload-time = "2025-01-16T20:18:18.934Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1f/88/52c9422bc853cd7c2b6122090e887d17b5fad29b67f930e4277c9c557357/griffe-1.5.5-py3-none-any.whl", hash = "sha256:2761b1e8876c6f1f9ab1af274df93ea6bbadd65090de5f38f4cb5cc84897c7dd", size = 128221 }, + { url = "https://files.pythonhosted.org/packages/1f/88/52c9422bc853cd7c2b6122090e887d17b5fad29b67f930e4277c9c557357/griffe-1.5.5-py3-none-any.whl", hash = "sha256:2761b1e8876c6f1f9ab1af274df93ea6bbadd65090de5f38f4cb5cc84897c7dd", size = 128221, upload-time = "2025-01-16T20:18:15.887Z" }, ] [[package]] @@ -266,18 +268,18 @@ dependencies = [ { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "sortedcontainers" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/e6/3b/3a7cf8973b0424c6af0b2b5fe30f89ab738616bad2a16aafcc49ff069ed4/hypothesis-6.124.2.tar.gz", hash = "sha256:c98823fc1323f23399e5f2251982fd1f38259f84cf627aaaea1b3f0a0d4d2b03", size = 419462 } +sdist = { url = "https://files.pythonhosted.org/packages/e6/3b/3a7cf8973b0424c6af0b2b5fe30f89ab738616bad2a16aafcc49ff069ed4/hypothesis-6.124.2.tar.gz", hash = "sha256:c98823fc1323f23399e5f2251982fd1f38259f84cf627aaaea1b3f0a0d4d2b03", size = 419462, upload-time = "2025-01-21T18:45:00.461Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a3/e1/80f1819e65a9a0b1b744b453cd26803764fc192cff8eaea202e76f6f5a65/hypothesis-6.124.2-py3-none-any.whl", hash = "sha256:fef7709a404929a9cd3e785f60a6e026089aab986e288b1fdced13091574d474", size = 482180 }, + { url = "https://files.pythonhosted.org/packages/a3/e1/80f1819e65a9a0b1b744b453cd26803764fc192cff8eaea202e76f6f5a65/hypothesis-6.124.2-py3-none-any.whl", hash = "sha256:fef7709a404929a9cd3e785f60a6e026089aab986e288b1fdced13091574d474", size = 482180, upload-time = "2025-01-21T18:44:55.288Z" }, ] [[package]] name = "iniconfig" version = "2.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646 } +sdist = { url = "https://files.pythonhosted.org/packages/d7/4b/cbd8e699e64a6f16ca3a8220661b5f83792b3017d0f79807cb8708d33913/iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3", size = 4646, upload-time = "2023-01-07T11:08:11.254Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 }, + { url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892, upload-time = "2023-01-07T11:08:09.864Z" }, ] [[package]] @@ -290,9 +292,9 @@ dependencies = [ { name = "rich" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/42/bc/bbba2efb2ab0c8cf3d43fb0a7a1d3dfd8533d3bf18df9662ee4c09af7cac/inline_snapshot-0.19.3.tar.gz", hash = "sha256:1e40f34da64fe2406c6bba3f473905e22386da43e16c85060610692325aa94d7", size = 88636 } +sdist = { url = "https://files.pythonhosted.org/packages/42/bc/bbba2efb2ab0c8cf3d43fb0a7a1d3dfd8533d3bf18df9662ee4c09af7cac/inline_snapshot-0.19.3.tar.gz", hash = "sha256:1e40f34da64fe2406c6bba3f473905e22386da43e16c85060610692325aa94d7", size = 88636, upload-time = "2025-01-15T18:48:55.515Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fd/fc/d99b8983af46c0adbe10ad369ab929eb35cb32635526a9de4fe06ffd612f/inline_snapshot-0.19.3-py3-none-any.whl", hash = "sha256:81ed10eedb593aee630d2fc0cfe5d10a843c4bd507c2d96ea058c28413985452", size = 43627 }, + { url = "https://files.pythonhosted.org/packages/fd/fc/d99b8983af46c0adbe10ad369ab929eb35cb32635526a9de4fe06ffd612f/inline_snapshot-0.19.3-py3-none-any.whl", hash = "sha256:81ed10eedb593aee630d2fc0cfe5d10a843c4bd507c2d96ea058c28413985452", size = 43627, upload-time = "2025-01-15T18:48:52.199Z" }, ] [[package]] @@ -302,9 +304,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "mdurl" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } +sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 }, + { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" }, ] [[package]] @@ -314,29 +316,29 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9a/08/ccb0f917722a35ab0d758be9bb5edaf645c3a3d6170061f10d396ecd273f/maturin-1.8.1.tar.gz", hash = "sha256:49cd964aabf59f8b0a6969f9860d2cdf194ac331529caae14c884f5659568857", size = 197397 } +sdist = { url = "https://files.pythonhosted.org/packages/9a/08/ccb0f917722a35ab0d758be9bb5edaf645c3a3d6170061f10d396ecd273f/maturin-1.8.1.tar.gz", hash = "sha256:49cd964aabf59f8b0a6969f9860d2cdf194ac331529caae14c884f5659568857", size = 197397, upload-time = "2024-12-30T14:03:48.109Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4c/00/f34077315f34db8ad2ccf6bfe11b864ca27baab3a1320634da8e3cf89a48/maturin-1.8.1-py3-none-linux_armv6l.whl", hash = "sha256:7e590a23d9076b8a994f2e67bc63dc9a2d1c9a41b1e7b45ac354ba8275254e89", size = 7568415 }, - { url = "https://files.pythonhosted.org/packages/5c/07/9219976135ce0cb32d2fa6ea5c6d0ad709013d9a17967312e149b98153a6/maturin-1.8.1-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8d8251a95682c83ea60988c804b620c181911cd824aa107b4a49ac5333c92968", size = 14527816 }, - { url = "https://files.pythonhosted.org/packages/e6/04/fa009a00903acdd1785d58322193140bfe358595347c39f315112dabdf9e/maturin-1.8.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b9fc1a4354cac5e32c190410208039812ea88c4a36bd2b6499268ec49ef5de00", size = 7580446 }, - { url = "https://files.pythonhosted.org/packages/9b/d4/414b2aab9bbfe88182b734d3aa1b4fef7d7701e50f6be48500378b8c8721/maturin-1.8.1-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:621e171c6b39f95f1d0df69a118416034fbd59c0f89dcaea8c2ea62019deecba", size = 7650535 }, - { url = "https://files.pythonhosted.org/packages/f0/64/879418a8a0196013ec1fb19eada0781c04a30e8d6d9227e80f91275a4f5b/maturin-1.8.1-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:98f638739a5132962347871b85c91f525c9246ef4d99796ae98a2031e3df029f", size = 8006702 }, - { url = "https://files.pythonhosted.org/packages/39/c2/605829324f8371294f70303aca130682df75318958efed246873d3d604ab/maturin-1.8.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:f9f5c47521924b6e515cbc652a042fe5f17f8747445be9d931048e5d8ddb50a4", size = 7368164 }, - { url = "https://files.pythonhosted.org/packages/be/6c/30e136d397bb146b94b628c0ef7f17708281611b97849e2cf37847025ac7/maturin-1.8.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:0f4407c7353c31bfbb8cdeb82bc2170e474cbfb97b5ba27568f440c9d6c1fdd4", size = 7450889 }, - { url = "https://files.pythonhosted.org/packages/1b/50/e1f5023512696d4e56096f702e2f68d6d9a30afe0a4eec82b0e27b8eb4e4/maturin-1.8.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:ec49cd70cad3c389946c6e2bc0bd50772a7fcb463040dd800720345897eec9bf", size = 9585819 }, - { url = "https://files.pythonhosted.org/packages/b7/80/b24b5248d89d2e5982553900237a337ea098ca9297b8369ca2aa95549e0f/maturin-1.8.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c08767d794de8f8a11c5c8b1b47a4ff9fb6ae2d2d97679e27030f2f509c8c2a0", size = 10920801 }, - { url = "https://files.pythonhosted.org/packages/6e/f4/8ede7a662fabf93456b44390a5ad22630e25fb5ddaecf787251071b2e143/maturin-1.8.1-py3-none-win32.whl", hash = "sha256:d678407713f3e10df33c5b3d7a343ec0551eb7f14d8ad9ba6febeb96f4e4c75c", size = 6873556 }, - { url = "https://files.pythonhosted.org/packages/9c/22/757f093ed0e319e9648155b8c9d716765442bea5bc98ebc58ad4ad5b0524/maturin-1.8.1-py3-none-win_amd64.whl", hash = "sha256:a526f90fe0e5cb59ffb81f4ff547ddc42e823bbdeae4a31012c0893ca6dcaf46", size = 7823153 }, - { url = "https://files.pythonhosted.org/packages/a4/f5/051413e04f6da25069db5e76759ecdb8cd2a8ab4a94045b5a3bf548c66fa/maturin-1.8.1-py3-none-win_arm64.whl", hash = "sha256:e95f077fd2ddd2f048182880eed458c308571a534be3eb2add4d3dac55bf57f4", size = 6552131 }, + { url = "https://files.pythonhosted.org/packages/4c/00/f34077315f34db8ad2ccf6bfe11b864ca27baab3a1320634da8e3cf89a48/maturin-1.8.1-py3-none-linux_armv6l.whl", hash = "sha256:7e590a23d9076b8a994f2e67bc63dc9a2d1c9a41b1e7b45ac354ba8275254e89", size = 7568415, upload-time = "2024-12-30T14:03:07.939Z" }, + { url = "https://files.pythonhosted.org/packages/5c/07/9219976135ce0cb32d2fa6ea5c6d0ad709013d9a17967312e149b98153a6/maturin-1.8.1-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:8d8251a95682c83ea60988c804b620c181911cd824aa107b4a49ac5333c92968", size = 14527816, upload-time = "2024-12-30T14:03:13.851Z" }, + { url = "https://files.pythonhosted.org/packages/e6/04/fa009a00903acdd1785d58322193140bfe358595347c39f315112dabdf9e/maturin-1.8.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b9fc1a4354cac5e32c190410208039812ea88c4a36bd2b6499268ec49ef5de00", size = 7580446, upload-time = "2024-12-30T14:03:17.64Z" }, + { url = "https://files.pythonhosted.org/packages/9b/d4/414b2aab9bbfe88182b734d3aa1b4fef7d7701e50f6be48500378b8c8721/maturin-1.8.1-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:621e171c6b39f95f1d0df69a118416034fbd59c0f89dcaea8c2ea62019deecba", size = 7650535, upload-time = "2024-12-30T14:03:21.115Z" }, + { url = "https://files.pythonhosted.org/packages/f0/64/879418a8a0196013ec1fb19eada0781c04a30e8d6d9227e80f91275a4f5b/maturin-1.8.1-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:98f638739a5132962347871b85c91f525c9246ef4d99796ae98a2031e3df029f", size = 8006702, upload-time = "2024-12-30T14:03:24.318Z" }, + { url = "https://files.pythonhosted.org/packages/39/c2/605829324f8371294f70303aca130682df75318958efed246873d3d604ab/maturin-1.8.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:f9f5c47521924b6e515cbc652a042fe5f17f8747445be9d931048e5d8ddb50a4", size = 7368164, upload-time = "2024-12-30T14:03:26.582Z" }, + { url = "https://files.pythonhosted.org/packages/be/6c/30e136d397bb146b94b628c0ef7f17708281611b97849e2cf37847025ac7/maturin-1.8.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:0f4407c7353c31bfbb8cdeb82bc2170e474cbfb97b5ba27568f440c9d6c1fdd4", size = 7450889, upload-time = "2024-12-30T14:03:28.893Z" }, + { url = "https://files.pythonhosted.org/packages/1b/50/e1f5023512696d4e56096f702e2f68d6d9a30afe0a4eec82b0e27b8eb4e4/maturin-1.8.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:ec49cd70cad3c389946c6e2bc0bd50772a7fcb463040dd800720345897eec9bf", size = 9585819, upload-time = "2024-12-30T14:03:31.125Z" }, + { url = "https://files.pythonhosted.org/packages/b7/80/b24b5248d89d2e5982553900237a337ea098ca9297b8369ca2aa95549e0f/maturin-1.8.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c08767d794de8f8a11c5c8b1b47a4ff9fb6ae2d2d97679e27030f2f509c8c2a0", size = 10920801, upload-time = "2024-12-30T14:03:35.127Z" }, + { url = "https://files.pythonhosted.org/packages/6e/f4/8ede7a662fabf93456b44390a5ad22630e25fb5ddaecf787251071b2e143/maturin-1.8.1-py3-none-win32.whl", hash = "sha256:d678407713f3e10df33c5b3d7a343ec0551eb7f14d8ad9ba6febeb96f4e4c75c", size = 6873556, upload-time = "2024-12-30T14:03:37.913Z" }, + { url = "https://files.pythonhosted.org/packages/9c/22/757f093ed0e319e9648155b8c9d716765442bea5bc98ebc58ad4ad5b0524/maturin-1.8.1-py3-none-win_amd64.whl", hash = "sha256:a526f90fe0e5cb59ffb81f4ff547ddc42e823bbdeae4a31012c0893ca6dcaf46", size = 7823153, upload-time = "2024-12-30T14:03:40.33Z" }, + { url = "https://files.pythonhosted.org/packages/a4/f5/051413e04f6da25069db5e76759ecdb8cd2a8ab4a94045b5a3bf548c66fa/maturin-1.8.1-py3-none-win_arm64.whl", hash = "sha256:e95f077fd2ddd2f048182880eed458c308571a534be3eb2add4d3dac55bf57f4", size = 6552131, upload-time = "2024-12-30T14:03:45.203Z" }, ] [[package]] name = "mdurl" version = "0.1.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, ] [[package]] @@ -348,57 +350,57 @@ dependencies = [ { name = "tomli", marker = "python_full_version < '3.11'" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/b9/eb/2c92d8ea1e684440f54fa49ac5d9a5f19967b7b472a281f419e69a8d228e/mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6", size = 3216051 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9b/7a/87ae2adb31d68402da6da1e5f30c07ea6063e9f09b5e7cfc9dfa44075e74/mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb", size = 11211002 }, - { url = "https://files.pythonhosted.org/packages/e1/23/eada4c38608b444618a132be0d199b280049ded278b24cbb9d3fc59658e4/mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0", size = 10358400 }, - { url = "https://files.pythonhosted.org/packages/43/c9/d6785c6f66241c62fd2992b05057f404237deaad1566545e9f144ced07f5/mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d", size = 12095172 }, - { url = "https://files.pythonhosted.org/packages/c3/62/daa7e787770c83c52ce2aaf1a111eae5893de9e004743f51bfcad9e487ec/mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b", size = 12828732 }, - { url = "https://files.pythonhosted.org/packages/1b/a2/5fb18318a3637f29f16f4e41340b795da14f4751ef4f51c99ff39ab62e52/mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427", size = 13012197 }, - { url = "https://files.pythonhosted.org/packages/28/99/e153ce39105d164b5f02c06c35c7ba958aaff50a2babba7d080988b03fe7/mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f", size = 9780836 }, - { url = "https://files.pythonhosted.org/packages/da/11/a9422850fd506edbcdc7f6090682ecceaf1f87b9dd847f9df79942da8506/mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c", size = 11120432 }, - { url = "https://files.pythonhosted.org/packages/b6/9e/47e450fd39078d9c02d620545b2cb37993a8a8bdf7db3652ace2f80521ca/mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1", size = 10279515 }, - { url = "https://files.pythonhosted.org/packages/01/b5/6c8d33bd0f851a7692a8bfe4ee75eb82b6983a3cf39e5e32a5d2a723f0c1/mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8", size = 12025791 }, - { url = "https://files.pythonhosted.org/packages/f0/4c/e10e2c46ea37cab5c471d0ddaaa9a434dc1d28650078ac1b56c2d7b9b2e4/mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f", size = 12749203 }, - { url = "https://files.pythonhosted.org/packages/88/55/beacb0c69beab2153a0f57671ec07861d27d735a0faff135a494cd4f5020/mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1", size = 12885900 }, - { url = "https://files.pythonhosted.org/packages/a2/75/8c93ff7f315c4d086a2dfcde02f713004357d70a163eddb6c56a6a5eff40/mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae", size = 9777869 }, - { url = "https://files.pythonhosted.org/packages/43/1b/b38c079609bb4627905b74fc6a49849835acf68547ac33d8ceb707de5f52/mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14", size = 11266668 }, - { url = "https://files.pythonhosted.org/packages/6b/75/2ed0d2964c1ffc9971c729f7a544e9cd34b2cdabbe2d11afd148d7838aa2/mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9", size = 10254060 }, - { url = "https://files.pythonhosted.org/packages/a1/5f/7b8051552d4da3c51bbe8fcafffd76a6823779101a2b198d80886cd8f08e/mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11", size = 11933167 }, - { url = "https://files.pythonhosted.org/packages/04/90/f53971d3ac39d8b68bbaab9a4c6c58c8caa4d5fd3d587d16f5927eeeabe1/mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e", size = 12864341 }, - { url = "https://files.pythonhosted.org/packages/03/d2/8bc0aeaaf2e88c977db41583559319f1821c069e943ada2701e86d0430b7/mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89", size = 12972991 }, - { url = "https://files.pythonhosted.org/packages/6f/17/07815114b903b49b0f2cf7499f1c130e5aa459411596668267535fe9243c/mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b", size = 9879016 }, - { url = "https://files.pythonhosted.org/packages/9e/15/bb6a686901f59222275ab228453de741185f9d54fecbaacec041679496c6/mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255", size = 11252097 }, - { url = "https://files.pythonhosted.org/packages/f8/b3/8b0f74dfd072c802b7fa368829defdf3ee1566ba74c32a2cb2403f68024c/mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34", size = 10239728 }, - { url = "https://files.pythonhosted.org/packages/c5/9b/4fd95ab20c52bb5b8c03cc49169be5905d931de17edfe4d9d2986800b52e/mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a", size = 11924965 }, - { url = "https://files.pythonhosted.org/packages/56/9d/4a236b9c57f5d8f08ed346914b3f091a62dd7e19336b2b2a0d85485f82ff/mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9", size = 12867660 }, - { url = "https://files.pythonhosted.org/packages/40/88/a61a5497e2f68d9027de2bb139c7bb9abaeb1be1584649fa9d807f80a338/mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd", size = 12969198 }, - { url = "https://files.pythonhosted.org/packages/54/da/3d6fc5d92d324701b0c23fb413c853892bfe0e1dbe06c9138037d459756b/mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107", size = 9885276 }, - { url = "https://files.pythonhosted.org/packages/ca/1f/186d133ae2514633f8558e78cd658070ba686c0e9275c5a5c24a1e1f0d67/mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35", size = 11200493 }, - { url = "https://files.pythonhosted.org/packages/af/fc/4842485d034e38a4646cccd1369f6b1ccd7bc86989c52770d75d719a9941/mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc", size = 10357702 }, - { url = "https://files.pythonhosted.org/packages/b4/e6/457b83f2d701e23869cfec013a48a12638f75b9d37612a9ddf99072c1051/mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9", size = 12091104 }, - { url = "https://files.pythonhosted.org/packages/f1/bf/76a569158db678fee59f4fd30b8e7a0d75bcbaeef49edd882a0d63af6d66/mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb", size = 12830167 }, - { url = "https://files.pythonhosted.org/packages/43/bc/0bc6b694b3103de9fed61867f1c8bd33336b913d16831431e7cb48ef1c92/mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60", size = 13013834 }, - { url = "https://files.pythonhosted.org/packages/b0/79/5f5ec47849b6df1e6943d5fd8e6632fbfc04b4fd4acfa5a5a9535d11b4e2/mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c", size = 9781231 }, - { url = "https://files.pythonhosted.org/packages/a0/b5/32dd67b69a16d088e533962e5044e51004176a9952419de0370cdaead0f8/mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1", size = 2752905 }, +sdist = { url = "https://files.pythonhosted.org/packages/b9/eb/2c92d8ea1e684440f54fa49ac5d9a5f19967b7b472a281f419e69a8d228e/mypy-1.14.1.tar.gz", hash = "sha256:7ec88144fe9b510e8475ec2f5f251992690fcf89ccb4500b214b4226abcd32d6", size = 3216051, upload-time = "2024-12-30T16:39:07.335Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/7a/87ae2adb31d68402da6da1e5f30c07ea6063e9f09b5e7cfc9dfa44075e74/mypy-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:52686e37cf13d559f668aa398dd7ddf1f92c5d613e4f8cb262be2fb4fedb0fcb", size = 11211002, upload-time = "2024-12-30T16:37:22.435Z" }, + { url = "https://files.pythonhosted.org/packages/e1/23/eada4c38608b444618a132be0d199b280049ded278b24cbb9d3fc59658e4/mypy-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1fb545ca340537d4b45d3eecdb3def05e913299ca72c290326be19b3804b39c0", size = 10358400, upload-time = "2024-12-30T16:37:53.526Z" }, + { url = "https://files.pythonhosted.org/packages/43/c9/d6785c6f66241c62fd2992b05057f404237deaad1566545e9f144ced07f5/mypy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:90716d8b2d1f4cd503309788e51366f07c56635a3309b0f6a32547eaaa36a64d", size = 12095172, upload-time = "2024-12-30T16:37:50.332Z" }, + { url = "https://files.pythonhosted.org/packages/c3/62/daa7e787770c83c52ce2aaf1a111eae5893de9e004743f51bfcad9e487ec/mypy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2ae753f5c9fef278bcf12e1a564351764f2a6da579d4a81347e1d5a15819997b", size = 12828732, upload-time = "2024-12-30T16:37:29.96Z" }, + { url = "https://files.pythonhosted.org/packages/1b/a2/5fb18318a3637f29f16f4e41340b795da14f4751ef4f51c99ff39ab62e52/mypy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e0fe0f5feaafcb04505bcf439e991c6d8f1bf8b15f12b05feeed96e9e7bf1427", size = 13012197, upload-time = "2024-12-30T16:38:05.037Z" }, + { url = "https://files.pythonhosted.org/packages/28/99/e153ce39105d164b5f02c06c35c7ba958aaff50a2babba7d080988b03fe7/mypy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:7d54bd85b925e501c555a3227f3ec0cfc54ee8b6930bd6141ec872d1c572f81f", size = 9780836, upload-time = "2024-12-30T16:37:19.726Z" }, + { url = "https://files.pythonhosted.org/packages/da/11/a9422850fd506edbcdc7f6090682ecceaf1f87b9dd847f9df79942da8506/mypy-1.14.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f995e511de847791c3b11ed90084a7a0aafdc074ab88c5a9711622fe4751138c", size = 11120432, upload-time = "2024-12-30T16:37:11.533Z" }, + { url = "https://files.pythonhosted.org/packages/b6/9e/47e450fd39078d9c02d620545b2cb37993a8a8bdf7db3652ace2f80521ca/mypy-1.14.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d64169ec3b8461311f8ce2fd2eb5d33e2d0f2c7b49116259c51d0d96edee48d1", size = 10279515, upload-time = "2024-12-30T16:37:40.724Z" }, + { url = "https://files.pythonhosted.org/packages/01/b5/6c8d33bd0f851a7692a8bfe4ee75eb82b6983a3cf39e5e32a5d2a723f0c1/mypy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ba24549de7b89b6381b91fbc068d798192b1b5201987070319889e93038967a8", size = 12025791, upload-time = "2024-12-30T16:36:58.73Z" }, + { url = "https://files.pythonhosted.org/packages/f0/4c/e10e2c46ea37cab5c471d0ddaaa9a434dc1d28650078ac1b56c2d7b9b2e4/mypy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:183cf0a45457d28ff9d758730cd0210419ac27d4d3f285beda038c9083363b1f", size = 12749203, upload-time = "2024-12-30T16:37:03.741Z" }, + { url = "https://files.pythonhosted.org/packages/88/55/beacb0c69beab2153a0f57671ec07861d27d735a0faff135a494cd4f5020/mypy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f2a0ecc86378f45347f586e4163d1769dd81c5a223d577fe351f26b179e148b1", size = 12885900, upload-time = "2024-12-30T16:37:57.948Z" }, + { url = "https://files.pythonhosted.org/packages/a2/75/8c93ff7f315c4d086a2dfcde02f713004357d70a163eddb6c56a6a5eff40/mypy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:ad3301ebebec9e8ee7135d8e3109ca76c23752bac1e717bc84cd3836b4bf3eae", size = 9777869, upload-time = "2024-12-30T16:37:33.428Z" }, + { url = "https://files.pythonhosted.org/packages/43/1b/b38c079609bb4627905b74fc6a49849835acf68547ac33d8ceb707de5f52/mypy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:30ff5ef8519bbc2e18b3b54521ec319513a26f1bba19a7582e7b1f58a6e69f14", size = 11266668, upload-time = "2024-12-30T16:38:02.211Z" }, + { url = "https://files.pythonhosted.org/packages/6b/75/2ed0d2964c1ffc9971c729f7a544e9cd34b2cdabbe2d11afd148d7838aa2/mypy-1.14.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb9f255c18052343c70234907e2e532bc7e55a62565d64536dbc7706a20b78b9", size = 10254060, upload-time = "2024-12-30T16:37:46.131Z" }, + { url = "https://files.pythonhosted.org/packages/a1/5f/7b8051552d4da3c51bbe8fcafffd76a6823779101a2b198d80886cd8f08e/mypy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b4e3413e0bddea671012b063e27591b953d653209e7a4fa5e48759cda77ca11", size = 11933167, upload-time = "2024-12-30T16:37:43.534Z" }, + { url = "https://files.pythonhosted.org/packages/04/90/f53971d3ac39d8b68bbaab9a4c6c58c8caa4d5fd3d587d16f5927eeeabe1/mypy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:553c293b1fbdebb6c3c4030589dab9fafb6dfa768995a453d8a5d3b23784af2e", size = 12864341, upload-time = "2024-12-30T16:37:36.249Z" }, + { url = "https://files.pythonhosted.org/packages/03/d2/8bc0aeaaf2e88c977db41583559319f1821c069e943ada2701e86d0430b7/mypy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fad79bfe3b65fe6a1efaed97b445c3d37f7be9fdc348bdb2d7cac75579607c89", size = 12972991, upload-time = "2024-12-30T16:37:06.743Z" }, + { url = "https://files.pythonhosted.org/packages/6f/17/07815114b903b49b0f2cf7499f1c130e5aa459411596668267535fe9243c/mypy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:8fa2220e54d2946e94ab6dbb3ba0a992795bd68b16dc852db33028df2b00191b", size = 9879016, upload-time = "2024-12-30T16:37:15.02Z" }, + { url = "https://files.pythonhosted.org/packages/9e/15/bb6a686901f59222275ab228453de741185f9d54fecbaacec041679496c6/mypy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:92c3ed5afb06c3a8e188cb5da4984cab9ec9a77ba956ee419c68a388b4595255", size = 11252097, upload-time = "2024-12-30T16:37:25.144Z" }, + { url = "https://files.pythonhosted.org/packages/f8/b3/8b0f74dfd072c802b7fa368829defdf3ee1566ba74c32a2cb2403f68024c/mypy-1.14.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dbec574648b3e25f43d23577309b16534431db4ddc09fda50841f1e34e64ed34", size = 10239728, upload-time = "2024-12-30T16:38:08.634Z" }, + { url = "https://files.pythonhosted.org/packages/c5/9b/4fd95ab20c52bb5b8c03cc49169be5905d931de17edfe4d9d2986800b52e/mypy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8c6d94b16d62eb3e947281aa7347d78236688e21081f11de976376cf010eb31a", size = 11924965, upload-time = "2024-12-30T16:38:12.132Z" }, + { url = "https://files.pythonhosted.org/packages/56/9d/4a236b9c57f5d8f08ed346914b3f091a62dd7e19336b2b2a0d85485f82ff/mypy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d4b19b03fdf54f3c5b2fa474c56b4c13c9dbfb9a2db4370ede7ec11a2c5927d9", size = 12867660, upload-time = "2024-12-30T16:38:17.342Z" }, + { url = "https://files.pythonhosted.org/packages/40/88/a61a5497e2f68d9027de2bb139c7bb9abaeb1be1584649fa9d807f80a338/mypy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0c911fde686394753fff899c409fd4e16e9b294c24bfd5e1ea4675deae1ac6fd", size = 12969198, upload-time = "2024-12-30T16:38:32.839Z" }, + { url = "https://files.pythonhosted.org/packages/54/da/3d6fc5d92d324701b0c23fb413c853892bfe0e1dbe06c9138037d459756b/mypy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:8b21525cb51671219f5307be85f7e646a153e5acc656e5cebf64bfa076c50107", size = 9885276, upload-time = "2024-12-30T16:38:20.828Z" }, + { url = "https://files.pythonhosted.org/packages/ca/1f/186d133ae2514633f8558e78cd658070ba686c0e9275c5a5c24a1e1f0d67/mypy-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3888a1816d69f7ab92092f785a462944b3ca16d7c470d564165fe703b0970c35", size = 11200493, upload-time = "2024-12-30T16:38:26.935Z" }, + { url = "https://files.pythonhosted.org/packages/af/fc/4842485d034e38a4646cccd1369f6b1ccd7bc86989c52770d75d719a9941/mypy-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46c756a444117c43ee984bd055db99e498bc613a70bbbc120272bd13ca579fbc", size = 10357702, upload-time = "2024-12-30T16:38:50.623Z" }, + { url = "https://files.pythonhosted.org/packages/b4/e6/457b83f2d701e23869cfec013a48a12638f75b9d37612a9ddf99072c1051/mypy-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:27fc248022907e72abfd8e22ab1f10e903915ff69961174784a3900a8cba9ad9", size = 12091104, upload-time = "2024-12-30T16:38:53.735Z" }, + { url = "https://files.pythonhosted.org/packages/f1/bf/76a569158db678fee59f4fd30b8e7a0d75bcbaeef49edd882a0d63af6d66/mypy-1.14.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:499d6a72fb7e5de92218db961f1a66d5f11783f9ae549d214617edab5d4dbdbb", size = 12830167, upload-time = "2024-12-30T16:38:56.437Z" }, + { url = "https://files.pythonhosted.org/packages/43/bc/0bc6b694b3103de9fed61867f1c8bd33336b913d16831431e7cb48ef1c92/mypy-1.14.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:57961db9795eb566dc1d1b4e9139ebc4c6b0cb6e7254ecde69d1552bf7613f60", size = 13013834, upload-time = "2024-12-30T16:38:59.204Z" }, + { url = "https://files.pythonhosted.org/packages/b0/79/5f5ec47849b6df1e6943d5fd8e6632fbfc04b4fd4acfa5a5a9535d11b4e2/mypy-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:07ba89fdcc9451f2ebb02853deb6aaaa3d2239a236669a63ab3801bbf923ef5c", size = 9781231, upload-time = "2024-12-30T16:39:05.124Z" }, + { url = "https://files.pythonhosted.org/packages/a0/b5/32dd67b69a16d088e533962e5044e51004176a9952419de0370cdaead0f8/mypy-1.14.1-py3-none-any.whl", hash = "sha256:b66a60cc4073aeb8ae00057f9c1f64d49e90f918fbcef9a977eb121da8b8f1d1", size = 2752905, upload-time = "2024-12-30T16:38:42.021Z" }, ] [[package]] name = "mypy-extensions" version = "1.0.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433 } +sdist = { url = "https://files.pythonhosted.org/packages/98/a4/1ab47638b92648243faf97a5aeb6ea83059cc3624972ab6b8d2316078d3f/mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782", size = 4433, upload-time = "2023-02-04T12:11:27.157Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695 }, + { url = "https://files.pythonhosted.org/packages/2a/e2/5d3f6ada4297caebe1a2add3b126fe800c96f56dbe5d1988a2cbe0b267aa/mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", size = 4695, upload-time = "2023-02-04T12:11:25.002Z" }, ] [[package]] name = "nodeenv" version = "1.9.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437 } +sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314 }, + { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, ] [[package]] @@ -408,32 +410,32 @@ source = { registry = "https://pypi.org/simple" } resolution-markers = [ "python_full_version < '3.10'", ] -sdist = { url = "https://files.pythonhosted.org/packages/a9/75/10dd1f8116a8b796cb2c737b674e02d02e80454bda953fa7e65d8c12b016/numpy-2.0.2.tar.gz", hash = "sha256:883c987dee1880e2a864ab0dc9892292582510604156762362d9326444636e78", size = 18902015 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/21/91/3495b3237510f79f5d81f2508f9f13fea78ebfdf07538fc7444badda173d/numpy-2.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:51129a29dbe56f9ca83438b706e2e69a39892b5eda6cedcb6b0c9fdc9b0d3ece", size = 21165245 }, - { url = "https://files.pythonhosted.org/packages/6e/16/7bfcebf27bb4f9d7ec67332ffebee4d1bf085c84246552d52dbb548600e7/numpy-2.0.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:becfae3ddd30736fe1889a37f1f580e245ba79a5855bff5f2a29cb3ccc22dd7b", size = 6901774 }, - { url = "https://files.pythonhosted.org/packages/fa/66/f7177ab331876200ac7563a580140643d1179c8b4b6a6b0fc9838de2a9b8/numpy-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:496f71341824ed9f3d2fd36cf3ac57ae2e0165c143b55c3a035ee219413f3318", size = 19523451 }, - { url = "https://files.pythonhosted.org/packages/25/7f/0b209498009ad6453e4efc2c65bcdf0ae08a182b2b7877d7ab38a92dc542/numpy-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a61ec659f68ae254e4d237816e33171497e978140353c0c2038d46e63282d0c8", size = 19927572 }, - { url = "https://files.pythonhosted.org/packages/10/05/3442317535028bc29cf0c0dd4c191a4481e8376e9f0db6bcf29703cadae6/numpy-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:c7b0be4ef08607dd04da4092faee0b86607f111d5ae68036f16cc787e250a131", size = 15905558 }, - { url = "https://files.pythonhosted.org/packages/8b/cf/034500fb83041aa0286e0fb16e7c76e5c8b67c0711bb6e9e9737a717d5fe/numpy-2.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:49ca4decb342d66018b01932139c0961a8f9ddc7589611158cb3c27cbcf76448", size = 21169137 }, - { url = "https://files.pythonhosted.org/packages/0e/78/a3e4f9fb6aa4e6fdca0c5428e8ba039408514388cf62d89651aade838269/numpy-2.0.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8cafab480740e22f8d833acefed5cc87ce276f4ece12fdaa2e8903db2f82897a", size = 6905573 }, - { url = "https://files.pythonhosted.org/packages/ba/a8/c17acf65a931ce551fee11b72e8de63bf7e8a6f0e21add4c937c83563538/numpy-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13e689d772146140a252c3a28501da66dfecd77490b498b168b501835041f951", size = 19534895 }, - { url = "https://files.pythonhosted.org/packages/ba/86/8767f3d54f6ae0165749f84648da9dcc8cd78ab65d415494962c86fac80f/numpy-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9ea91dfb7c3d1c56a0e55657c0afb38cf1eeae4544c208dc465c3c9f3a7c09f9", size = 19937253 }, - { url = "https://files.pythonhosted.org/packages/eb/57/3a3f14d3a759dcf9bf6e9eda905794726b758819df4663f217d658a58695/numpy-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:286cd40ce2b7d652a6f22efdfc6d1edf879440e53e76a75955bc0c826c7e64dc", size = 15910230 }, - { url = "https://files.pythonhosted.org/packages/45/40/2e117be60ec50d98fa08c2f8c48e09b3edea93cfcabd5a9ff6925d54b1c2/numpy-2.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:df55d490dea7934f330006d0f81e8551ba6010a5bf035a249ef61a94f21c500b", size = 20895803 }, - { url = "https://files.pythonhosted.org/packages/e3/ff/ddf6dac2ff0dd50a7327bcdba45cb0264d0e96bb44d33324853f781a8f3c/numpy-2.0.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:a842d573724391493a97a62ebbb8e731f8a5dcc5d285dfc99141ca15a3302d0c", size = 6633497 }, - { url = "https://files.pythonhosted.org/packages/39/68/e9f1126d757653496dbc096cb429014347a36b228f5a991dae2c6b6cfd40/numpy-2.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0123ffdaa88fa4ab64835dcbde75dcdf89c453c922f18dced6e27c90d1d0ec5a", size = 19236173 }, - { url = "https://files.pythonhosted.org/packages/d1/e9/1f5333281e4ebf483ba1c888b1d61ba7e78d7e910fdd8e6499667041cc35/numpy-2.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:96a55f64139912d61de9137f11bf39a55ec8faec288c75a54f93dfd39f7eb40c", size = 19634174 }, - { url = "https://files.pythonhosted.org/packages/b2/b5/4ac39baebf1fdb2e72585c8352c56d063b6126be9fc95bd2bb5ef5770c20/numpy-2.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:cfd41e13fdc257aa5778496b8caa5e856dc4896d4ccf01841daee1d96465467a", size = 15606179 }, - { url = "https://files.pythonhosted.org/packages/43/c1/41c8f6df3162b0c6ffd4437d729115704bd43363de0090c7f913cfbc2d89/numpy-2.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9059e10581ce4093f735ed23f3b9d283b9d517ff46009ddd485f1747eb22653c", size = 21169942 }, - { url = "https://files.pythonhosted.org/packages/2d/98/121996dcfb10a6087a05e54453e28e58694a7db62c5a5a29cee14c6e047b/numpy-2.0.2-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:97032a27bd9d8988b9a97a8c4d2c9f2c15a81f61e2f21404d7e8ef00cb5be729", size = 6906494 }, - { url = "https://files.pythonhosted.org/packages/b9/14/78635daab4b07c0930c919d451b8bf8c164774e6a3413aed04a6d95758ce/numpy-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b258c385842546006213344c50655ff1555a9338e2e5e02a0756dc3e803dd", size = 19526099 }, - { url = "https://files.pythonhosted.org/packages/26/4c/0eeca4614003077f68bfe7aac8b7496f04221865b3a5e7cb230c9d055afd/numpy-2.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fec9451a7789926bcf7c2b8d187292c9f93ea30284802a0ab3f5be8ab36865d", size = 19932823 }, - { url = "https://files.pythonhosted.org/packages/ea/2b/7fc9f4e7ae5b507c1a3a21f0f15ed03e794c1242ea8a242ac158beb56034/numpy-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:a3f4ab0caa7f053f6797fcd4e1e25caee367db3112ef2b6ef82d749530768c73", size = 15911314 }, - { url = "https://files.pythonhosted.org/packages/8f/3b/df5a870ac6a3be3a86856ce195ef42eec7ae50d2a202be1f5a4b3b340e14/numpy-2.0.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7f0a0c6f12e07fa94133c8a67404322845220c06a9e80e85999afe727f7438b8", size = 21025288 }, - { url = "https://files.pythonhosted.org/packages/2c/97/51af92f18d6f6f2d9ad8b482a99fb74e142d71372da5d834b3a2747a446e/numpy-2.0.2-pp39-pypy39_pp73-macosx_14_0_x86_64.whl", hash = "sha256:312950fdd060354350ed123c0e25a71327d3711584beaef30cdaa93320c392d4", size = 6762793 }, - { url = "https://files.pythonhosted.org/packages/12/46/de1fbd0c1b5ccaa7f9a005b66761533e2f6a3e560096682683a223631fe9/numpy-2.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26df23238872200f63518dd2aa984cfca675d82469535dc7162dc2ee52d9dd5c", size = 19334885 }, - { url = "https://files.pythonhosted.org/packages/cc/dc/d330a6faefd92b446ec0f0dfea4c3207bb1fef3c4771d19cf4543efd2c78/numpy-2.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a46288ec55ebbd58947d31d72be2c63cbf839f0a63b49cb755022310792a3385", size = 15828784 }, +sdist = { url = "https://files.pythonhosted.org/packages/a9/75/10dd1f8116a8b796cb2c737b674e02d02e80454bda953fa7e65d8c12b016/numpy-2.0.2.tar.gz", hash = "sha256:883c987dee1880e2a864ab0dc9892292582510604156762362d9326444636e78", size = 18902015, upload-time = "2024-08-26T20:19:40.945Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/21/91/3495b3237510f79f5d81f2508f9f13fea78ebfdf07538fc7444badda173d/numpy-2.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:51129a29dbe56f9ca83438b706e2e69a39892b5eda6cedcb6b0c9fdc9b0d3ece", size = 21165245, upload-time = "2024-08-26T20:04:14.625Z" }, + { url = "https://files.pythonhosted.org/packages/6e/16/7bfcebf27bb4f9d7ec67332ffebee4d1bf085c84246552d52dbb548600e7/numpy-2.0.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:becfae3ddd30736fe1889a37f1f580e245ba79a5855bff5f2a29cb3ccc22dd7b", size = 6901774, upload-time = "2024-08-26T20:04:58.173Z" }, + { url = "https://files.pythonhosted.org/packages/fa/66/f7177ab331876200ac7563a580140643d1179c8b4b6a6b0fc9838de2a9b8/numpy-2.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:496f71341824ed9f3d2fd36cf3ac57ae2e0165c143b55c3a035ee219413f3318", size = 19523451, upload-time = "2024-08-26T20:05:47.479Z" }, + { url = "https://files.pythonhosted.org/packages/25/7f/0b209498009ad6453e4efc2c65bcdf0ae08a182b2b7877d7ab38a92dc542/numpy-2.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a61ec659f68ae254e4d237816e33171497e978140353c0c2038d46e63282d0c8", size = 19927572, upload-time = "2024-08-26T20:06:17.137Z" }, + { url = "https://files.pythonhosted.org/packages/10/05/3442317535028bc29cf0c0dd4c191a4481e8376e9f0db6bcf29703cadae6/numpy-2.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:c7b0be4ef08607dd04da4092faee0b86607f111d5ae68036f16cc787e250a131", size = 15905558, upload-time = "2024-08-26T20:07:13.881Z" }, + { url = "https://files.pythonhosted.org/packages/8b/cf/034500fb83041aa0286e0fb16e7c76e5c8b67c0711bb6e9e9737a717d5fe/numpy-2.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:49ca4decb342d66018b01932139c0961a8f9ddc7589611158cb3c27cbcf76448", size = 21169137, upload-time = "2024-08-26T20:07:45.345Z" }, + { url = "https://files.pythonhosted.org/packages/0e/78/a3e4f9fb6aa4e6fdca0c5428e8ba039408514388cf62d89651aade838269/numpy-2.0.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8cafab480740e22f8d833acefed5cc87ce276f4ece12fdaa2e8903db2f82897a", size = 6905573, upload-time = "2024-08-26T20:08:27.185Z" }, + { url = "https://files.pythonhosted.org/packages/ba/a8/c17acf65a931ce551fee11b72e8de63bf7e8a6f0e21add4c937c83563538/numpy-2.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13e689d772146140a252c3a28501da66dfecd77490b498b168b501835041f951", size = 19534895, upload-time = "2024-08-26T20:09:16.536Z" }, + { url = "https://files.pythonhosted.org/packages/ba/86/8767f3d54f6ae0165749f84648da9dcc8cd78ab65d415494962c86fac80f/numpy-2.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9ea91dfb7c3d1c56a0e55657c0afb38cf1eeae4544c208dc465c3c9f3a7c09f9", size = 19937253, upload-time = "2024-08-26T20:09:46.263Z" }, + { url = "https://files.pythonhosted.org/packages/eb/57/3a3f14d3a759dcf9bf6e9eda905794726b758819df4663f217d658a58695/numpy-2.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:286cd40ce2b7d652a6f22efdfc6d1edf879440e53e76a75955bc0c826c7e64dc", size = 15910230, upload-time = "2024-08-26T20:10:43.413Z" }, + { url = "https://files.pythonhosted.org/packages/45/40/2e117be60ec50d98fa08c2f8c48e09b3edea93cfcabd5a9ff6925d54b1c2/numpy-2.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:df55d490dea7934f330006d0f81e8551ba6010a5bf035a249ef61a94f21c500b", size = 20895803, upload-time = "2024-08-26T20:11:13.916Z" }, + { url = "https://files.pythonhosted.org/packages/e3/ff/ddf6dac2ff0dd50a7327bcdba45cb0264d0e96bb44d33324853f781a8f3c/numpy-2.0.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:a842d573724391493a97a62ebbb8e731f8a5dcc5d285dfc99141ca15a3302d0c", size = 6633497, upload-time = "2024-08-26T20:11:55.09Z" }, + { url = "https://files.pythonhosted.org/packages/39/68/e9f1126d757653496dbc096cb429014347a36b228f5a991dae2c6b6cfd40/numpy-2.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0123ffdaa88fa4ab64835dcbde75dcdf89c453c922f18dced6e27c90d1d0ec5a", size = 19236173, upload-time = "2024-08-26T20:12:44.049Z" }, + { url = "https://files.pythonhosted.org/packages/d1/e9/1f5333281e4ebf483ba1c888b1d61ba7e78d7e910fdd8e6499667041cc35/numpy-2.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:96a55f64139912d61de9137f11bf39a55ec8faec288c75a54f93dfd39f7eb40c", size = 19634174, upload-time = "2024-08-26T20:13:13.634Z" }, + { url = "https://files.pythonhosted.org/packages/b2/b5/4ac39baebf1fdb2e72585c8352c56d063b6126be9fc95bd2bb5ef5770c20/numpy-2.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:cfd41e13fdc257aa5778496b8caa5e856dc4896d4ccf01841daee1d96465467a", size = 15606179, upload-time = "2024-08-26T20:14:08.786Z" }, + { url = "https://files.pythonhosted.org/packages/43/c1/41c8f6df3162b0c6ffd4437d729115704bd43363de0090c7f913cfbc2d89/numpy-2.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9059e10581ce4093f735ed23f3b9d283b9d517ff46009ddd485f1747eb22653c", size = 21169942, upload-time = "2024-08-26T20:14:40.108Z" }, + { url = "https://files.pythonhosted.org/packages/2d/98/121996dcfb10a6087a05e54453e28e58694a7db62c5a5a29cee14c6e047b/numpy-2.0.2-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:97032a27bd9d8988b9a97a8c4d2c9f2c15a81f61e2f21404d7e8ef00cb5be729", size = 6906494, upload-time = "2024-08-26T20:15:22.055Z" }, + { url = "https://files.pythonhosted.org/packages/b9/14/78635daab4b07c0930c919d451b8bf8c164774e6a3413aed04a6d95758ce/numpy-2.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f26b258c385842546006213344c50655ff1555a9338e2e5e02a0756dc3e803dd", size = 19526099, upload-time = "2024-08-26T20:16:11.048Z" }, + { url = "https://files.pythonhosted.org/packages/26/4c/0eeca4614003077f68bfe7aac8b7496f04221865b3a5e7cb230c9d055afd/numpy-2.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5fec9451a7789926bcf7c2b8d187292c9f93ea30284802a0ab3f5be8ab36865d", size = 19932823, upload-time = "2024-08-26T20:16:40.171Z" }, + { url = "https://files.pythonhosted.org/packages/ea/2b/7fc9f4e7ae5b507c1a3a21f0f15ed03e794c1242ea8a242ac158beb56034/numpy-2.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:a3f4ab0caa7f053f6797fcd4e1e25caee367db3112ef2b6ef82d749530768c73", size = 15911314, upload-time = "2024-08-26T20:17:36.72Z" }, + { url = "https://files.pythonhosted.org/packages/8f/3b/df5a870ac6a3be3a86856ce195ef42eec7ae50d2a202be1f5a4b3b340e14/numpy-2.0.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:7f0a0c6f12e07fa94133c8a67404322845220c06a9e80e85999afe727f7438b8", size = 21025288, upload-time = "2024-08-26T20:18:07.732Z" }, + { url = "https://files.pythonhosted.org/packages/2c/97/51af92f18d6f6f2d9ad8b482a99fb74e142d71372da5d834b3a2747a446e/numpy-2.0.2-pp39-pypy39_pp73-macosx_14_0_x86_64.whl", hash = "sha256:312950fdd060354350ed123c0e25a71327d3711584beaef30cdaa93320c392d4", size = 6762793, upload-time = "2024-08-26T20:18:19.125Z" }, + { url = "https://files.pythonhosted.org/packages/12/46/de1fbd0c1b5ccaa7f9a005b66761533e2f6a3e560096682683a223631fe9/numpy-2.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26df23238872200f63518dd2aa984cfca675d82469535dc7162dc2ee52d9dd5c", size = 19334885, upload-time = "2024-08-26T20:18:47.237Z" }, + { url = "https://files.pythonhosted.org/packages/cc/dc/d330a6faefd92b446ec0f0dfea4c3207bb1fef3c4771d19cf4543efd2c78/numpy-2.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a46288ec55ebbd58947d31d72be2c63cbf839f0a63b49cb755022310792a3385", size = 15828784, upload-time = "2024-08-26T20:19:11.19Z" }, ] [[package]] @@ -441,50 +443,50 @@ name = "numpy" version = "2.2.2" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "(python_full_version >= '3.12' and implementation_name != 'cpython') or (python_full_version == '3.12.*' and implementation_name == 'cpython') or (python_full_version >= '3.14' and implementation_name == 'cpython')", + "(python_full_version >= '3.12' and implementation_name != 'cpython') or (python_full_version == '3.12.*' and implementation_name == 'cpython') or (python_full_version >= '3.15' and implementation_name == 'cpython')", "python_full_version == '3.11.*'", "python_full_version == '3.10.*'", ] -sdist = { url = "https://files.pythonhosted.org/packages/ec/d0/c12ddfd3a02274be06ffc71f3efc6d0e457b0409c4481596881e748cb264/numpy-2.2.2.tar.gz", hash = "sha256:ed6906f61834d687738d25988ae117683705636936cc605be0bb208b23df4d8f", size = 20233295 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/70/2a/69033dc22d981ad21325314f8357438078f5c28310a6d89fb3833030ec8a/numpy-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7079129b64cb78bdc8d611d1fd7e8002c0a2565da6a47c4df8062349fee90e3e", size = 21215825 }, - { url = "https://files.pythonhosted.org/packages/7f/f4/3d8a5a0da297034106c5de92be881aca7079cde6058934215a1de91334f6/numpy-2.2.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:995f9e8181723852ca458e22de5d9b7d3ba4da3f11cc1cb113f093b271d7965a", size = 6928931 }, - { url = "https://files.pythonhosted.org/packages/e3/d7/11fc594838d35c43519763310c316d4fd56f8600d3fc80a8e13e325b5c5c/numpy-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fbe72d347fbc59f94124125e73fc4976a06927ebc503ec5afbfb35f193cd957", size = 16381794 }, - { url = "https://files.pythonhosted.org/packages/30/97/ab96b7650f27f684a9b1e46757a7294ecc50cab27701d05f146e9f779627/numpy-2.2.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:09d6a2032faf25e8d0cadde7fd6145118ac55d2740132c1d845f98721b5ebcfd", size = 18170896 }, - { url = "https://files.pythonhosted.org/packages/92/9b/95678092febd14070cfb7906ea7932e71e9dd5a6ab3ee948f9ed975e905d/numpy-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:64bd6e1762cd7f0986a740fee4dff927b9ec2c5e4d9a28d056eb17d332158014", size = 12915812 }, - { url = "https://files.pythonhosted.org/packages/21/67/32c68756eed84df181c06528ff57e09138f893c4653448c4967311e0f992/numpy-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:642199e98af1bd2b6aeb8ecf726972d238c9877b0f6e8221ee5ab945ec8a2189", size = 21220002 }, - { url = "https://files.pythonhosted.org/packages/47/e2/fccf89d64d9b47ffb242823d4e851fc9d36fa751908c9aac2807924d9b4e/numpy-2.2.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:451e854cfae0febe723077bd0cf0a4302a5d84ff25f0bfece8f29206c7bed02e", size = 6933133 }, - { url = "https://files.pythonhosted.org/packages/5b/86/caec78829311f62afa6fa334c8dfcd79cffb4d24bcf96ee02ae4840d462b/numpy-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02935e2c3c0c6cbe9c7955a8efa8908dd4221d7755644c59d1bba28b94fd334f", size = 16393429 }, - { url = "https://files.pythonhosted.org/packages/d4/bd/d557f10fa50dc4d5871fb9606af563249b66af2fc6f99041a10e8757c6f1/numpy-2.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d6d6a0910c3b4368d89dde073e630882cdb266755565155bc33520283b2d9df8", size = 18182967 }, - { url = "https://files.pythonhosted.org/packages/66/a3/4139296b481ae7304a43581046b8f0a20da6a0dfe0ee47a044cade796603/numpy-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:da1eeb460ecce8d5b8608826595c777728cdf28ce7b5a5a8c8ac8d949beadcf2", size = 12919805 }, - { url = "https://files.pythonhosted.org/packages/0c/e6/847d15770ab7a01e807bdfcd4ead5bdae57c0092b7dc83878171b6af97bb/numpy-2.2.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ac9bea18d6d58a995fac1b2cb4488e17eceeac413af014b1dd26170b766d8467", size = 20912636 }, - { url = "https://files.pythonhosted.org/packages/7a/1b/50985edb6f1ec495a1c36452e860476f5b7ecdc3fc59ea89ccad3c4926c5/numpy-2.2.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:8ec0636d3f7d68520afc6ac2dc4b8341ddb725039de042faf0e311599f54eb37", size = 6661937 }, - { url = "https://files.pythonhosted.org/packages/5b/73/65d2f0b698df1731e851e3295eb29a5ab8aa06f763f7e4188647a809578d/numpy-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0349b025e15ea9d05c3d63f9657707a4e1d471128a3b1d876c095f328f8ff7f0", size = 16099146 }, - { url = "https://files.pythonhosted.org/packages/f0/d8/d8d333ad0d8518d077a21aeea7b7c826eff766a2b1ce1194dea95ca0bacf/numpy-2.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9dd47ff0cb2a656ad69c38da850df3454da88ee9a6fde0ba79acceee0e79daba", size = 17863507 }, - { url = "https://files.pythonhosted.org/packages/fc/84/7f801a42a67b9772a883223a0a1e12069a14626c81a732bd70aac57aebc1/numpy-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:5acea83b801e98541619af398cc0109ff48016955cc0818f478ee9ef1c5c3dcb", size = 12616372 }, - { url = "https://files.pythonhosted.org/packages/e1/fe/df5624001f4f5c3e0b78e9017bfab7fdc18a8d3b3d3161da3d64924dd659/numpy-2.2.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b208cfd4f5fe34e1535c08983a1a6803fdbc7a1e86cf13dd0c61de0b51a0aadc", size = 20899188 }, - { url = "https://files.pythonhosted.org/packages/8d/f3/399c15629d5a0c68ef2aa7621d430b2be22034f01dd7f3c65a9c9666c445/numpy-2.2.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:128c41c085cab8a85dc29e66ed88c05613dccf6bc28b3866cd16050a2f5448be", size = 6648426 }, - { url = "https://files.pythonhosted.org/packages/83/9c/96a9ab62274ffafb023f8ee08c88d3d31ee74ca58869f859db6845494fa6/numpy-2.2.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0c8854b09bc4de7b041148d8550d3bd712b5c21ff6a8ed308085f190235d7ff", size = 16096614 }, - { url = "https://files.pythonhosted.org/packages/5e/6d/541717a554a8f56fa75e91886d9b79ade2e595918690eb5d0d3dbd3accb9/numpy-2.2.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:57b4012e04cc12b78590a334907e01b3a85efb2107df2b8733ff1ed05fce71de", size = 17859160 }, - { url = "https://files.pythonhosted.org/packages/56/e5/01106b9291ef1d680f82bc47d0c5b5e26dfed15b0754928e8f856c82c881/numpy-2.2.2-cp313-cp313-win_amd64.whl", hash = "sha256:5a8c863ceacae696aff37d1fd636121f1a512117652e5dfb86031c8d84836369", size = 12609010 }, - { url = "https://files.pythonhosted.org/packages/9f/30/f23d9876de0f08dceb707c4dcf7f8dd7588266745029debb12a3cdd40be6/numpy-2.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b3482cb7b3325faa5f6bc179649406058253d91ceda359c104dac0ad320e1391", size = 20924451 }, - { url = "https://files.pythonhosted.org/packages/f7/ec/fe2e91b2642b9d6544518388a441bcd65c904cea38d9ff998e2e8ebf808e/numpy-2.2.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:7dca87ca328f5ea7dafc907c5ec100d187911f94825f8700caac0b3f4c384b49", size = 6671958 }, - { url = "https://files.pythonhosted.org/packages/e1/fb/13c58591d0b6294a08cc40fcc6b9552d239d773d520858ae27f39997f2ae/numpy-2.2.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fad446ad0bc886855ddf5909cbf8cb5d0faa637aaa6277fb4b19ade134ab3c7", size = 16079759 }, - { url = "https://files.pythonhosted.org/packages/aa/29/14a177f1a90b8ad8a592ca32124ac06af5eff32889874e53a308f850290f/numpy-2.2.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:106397dbbb1896f99e044efc90360d098b3335060375c26aa89c0d8a97c5f648", size = 17856316 }, - { url = "https://files.pythonhosted.org/packages/80/94/cd9e9b04012c015cb6320ab3bf43bc615e248dddfeb163728e800a5d96f0/numpy-2.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:97b974d3ba0fb4612b77ed35d7627490e8e3dff56ab41454d9e8b23448940576", size = 12696208 }, - { url = "https://files.pythonhosted.org/packages/96/7e/1dd770ee68916ed358991ab62c2cc353ffd98d0b75b901d52183ca28e8bb/numpy-2.2.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b0531f0b0e07643eb089df4c509d30d72c9ef40defa53e41363eca8a8cc61495", size = 21047291 }, - { url = "https://files.pythonhosted.org/packages/d1/3c/ccd08578dc532a8e6927952339d4a02682b776d5e85be49ed0760308433e/numpy-2.2.2-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:e9e82dcb3f2ebbc8cb5ce1102d5f1c5ed236bf8a11730fb45ba82e2841ec21df", size = 6792494 }, - { url = "https://files.pythonhosted.org/packages/7c/28/8754b9aee4f97199f9a047f73bb644b5a2014994a6d7b061ba67134a42de/numpy-2.2.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0d4142eb40ca6f94539e4db929410f2a46052a0fe7a2c1c59f6179c39938d2a", size = 16197312 }, - { url = "https://files.pythonhosted.org/packages/26/96/deb93f871f401045a684ca08a009382b247d14996d7a94fea6aa43c67b94/numpy-2.2.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:356ca982c188acbfa6af0d694284d8cf20e95b1c3d0aefa8929376fea9146f60", size = 12822674 }, +sdist = { url = "https://files.pythonhosted.org/packages/ec/d0/c12ddfd3a02274be06ffc71f3efc6d0e457b0409c4481596881e748cb264/numpy-2.2.2.tar.gz", hash = "sha256:ed6906f61834d687738d25988ae117683705636936cc605be0bb208b23df4d8f", size = 20233295, upload-time = "2025-01-19T00:02:09.581Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/70/2a/69033dc22d981ad21325314f8357438078f5c28310a6d89fb3833030ec8a/numpy-2.2.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7079129b64cb78bdc8d611d1fd7e8002c0a2565da6a47c4df8062349fee90e3e", size = 21215825, upload-time = "2025-01-18T22:56:28.939Z" }, + { url = "https://files.pythonhosted.org/packages/7f/f4/3d8a5a0da297034106c5de92be881aca7079cde6058934215a1de91334f6/numpy-2.2.2-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:995f9e8181723852ca458e22de5d9b7d3ba4da3f11cc1cb113f093b271d7965a", size = 6928931, upload-time = "2025-01-18T22:57:21.24Z" }, + { url = "https://files.pythonhosted.org/packages/e3/d7/11fc594838d35c43519763310c316d4fd56f8600d3fc80a8e13e325b5c5c/numpy-2.2.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3fbe72d347fbc59f94124125e73fc4976a06927ebc503ec5afbfb35f193cd957", size = 16381794, upload-time = "2025-01-18T22:58:20.094Z" }, + { url = "https://files.pythonhosted.org/packages/30/97/ab96b7650f27f684a9b1e46757a7294ecc50cab27701d05f146e9f779627/numpy-2.2.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:09d6a2032faf25e8d0cadde7fd6145118ac55d2740132c1d845f98721b5ebcfd", size = 18170896, upload-time = "2025-01-18T22:59:18.84Z" }, + { url = "https://files.pythonhosted.org/packages/92/9b/95678092febd14070cfb7906ea7932e71e9dd5a6ab3ee948f9ed975e905d/numpy-2.2.2-cp310-cp310-win_amd64.whl", hash = "sha256:64bd6e1762cd7f0986a740fee4dff927b9ec2c5e4d9a28d056eb17d332158014", size = 12915812, upload-time = "2025-01-18T22:59:59.335Z" }, + { url = "https://files.pythonhosted.org/packages/21/67/32c68756eed84df181c06528ff57e09138f893c4653448c4967311e0f992/numpy-2.2.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:642199e98af1bd2b6aeb8ecf726972d238c9877b0f6e8221ee5ab945ec8a2189", size = 21220002, upload-time = "2025-01-18T23:00:41.728Z" }, + { url = "https://files.pythonhosted.org/packages/47/e2/fccf89d64d9b47ffb242823d4e851fc9d36fa751908c9aac2807924d9b4e/numpy-2.2.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:451e854cfae0febe723077bd0cf0a4302a5d84ff25f0bfece8f29206c7bed02e", size = 6933133, upload-time = "2025-01-18T23:01:53.087Z" }, + { url = "https://files.pythonhosted.org/packages/5b/86/caec78829311f62afa6fa334c8dfcd79cffb4d24bcf96ee02ae4840d462b/numpy-2.2.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02935e2c3c0c6cbe9c7955a8efa8908dd4221d7755644c59d1bba28b94fd334f", size = 16393429, upload-time = "2025-01-18T23:03:00.683Z" }, + { url = "https://files.pythonhosted.org/packages/d4/bd/d557f10fa50dc4d5871fb9606af563249b66af2fc6f99041a10e8757c6f1/numpy-2.2.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d6d6a0910c3b4368d89dde073e630882cdb266755565155bc33520283b2d9df8", size = 18182967, upload-time = "2025-01-18T23:22:14.371Z" }, + { url = "https://files.pythonhosted.org/packages/66/a3/4139296b481ae7304a43581046b8f0a20da6a0dfe0ee47a044cade796603/numpy-2.2.2-cp311-cp311-win_amd64.whl", hash = "sha256:da1eeb460ecce8d5b8608826595c777728cdf28ce7b5a5a8c8ac8d949beadcf2", size = 12919805, upload-time = "2025-01-18T23:22:56.851Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e6/847d15770ab7a01e807bdfcd4ead5bdae57c0092b7dc83878171b6af97bb/numpy-2.2.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ac9bea18d6d58a995fac1b2cb4488e17eceeac413af014b1dd26170b766d8467", size = 20912636, upload-time = "2025-01-18T23:23:58.337Z" }, + { url = "https://files.pythonhosted.org/packages/7a/1b/50985edb6f1ec495a1c36452e860476f5b7ecdc3fc59ea89ccad3c4926c5/numpy-2.2.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:8ec0636d3f7d68520afc6ac2dc4b8341ddb725039de042faf0e311599f54eb37", size = 6661937, upload-time = "2025-01-18T23:26:05.86Z" }, + { url = "https://files.pythonhosted.org/packages/5b/73/65d2f0b698df1731e851e3295eb29a5ab8aa06f763f7e4188647a809578d/numpy-2.2.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0349b025e15ea9d05c3d63f9657707a4e1d471128a3b1d876c095f328f8ff7f0", size = 16099146, upload-time = "2025-01-18T23:27:15.132Z" }, + { url = "https://files.pythonhosted.org/packages/f0/d8/d8d333ad0d8518d077a21aeea7b7c826eff766a2b1ce1194dea95ca0bacf/numpy-2.2.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9dd47ff0cb2a656ad69c38da850df3454da88ee9a6fde0ba79acceee0e79daba", size = 17863507, upload-time = "2025-01-18T23:28:56.146Z" }, + { url = "https://files.pythonhosted.org/packages/fc/84/7f801a42a67b9772a883223a0a1e12069a14626c81a732bd70aac57aebc1/numpy-2.2.2-cp312-cp312-win_amd64.whl", hash = "sha256:5acea83b801e98541619af398cc0109ff48016955cc0818f478ee9ef1c5c3dcb", size = 12616372, upload-time = "2025-01-18T23:29:46.645Z" }, + { url = "https://files.pythonhosted.org/packages/e1/fe/df5624001f4f5c3e0b78e9017bfab7fdc18a8d3b3d3161da3d64924dd659/numpy-2.2.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b208cfd4f5fe34e1535c08983a1a6803fdbc7a1e86cf13dd0c61de0b51a0aadc", size = 20899188, upload-time = "2025-01-18T23:31:15.292Z" }, + { url = "https://files.pythonhosted.org/packages/8d/f3/399c15629d5a0c68ef2aa7621d430b2be22034f01dd7f3c65a9c9666c445/numpy-2.2.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:128c41c085cab8a85dc29e66ed88c05613dccf6bc28b3866cd16050a2f5448be", size = 6648426, upload-time = "2025-01-18T23:32:06.055Z" }, + { url = "https://files.pythonhosted.org/packages/83/9c/96a9ab62274ffafb023f8ee08c88d3d31ee74ca58869f859db6845494fa6/numpy-2.2.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0c8854b09bc4de7b041148d8550d3bd712b5c21ff6a8ed308085f190235d7ff", size = 16096614, upload-time = "2025-01-18T23:33:12.265Z" }, + { url = "https://files.pythonhosted.org/packages/5e/6d/541717a554a8f56fa75e91886d9b79ade2e595918690eb5d0d3dbd3accb9/numpy-2.2.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:57b4012e04cc12b78590a334907e01b3a85efb2107df2b8733ff1ed05fce71de", size = 17859160, upload-time = "2025-01-18T23:34:37.857Z" }, + { url = "https://files.pythonhosted.org/packages/56/e5/01106b9291ef1d680f82bc47d0c5b5e26dfed15b0754928e8f856c82c881/numpy-2.2.2-cp313-cp313-win_amd64.whl", hash = "sha256:5a8c863ceacae696aff37d1fd636121f1a512117652e5dfb86031c8d84836369", size = 12609010, upload-time = "2025-01-18T23:40:31.34Z" }, + { url = "https://files.pythonhosted.org/packages/9f/30/f23d9876de0f08dceb707c4dcf7f8dd7588266745029debb12a3cdd40be6/numpy-2.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:b3482cb7b3325faa5f6bc179649406058253d91ceda359c104dac0ad320e1391", size = 20924451, upload-time = "2025-01-18T23:35:26.639Z" }, + { url = "https://files.pythonhosted.org/packages/f7/ec/fe2e91b2642b9d6544518388a441bcd65c904cea38d9ff998e2e8ebf808e/numpy-2.2.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:7dca87ca328f5ea7dafc907c5ec100d187911f94825f8700caac0b3f4c384b49", size = 6671958, upload-time = "2025-01-18T23:37:05.361Z" }, + { url = "https://files.pythonhosted.org/packages/e1/fb/13c58591d0b6294a08cc40fcc6b9552d239d773d520858ae27f39997f2ae/numpy-2.2.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fad446ad0bc886855ddf5909cbf8cb5d0faa637aaa6277fb4b19ade134ab3c7", size = 16079759, upload-time = "2025-01-18T23:38:05.757Z" }, + { url = "https://files.pythonhosted.org/packages/aa/29/14a177f1a90b8ad8a592ca32124ac06af5eff32889874e53a308f850290f/numpy-2.2.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:106397dbbb1896f99e044efc90360d098b3335060375c26aa89c0d8a97c5f648", size = 17856316, upload-time = "2025-01-18T23:39:11.454Z" }, + { url = "https://files.pythonhosted.org/packages/80/94/cd9e9b04012c015cb6320ab3bf43bc615e248dddfeb163728e800a5d96f0/numpy-2.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:97b974d3ba0fb4612b77ed35d7627490e8e3dff56ab41454d9e8b23448940576", size = 12696208, upload-time = "2025-01-18T23:39:51.85Z" }, + { url = "https://files.pythonhosted.org/packages/96/7e/1dd770ee68916ed358991ab62c2cc353ffd98d0b75b901d52183ca28e8bb/numpy-2.2.2-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b0531f0b0e07643eb089df4c509d30d72c9ef40defa53e41363eca8a8cc61495", size = 21047291, upload-time = "2025-01-18T23:41:14.547Z" }, + { url = "https://files.pythonhosted.org/packages/d1/3c/ccd08578dc532a8e6927952339d4a02682b776d5e85be49ed0760308433e/numpy-2.2.2-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:e9e82dcb3f2ebbc8cb5ce1102d5f1c5ed236bf8a11730fb45ba82e2841ec21df", size = 6792494, upload-time = "2025-01-18T23:41:34.66Z" }, + { url = "https://files.pythonhosted.org/packages/7c/28/8754b9aee4f97199f9a047f73bb644b5a2014994a6d7b061ba67134a42de/numpy-2.2.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0d4142eb40ca6f94539e4db929410f2a46052a0fe7a2c1c59f6179c39938d2a", size = 16197312, upload-time = "2025-01-18T23:42:26.273Z" }, + { url = "https://files.pythonhosted.org/packages/26/96/deb93f871f401045a684ca08a009382b247d14996d7a94fea6aa43c67b94/numpy-2.2.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:356ca982c188acbfa6af0d694284d8cf20e95b1c3d0aefa8929376fea9146f60", size = 12822674, upload-time = "2025-01-18T23:42:53.292Z" }, ] [[package]] name = "packaging" version = "24.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } +sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950, upload-time = "2024-11-08T09:47:47.202Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, + { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451, upload-time = "2024-11-08T09:47:44.722Z" }, ] [[package]] @@ -493,72 +495,72 @@ version = "2.2.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "numpy", version = "2.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, - { name = "numpy", version = "2.2.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.10' and python_full_version < '3.13') or (python_full_version >= '3.10' and implementation_name != 'cpython') or (python_full_version >= '3.14' and implementation_name == 'cpython')" }, - { name = "python-dateutil", marker = "python_full_version != '3.13.*' or implementation_name != 'cpython'" }, - { name = "pytz", marker = "python_full_version != '3.13.*' or implementation_name != 'cpython'" }, - { name = "tzdata", marker = "python_full_version != '3.13.*' or implementation_name != 'cpython'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9c/d6/9f8431bacc2e19dca897724cd097b1bb224a6ad5433784a44b587c7c13af/pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", size = 4399213 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/aa/70/c853aec59839bceed032d52010ff5f1b8d87dc3114b762e4ba2727661a3b/pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5", size = 12580827 }, - { url = "https://files.pythonhosted.org/packages/44/50/7db2cd5e6373ae796f0ddad3675268c8d59fb6076e66f0c339d61cea886b/pandas-2.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57", size = 13064210 }, - { url = "https://files.pythonhosted.org/packages/ce/0d/4cc7b69ce37fac07645a94e1d4b0880b15999494372c1523508511b09e40/pandas-2.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f", size = 14416379 }, - { url = "https://files.pythonhosted.org/packages/31/9e/6ebb433de864a6cd45716af52a4d7a8c3c9aaf3a98368e61db9e69e69a9c/pandas-2.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645", size = 11598471 }, - { url = "https://files.pythonhosted.org/packages/a8/44/d9502bf0ed197ba9bf1103c9867d5904ddcaf869e52329787fc54ed70cc8/pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039", size = 12602222 }, - { url = "https://files.pythonhosted.org/packages/cd/5f/4dba1d39bb9c38d574a9a22548c540177f78ea47b32f99c0ff2ec499fac5/pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc", size = 13058505 }, - { url = "https://files.pythonhosted.org/packages/86/4a/03ed6b7ee323cf30404265c284cee9c65c56a212e0a08d9ee06984ba2240/pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32", size = 14440457 }, - { url = "https://files.pythonhosted.org/packages/ed/8c/87ddf1fcb55d11f9f847e3c69bb1c6f8e46e2f40ab1a2d2abadb2401b007/pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5", size = 11617166 }, - { url = "https://files.pythonhosted.org/packages/17/a3/fb2734118db0af37ea7433f57f722c0a56687e14b14690edff0cdb4b7e58/pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9", size = 12529893 }, - { url = "https://files.pythonhosted.org/packages/38/f8/d8fddee9ed0d0c0f4a2132c1dfcf0e3e53265055da8df952a53e7eaf178c/pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319", size = 12739445 }, - { url = "https://files.pythonhosted.org/packages/1d/99/617d07a6a5e429ff90c90da64d428516605a1ec7d7bea494235e1c3882de/pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a", size = 14056756 }, - { url = "https://files.pythonhosted.org/packages/29/d4/1244ab8edf173a10fd601f7e13b9566c1b525c4f365d6bee918e68381889/pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13", size = 11504248 }, - { url = "https://files.pythonhosted.org/packages/64/22/3b8f4e0ed70644e85cfdcd57454686b9057c6c38d2f74fe4b8bc2527214a/pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015", size = 12477643 }, - { url = "https://files.pythonhosted.org/packages/e8/31/aa8da88ca0eadbabd0a639788a6da13bb2ff6edbbb9f29aa786450a30a91/pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24", size = 12711809 }, - { url = "https://files.pythonhosted.org/packages/57/b7/8b757e7d92023b832869fa8881a992696a0bfe2e26f72c9ae9f255988d42/pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb", size = 14022055 }, - { url = "https://files.pythonhosted.org/packages/3b/bc/4b18e2b8c002572c5a441a64826252ce5da2aa738855747247a971988043/pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d", size = 11481175 }, - { url = "https://files.pythonhosted.org/packages/76/a3/a5d88146815e972d40d19247b2c162e88213ef51c7c25993942c39dbf41d/pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468", size = 12615650 }, - { url = "https://files.pythonhosted.org/packages/25/b0/98d6ae2e1abac4f35230aa756005e8654649d305df9a28b16b9ae4353bff/pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4", size = 11871013 }, - { url = "https://files.pythonhosted.org/packages/ab/5f/b38085618b950b79d2d9164a711c52b10aefc0ae6833b96f626b7021b2ed/pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a", size = 13098436 }, - { url = "https://files.pythonhosted.org/packages/ca/8c/8848a4c9b8fdf5a534fe2077af948bf53cd713d77ffbcd7bd15710348fd7/pandas-2.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc6b93f9b966093cb0fd62ff1a7e4c09e6d546ad7c1de191767baffc57628f39", size = 12595535 }, - { url = "https://files.pythonhosted.org/packages/3d/dd/bed19c2974296661493d7acc4407b1d2db4e2a482197df100f8f965b6225/pandas-2.2.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99df71520d25fade9db7c1076ac94eb994f4d2673ef2aa2e86ee039b6746d20c", size = 13068928 }, - { url = "https://files.pythonhosted.org/packages/c4/a5/3429bd13d82bebc78f4d78c3945efedef63a7cd0c15c17b2eeb838d1121f/pandas-2.2.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7eee9e7cea6adf3e3d24e304ac6b8300646e2a5d1cd3a3c2abed9101b0846761", size = 14450871 }, - { url = "https://files.pythonhosted.org/packages/2f/49/5c30646e96c684570925b772eac4eb0a8cb0ca590fa978f56c5d3ae73ea1/pandas-2.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e", size = 11618011 }, + { name = "numpy", version = "2.2.2", source = { registry = "https://pypi.org/simple" }, marker = "(python_full_version >= '3.10' and python_full_version < '3.13') or (python_full_version >= '3.10' and implementation_name != 'cpython') or (python_full_version >= '3.15' and implementation_name == 'cpython')" }, + { name = "python-dateutil", marker = "python_full_version < '3.13' or python_full_version >= '3.15' or implementation_name != 'cpython'" }, + { name = "pytz", marker = "python_full_version < '3.13' or python_full_version >= '3.15' or implementation_name != 'cpython'" }, + { name = "tzdata", marker = "python_full_version < '3.13' or python_full_version >= '3.15' or implementation_name != 'cpython'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9c/d6/9f8431bacc2e19dca897724cd097b1bb224a6ad5433784a44b587c7c13af/pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", size = 4399213, upload-time = "2024-09-20T13:10:04.827Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/aa/70/c853aec59839bceed032d52010ff5f1b8d87dc3114b762e4ba2727661a3b/pandas-2.2.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1948ddde24197a0f7add2bdc4ca83bf2b1ef84a1bc8ccffd95eda17fd836ecb5", size = 12580827, upload-time = "2024-09-20T13:08:42.347Z" }, + { url = "https://files.pythonhosted.org/packages/44/50/7db2cd5e6373ae796f0ddad3675268c8d59fb6076e66f0c339d61cea886b/pandas-2.2.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:86976a1c5b25ae3f8ccae3a5306e443569ee3c3faf444dfd0f41cda24667ad57", size = 13064210, upload-time = "2024-09-20T13:08:48.325Z" }, + { url = "https://files.pythonhosted.org/packages/ce/0d/4cc7b69ce37fac07645a94e1d4b0880b15999494372c1523508511b09e40/pandas-2.2.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:37e0aced3e8f539eccf2e099f65cdb9c8aa85109b0be6e93e2baff94264bdc6f", size = 14416379, upload-time = "2024-09-20T13:08:50.882Z" }, + { url = "https://files.pythonhosted.org/packages/31/9e/6ebb433de864a6cd45716af52a4d7a8c3c9aaf3a98368e61db9e69e69a9c/pandas-2.2.3-cp310-cp310-win_amd64.whl", hash = "sha256:56534ce0746a58afaf7942ba4863e0ef81c9c50d3f0ae93e9497d6a41a057645", size = 11598471, upload-time = "2024-09-20T13:08:53.332Z" }, + { url = "https://files.pythonhosted.org/packages/a8/44/d9502bf0ed197ba9bf1103c9867d5904ddcaf869e52329787fc54ed70cc8/pandas-2.2.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:66108071e1b935240e74525006034333f98bcdb87ea116de573a6a0dccb6c039", size = 12602222, upload-time = "2024-09-20T13:08:56.254Z" }, + { url = "https://files.pythonhosted.org/packages/cd/5f/4dba1d39bb9c38d574a9a22548c540177f78ea47b32f99c0ff2ec499fac5/pandas-2.2.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c124333816c3a9b03fbeef3a9f230ba9a737e9e5bb4060aa2107a86cc0a497fc", size = 13058505, upload-time = "2024-09-20T13:09:01.501Z" }, + { url = "https://files.pythonhosted.org/packages/86/4a/03ed6b7ee323cf30404265c284cee9c65c56a212e0a08d9ee06984ba2240/pandas-2.2.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:29401dbfa9ad77319367d36940cd8a0b3a11aba16063e39632d98b0e931ddf32", size = 14440457, upload-time = "2024-09-20T13:09:04.105Z" }, + { url = "https://files.pythonhosted.org/packages/ed/8c/87ddf1fcb55d11f9f847e3c69bb1c6f8e46e2f40ab1a2d2abadb2401b007/pandas-2.2.3-cp311-cp311-win_amd64.whl", hash = "sha256:3fc6873a41186404dad67245896a6e440baacc92f5b716ccd1bc9ed2995ab2c5", size = 11617166, upload-time = "2024-09-20T13:09:06.917Z" }, + { url = "https://files.pythonhosted.org/packages/17/a3/fb2734118db0af37ea7433f57f722c0a56687e14b14690edff0cdb4b7e58/pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9", size = 12529893, upload-time = "2024-09-20T13:09:09.655Z" }, + { url = "https://files.pythonhosted.org/packages/38/f8/d8fddee9ed0d0c0f4a2132c1dfcf0e3e53265055da8df952a53e7eaf178c/pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319", size = 12739445, upload-time = "2024-09-20T13:09:17.621Z" }, + { url = "https://files.pythonhosted.org/packages/1d/99/617d07a6a5e429ff90c90da64d428516605a1ec7d7bea494235e1c3882de/pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a", size = 14056756, upload-time = "2024-09-20T13:09:20.474Z" }, + { url = "https://files.pythonhosted.org/packages/29/d4/1244ab8edf173a10fd601f7e13b9566c1b525c4f365d6bee918e68381889/pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13", size = 11504248, upload-time = "2024-09-20T13:09:23.137Z" }, + { url = "https://files.pythonhosted.org/packages/64/22/3b8f4e0ed70644e85cfdcd57454686b9057c6c38d2f74fe4b8bc2527214a/pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015", size = 12477643, upload-time = "2024-09-20T13:09:25.522Z" }, + { url = "https://files.pythonhosted.org/packages/e8/31/aa8da88ca0eadbabd0a639788a6da13bb2ff6edbbb9f29aa786450a30a91/pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24", size = 12711809, upload-time = "2024-09-20T13:09:30.814Z" }, + { url = "https://files.pythonhosted.org/packages/57/b7/8b757e7d92023b832869fa8881a992696a0bfe2e26f72c9ae9f255988d42/pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb", size = 14022055, upload-time = "2024-09-20T13:09:33.462Z" }, + { url = "https://files.pythonhosted.org/packages/3b/bc/4b18e2b8c002572c5a441a64826252ce5da2aa738855747247a971988043/pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d", size = 11481175, upload-time = "2024-09-20T13:09:35.871Z" }, + { url = "https://files.pythonhosted.org/packages/76/a3/a5d88146815e972d40d19247b2c162e88213ef51c7c25993942c39dbf41d/pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468", size = 12615650, upload-time = "2024-09-20T13:09:38.685Z" }, + { url = "https://files.pythonhosted.org/packages/25/b0/98d6ae2e1abac4f35230aa756005e8654649d305df9a28b16b9ae4353bff/pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4", size = 11871013, upload-time = "2024-09-20T13:09:44.39Z" }, + { url = "https://files.pythonhosted.org/packages/ab/5f/b38085618b950b79d2d9164a711c52b10aefc0ae6833b96f626b7021b2ed/pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a", size = 13098436, upload-time = "2024-09-20T13:09:48.112Z" }, + { url = "https://files.pythonhosted.org/packages/ca/8c/8848a4c9b8fdf5a534fe2077af948bf53cd713d77ffbcd7bd15710348fd7/pandas-2.2.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc6b93f9b966093cb0fd62ff1a7e4c09e6d546ad7c1de191767baffc57628f39", size = 12595535, upload-time = "2024-09-20T13:09:51.339Z" }, + { url = "https://files.pythonhosted.org/packages/3d/dd/bed19c2974296661493d7acc4407b1d2db4e2a482197df100f8f965b6225/pandas-2.2.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99df71520d25fade9db7c1076ac94eb994f4d2673ef2aa2e86ee039b6746d20c", size = 13068928, upload-time = "2024-09-20T13:09:56.746Z" }, + { url = "https://files.pythonhosted.org/packages/c4/a5/3429bd13d82bebc78f4d78c3945efedef63a7cd0c15c17b2eeb838d1121f/pandas-2.2.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:7eee9e7cea6adf3e3d24e304ac6b8300646e2a5d1cd3a3c2abed9101b0846761", size = 14450871, upload-time = "2024-09-20T13:09:59.779Z" }, + { url = "https://files.pythonhosted.org/packages/2f/49/5c30646e96c684570925b772eac4eb0a8cb0ca590fa978f56c5d3ae73ea1/pandas-2.2.3-cp39-cp39-win_amd64.whl", hash = "sha256:4850ba03528b6dd51d6c5d273c46f183f39a9baf3f0143e566b89450965b105e", size = 11618011, upload-time = "2024-09-20T13:10:02.351Z" }, ] [[package]] name = "pathspec" version = "0.12.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043 } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191 }, + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, ] [[package]] name = "platformdirs" version = "4.3.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 } +sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302, upload-time = "2024-09-17T19:06:50.688Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 }, + { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439, upload-time = "2024-09-17T19:06:49.212Z" }, ] [[package]] name = "pluggy" version = "1.5.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955 } +sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955, upload-time = "2024-04-20T21:34:42.531Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 }, + { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556, upload-time = "2024-04-20T21:34:40.434Z" }, ] [[package]] name = "pycparser" version = "2.22" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736 } +sdist = { url = "https://files.pythonhosted.org/packages/1d/b2/31537cf4b1ca988837256c910a668b553fceb8f069bedc4b1c826024b52c/pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", size = 172736, upload-time = "2024-03-30T13:22:22.564Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552 }, + { url = "https://files.pythonhosted.org/packages/13/a3/a812df4e2dd5696d1f351d58b8fe16a405b234ad2886a0dab9183fb78109/pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc", size = 117552, upload-time = "2024-03-30T13:22:20.476Z" }, ] [[package]] @@ -591,7 +593,7 @@ all = [ { name = "pytest-timeout" }, { name = "python-dateutil" }, { name = "ruff" }, - { name = "typing-extensions" }, + { name = "typing-inspection" }, { name = "tzdata" }, ] codspeed = [ @@ -625,21 +627,19 @@ testing = [ { name = "pytest-speed" }, { name = "pytest-timeout" }, { name = "python-dateutil" }, - { name = "typing-extensions" }, + { name = "typing-inspection" }, { name = "tzdata" }, ] wasm = [ { name = "maturin" }, { name = "ruff" }, - { name = "typing-extensions" }, ] [package.metadata] -requires-dist = [{ name = "typing-extensions", specifier = ">=4.6.0,!=4.7.0" }] +requires-dist = [{ name = "typing-extensions", specifier = ">=4.13.0" }] [package.metadata.requires-dev] all = [ - { name = "backports-zoneinfo", marker = "python_full_version < '3.9'" }, { name = "coverage" }, { name = "dirty-equals" }, { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, @@ -648,8 +648,8 @@ all = [ { name = "inline-snapshot" }, { name = "maturin" }, { name = "mypy" }, - { name = "numpy", marker = "python_full_version >= '3.9' and python_full_version < '3.13' and implementation_name == 'cpython' and platform_machine == 'x86_64'" }, - { name = "pandas", marker = "python_full_version >= '3.9' and python_full_version < '3.13' and implementation_name == 'cpython' and platform_machine == 'x86_64'" }, + { name = "numpy", marker = "python_full_version < '3.13' and implementation_name == 'cpython' and platform_machine == 'x86_64'" }, + { name = "pandas", marker = "python_full_version < '3.13' and implementation_name == 'cpython' and platform_machine == 'x86_64'" }, { name = "pyright" }, { name = "pytest" }, { name = "pytest-examples", marker = "implementation_name == 'cpython' and platform_machine == 'x86_64'" }, @@ -660,7 +660,7 @@ all = [ { name = "pytest-timeout" }, { name = "python-dateutil" }, { name = "ruff" }, - { name = "typing-extensions" }, + { name = "typing-inspection", specifier = ">=0.4.1" }, { name = "tzdata" }, ] codspeed = [{ name = "pytest-codspeed", marker = "python_full_version == '3.13.*' and implementation_name == 'cpython'" }] @@ -673,15 +673,14 @@ linting = [ { name = "ruff" }, ] testing = [ - { name = "backports-zoneinfo", marker = "python_full_version < '3.9'" }, { name = "coverage" }, { name = "dirty-equals" }, { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, { name = "hypothesis" }, { name = "inline-snapshot" }, { name = "maturin" }, - { name = "numpy", marker = "python_full_version >= '3.9' and python_full_version < '3.13' and implementation_name == 'cpython' and platform_machine == 'x86_64'" }, - { name = "pandas", marker = "python_full_version >= '3.9' and python_full_version < '3.13' and implementation_name == 'cpython' and platform_machine == 'x86_64'" }, + { name = "numpy", marker = "python_full_version < '3.13' and implementation_name == 'cpython' and platform_machine == 'x86_64'" }, + { name = "pandas", marker = "python_full_version < '3.13' and implementation_name == 'cpython' and platform_machine == 'x86_64'" }, { name = "pytest" }, { name = "pytest-examples", marker = "implementation_name == 'cpython' and platform_machine == 'x86_64'" }, { name = "pytest-mock" }, @@ -690,22 +689,21 @@ testing = [ { name = "pytest-speed" }, { name = "pytest-timeout" }, { name = "python-dateutil" }, - { name = "typing-extensions" }, + { name = "typing-inspection", specifier = ">=0.4.1" }, { name = "tzdata" }, ] wasm = [ { name = "maturin" }, { name = "ruff" }, - { name = "typing-extensions" }, ] [[package]] name = "pygments" version = "2.19.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 } +sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload-time = "2025-01-06T17:26:30.443Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, + { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" }, ] [[package]] @@ -716,9 +714,9 @@ dependencies = [ { name = "nodeenv" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/66/df/3c6f6b08fba7ccf49b114dfc4bb33e25c299883fd763f93fad47ef8bc58d/pyright-1.1.392.post0.tar.gz", hash = "sha256:3b7f88de74a28dcfa90c7d90c782b6569a48c2be5f9d4add38472bdaac247ebd", size = 3789911 } +sdist = { url = "https://files.pythonhosted.org/packages/66/df/3c6f6b08fba7ccf49b114dfc4bb33e25c299883fd763f93fad47ef8bc58d/pyright-1.1.392.post0.tar.gz", hash = "sha256:3b7f88de74a28dcfa90c7d90c782b6569a48c2be5f9d4add38472bdaac247ebd", size = 3789911, upload-time = "2025-01-15T15:01:20.913Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/b1/a18de17f40e4f61ca58856b9ef9b0febf74ff88978c3f7776f910071f567/pyright-1.1.392.post0-py3-none-any.whl", hash = "sha256:252f84458a46fa2f0fd4e2f91fc74f50b9ca52c757062e93f6c250c0d8329eb2", size = 5595487 }, + { url = "https://files.pythonhosted.org/packages/e7/b1/a18de17f40e4f61ca58856b9ef9b0febf74ff88978c3f7776f910071f567/pyright-1.1.392.post0-py3-none-any.whl", hash = "sha256:252f84458a46fa2f0fd4e2f91fc74f50b9ca52c757062e93f6c250c0d8329eb2", size = 5595487, upload-time = "2025-01-15T15:01:17.775Z" }, ] [[package]] @@ -733,9 +731,9 @@ dependencies = [ { name = "pluggy" }, { name = "tomli", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919 } +sdist = { url = "https://files.pythonhosted.org/packages/05/35/30e0d83068951d90a01852cb1cef56e5d8a09d20c7f511634cc2f7e0372a/pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761", size = 1445919, upload-time = "2024-12-01T12:54:25.98Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083 }, + { url = "https://files.pythonhosted.org/packages/11/92/76a1c94d3afee238333bc0a42b82935dd8f9cf8ce9e336ff87ee14d9e1cf/pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6", size = 343083, upload-time = "2024-12-01T12:54:19.735Z" }, ] [[package]] @@ -747,19 +745,19 @@ dependencies = [ { name = "pytest", marker = "python_full_version == '3.13.*' and implementation_name == 'cpython'" }, { name = "rich", marker = "python_full_version == '3.13.*' and implementation_name == 'cpython'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/36/39/4a94b61e981f993d52d0fbff259c3de08a2fb884a77464f35522031125d5/pytest_codspeed-3.1.2.tar.gz", hash = "sha256:09c1733af3aab35e94a621aa510f2d2114f65591e6f644c42ca3f67547edad4b", size = 18277 } +sdist = { url = "https://files.pythonhosted.org/packages/36/39/4a94b61e981f993d52d0fbff259c3de08a2fb884a77464f35522031125d5/pytest_codspeed-3.1.2.tar.gz", hash = "sha256:09c1733af3aab35e94a621aa510f2d2114f65591e6f644c42ca3f67547edad4b", size = 18277, upload-time = "2025-01-09T13:42:03.27Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/a5/ca/8fbcf065e10fcde0d766fa40452e1e348ad17456b87584fb3136c8b53809/pytest_codspeed-3.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aed496f873670ce0ea8f980a7c1a2c6a08f415e0ebdf207bf651b2d922103374", size = 26734 }, - { url = "https://files.pythonhosted.org/packages/f6/b9/852971f76d8e4aa73ef4dcc028c07d2d8f2ca7add8eb8bc94f9e6053c879/pytest_codspeed-3.1.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee45b0b763f6b5fa5d74c7b91d694a9615561c428b320383660672f4471756e3", size = 25373 }, - { url = "https://files.pythonhosted.org/packages/44/9f/5d2c0879256ca824c720baf5fac61d51179dd16111c609abab4f84e8ddcb/pytest_codspeed-3.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c84e591a7a0f67d45e2dc9fd05b276971a3aabcab7478fe43363ebefec1358f4", size = 26742 }, - { url = "https://files.pythonhosted.org/packages/5b/ff/862657f1a5a5dc9682dc7c23849fdabb0501df8da44eb307b1a9c3017254/pytest_codspeed-3.1.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6ae6d094247156407770e6b517af70b98862dd59a3c31034aede11d5f71c32c", size = 25375 }, - { url = "https://files.pythonhosted.org/packages/1b/bb/42fa7de046ddd0cefb1987d72e7ed4ee5ae4d962c8e6c62c29a8d6334e90/pytest_codspeed-3.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d0f264991de5b5cdc118b96fc671386cca3f0f34e411482939bf2459dc599097", size = 27114 }, - { url = "https://files.pythonhosted.org/packages/0a/8e/bc84e8f94637ef31323961e25ce83508edb630e05a5956ce585fa96b57f2/pytest_codspeed-3.1.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c0695a4bcd5ff04e8379124dba5d9795ea5e0cadf38be7a0406432fc1467b555", size = 25870 }, - { url = "https://files.pythonhosted.org/packages/d6/a1/b85a880916d8c8992a18ce2ee41b179e867af1b5d9ea1c27a68190780d3d/pytest_codspeed-3.1.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6dc356c8dcaaa883af83310f397ac06c96fac9b8a1146e303d4b374b2cb46a18", size = 27112 }, - { url = "https://files.pythonhosted.org/packages/23/44/2ba137983072cad2c853687fa737138b790cc0f71dc1842f3672488c61fc/pytest_codspeed-3.1.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cc8a5d0366322a75cf562f7d8d672d28c1cf6948695c4dddca50331e08f6b3d5", size = 25859 }, - { url = "https://files.pythonhosted.org/packages/ea/f4/8deca488c04d993eb8b9a7c30408bdffcd84b87eda8f83759718a8f82efb/pytest_codspeed-3.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6c5fe7a19b72f54f217480b3b527102579547b1de9fe3acd9e66cb4629ff46c8", size = 26725 }, - { url = "https://files.pythonhosted.org/packages/c1/8f/0433514dd85f136057b31c27264bab08a3b96c91f3870912a9a1cb362572/pytest_codspeed-3.1.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b67205755a665593f6521a98317d02a9d07d6fdc593f6634de2c94dea47a3055", size = 25364 }, - { url = "https://files.pythonhosted.org/packages/a0/9f/7833be9ce5ceed7284955e1c1602a19552c397861a5b3c1eab3d6b26fca7/pytest_codspeed-3.1.2-py3-none-any.whl", hash = "sha256:5e7ed0315e33496c5c07dba262b50303b8d0bc4c3d10bf1d422a41e70783f1cb", size = 14938 }, + { url = "https://files.pythonhosted.org/packages/a5/ca/8fbcf065e10fcde0d766fa40452e1e348ad17456b87584fb3136c8b53809/pytest_codspeed-3.1.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aed496f873670ce0ea8f980a7c1a2c6a08f415e0ebdf207bf651b2d922103374", size = 26734, upload-time = "2025-01-09T13:41:44.96Z" }, + { url = "https://files.pythonhosted.org/packages/f6/b9/852971f76d8e4aa73ef4dcc028c07d2d8f2ca7add8eb8bc94f9e6053c879/pytest_codspeed-3.1.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ee45b0b763f6b5fa5d74c7b91d694a9615561c428b320383660672f4471756e3", size = 25373, upload-time = "2025-01-09T13:41:47.236Z" }, + { url = "https://files.pythonhosted.org/packages/44/9f/5d2c0879256ca824c720baf5fac61d51179dd16111c609abab4f84e8ddcb/pytest_codspeed-3.1.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c84e591a7a0f67d45e2dc9fd05b276971a3aabcab7478fe43363ebefec1358f4", size = 26742, upload-time = "2025-01-09T13:41:49.265Z" }, + { url = "https://files.pythonhosted.org/packages/5b/ff/862657f1a5a5dc9682dc7c23849fdabb0501df8da44eb307b1a9c3017254/pytest_codspeed-3.1.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c6ae6d094247156407770e6b517af70b98862dd59a3c31034aede11d5f71c32c", size = 25375, upload-time = "2025-01-09T13:41:51.295Z" }, + { url = "https://files.pythonhosted.org/packages/1b/bb/42fa7de046ddd0cefb1987d72e7ed4ee5ae4d962c8e6c62c29a8d6334e90/pytest_codspeed-3.1.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d0f264991de5b5cdc118b96fc671386cca3f0f34e411482939bf2459dc599097", size = 27114, upload-time = "2025-01-09T13:41:52.675Z" }, + { url = "https://files.pythonhosted.org/packages/0a/8e/bc84e8f94637ef31323961e25ce83508edb630e05a5956ce585fa96b57f2/pytest_codspeed-3.1.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c0695a4bcd5ff04e8379124dba5d9795ea5e0cadf38be7a0406432fc1467b555", size = 25870, upload-time = "2025-01-09T13:41:54.72Z" }, + { url = "https://files.pythonhosted.org/packages/d6/a1/b85a880916d8c8992a18ce2ee41b179e867af1b5d9ea1c27a68190780d3d/pytest_codspeed-3.1.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6dc356c8dcaaa883af83310f397ac06c96fac9b8a1146e303d4b374b2cb46a18", size = 27112, upload-time = "2025-01-09T13:41:55.656Z" }, + { url = "https://files.pythonhosted.org/packages/23/44/2ba137983072cad2c853687fa737138b790cc0f71dc1842f3672488c61fc/pytest_codspeed-3.1.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cc8a5d0366322a75cf562f7d8d672d28c1cf6948695c4dddca50331e08f6b3d5", size = 25859, upload-time = "2025-01-09T13:41:57.94Z" }, + { url = "https://files.pythonhosted.org/packages/ea/f4/8deca488c04d993eb8b9a7c30408bdffcd84b87eda8f83759718a8f82efb/pytest_codspeed-3.1.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6c5fe7a19b72f54f217480b3b527102579547b1de9fe3acd9e66cb4629ff46c8", size = 26725, upload-time = "2025-01-09T13:42:00.461Z" }, + { url = "https://files.pythonhosted.org/packages/c1/8f/0433514dd85f136057b31c27264bab08a3b96c91f3870912a9a1cb362572/pytest_codspeed-3.1.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b67205755a665593f6521a98317d02a9d07d6fdc593f6634de2c94dea47a3055", size = 25364, upload-time = "2025-01-09T13:42:01.434Z" }, + { url = "https://files.pythonhosted.org/packages/a0/9f/7833be9ce5ceed7284955e1c1602a19552c397861a5b3c1eab3d6b26fca7/pytest_codspeed-3.1.2-py3-none-any.whl", hash = "sha256:5e7ed0315e33496c5c07dba262b50303b8d0bc4c3d10bf1d422a41e70783f1cb", size = 14938, upload-time = "2025-01-09T13:42:02.329Z" }, ] [[package]] @@ -771,9 +769,9 @@ dependencies = [ { name = "pytest" }, { name = "ruff" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c3/82/fa4fb866d52934de97b90c84c89896faebfb984436804fc3baa55d48d511/pytest_examples-0.0.15.tar.gz", hash = "sha256:2d6ced2d1f0d59863f81a4d2f193737464b8004a7670907c3bedef6306a5d660", size = 20771 } +sdist = { url = "https://files.pythonhosted.org/packages/c3/82/fa4fb866d52934de97b90c84c89896faebfb984436804fc3baa55d48d511/pytest_examples-0.0.15.tar.gz", hash = "sha256:2d6ced2d1f0d59863f81a4d2f193737464b8004a7670907c3bedef6306a5d660", size = 20771, upload-time = "2024-11-20T17:27:37.086Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ba/81/3f727a7d2f9c1ff36f581453949a4af314629108642d5140298476e90902/pytest_examples-0.0.15-py3-none-any.whl", hash = "sha256:6e4adc522bf2e3f93cae3b37a4add76fcc2c1ada29d8988b2ea15b236233ec0f", size = 17922 }, + { url = "https://files.pythonhosted.org/packages/ba/81/3f727a7d2f9c1ff36f581453949a4af314629108642d5140298476e90902/pytest_examples-0.0.15-py3-none-any.whl", hash = "sha256:6e4adc522bf2e3f93cae3b37a4add76fcc2c1ada29d8988b2ea15b236233ec0f", size = 17922, upload-time = "2024-11-20T17:27:35.155Z" }, ] [[package]] @@ -783,9 +781,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c6/90/a955c3ab35ccd41ad4de556596fa86685bf4fc5ffcc62d22d856cfd4e29a/pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0", size = 32814 } +sdist = { url = "https://files.pythonhosted.org/packages/c6/90/a955c3ab35ccd41ad4de556596fa86685bf4fc5ffcc62d22d856cfd4e29a/pytest-mock-3.14.0.tar.gz", hash = "sha256:2719255a1efeceadbc056d6bf3df3d1c5015530fb40cf347c0f9afac88410bd0", size = 32814, upload-time = "2024-03-21T22:14:04.964Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f2/3b/b26f90f74e2986a82df6e7ac7e319b8ea7ccece1caec9f8ab6104dc70603/pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f", size = 9863 }, + { url = "https://files.pythonhosted.org/packages/f2/3b/b26f90f74e2986a82df6e7ac7e319b8ea7ccece1caec9f8ab6104dc70603/pytest_mock-3.14.0-py3-none-any.whl", hash = "sha256:0b72c38033392a5f4621342fe11e9219ac11ec9d375f8e2a0c164539e0d70f6f", size = 9863, upload-time = "2024-03-21T22:14:02.694Z" }, ] [[package]] @@ -796,9 +794,9 @@ dependencies = [ { name = "pytest" }, { name = "rich" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a5/18/30ad0408295f3157f7a4913f0eaa51a0a377ebad0ffa51ff239e833c6c72/pytest_pretty-1.2.0.tar.gz", hash = "sha256:105a355f128e392860ad2c478ae173ff96d2f03044692f9818ff3d49205d3a60", size = 6542 } +sdist = { url = "https://files.pythonhosted.org/packages/a5/18/30ad0408295f3157f7a4913f0eaa51a0a377ebad0ffa51ff239e833c6c72/pytest_pretty-1.2.0.tar.gz", hash = "sha256:105a355f128e392860ad2c478ae173ff96d2f03044692f9818ff3d49205d3a60", size = 6542, upload-time = "2023-04-05T17:11:50.917Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/fe/d44d391312c1b8abee2af58ee70fabb1c00b6577ac4e0bdf25b70c1caffb/pytest_pretty-1.2.0-py3-none-any.whl", hash = "sha256:6f79122bf53864ae2951b6c9e94d7a06a87ef753476acd4588aeac018f062036", size = 6180 }, + { url = "https://files.pythonhosted.org/packages/bf/fe/d44d391312c1b8abee2af58ee70fabb1c00b6577ac4e0bdf25b70c1caffb/pytest_pretty-1.2.0-py3-none-any.whl", hash = "sha256:6f79122bf53864ae2951b6c9e94d7a06a87ef753476acd4588aeac018f062036", size = 6180, upload-time = "2023-04-05T17:11:49.801Z" }, ] [[package]] @@ -808,9 +806,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/fe/13/d3bcb2c52f63b774be612cbee51f33a5cf2fa97d2f60fe26264f6720477b/pytest_run_parallel-0.3.1.tar.gz", hash = "sha256:636306d3ed6838898d8d42b3cd379dac7b327ce6d68df1bcc30d55a208d5081e", size = 14142 } +sdist = { url = "https://files.pythonhosted.org/packages/fe/13/d3bcb2c52f63b774be612cbee51f33a5cf2fa97d2f60fe26264f6720477b/pytest_run_parallel-0.3.1.tar.gz", hash = "sha256:636306d3ed6838898d8d42b3cd379dac7b327ce6d68df1bcc30d55a208d5081e", size = 14142, upload-time = "2025-02-05T20:29:11.504Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/4d/67/4943178bb5dacb2e0b745b4db4ab126112dafab66266f2262896e791dbbe/pytest_run_parallel-0.3.1-py3-none-any.whl", hash = "sha256:0675c9e4c8e843085333c66bc0ce6b8091e3509dc8e6df3429f05c28f5345b17", size = 9468 }, + { url = "https://files.pythonhosted.org/packages/4d/67/4943178bb5dacb2e0b745b4db4ab126112dafab66266f2262896e791dbbe/pytest_run_parallel-0.3.1-py3-none-any.whl", hash = "sha256:0675c9e4c8e843085333c66bc0ce6b8091e3509dc8e6df3429f05c28f5345b17", size = 9468, upload-time = "2025-02-05T20:29:10.406Z" }, ] [[package]] @@ -822,9 +820,9 @@ dependencies = [ { name = "pytest" }, { name = "rich" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/61/21/6acc1504e62f5b72ede4a1d10b70dd3e6a2acc14e21f214673fe701c272b/pytest_speed-0.3.5.tar.gz", hash = "sha256:e76208eb37362d0de9ce228488d18b5d96b95ea0dec6b0ad0e0f4ddfa359f3b0", size = 8702 } +sdist = { url = "https://files.pythonhosted.org/packages/61/21/6acc1504e62f5b72ede4a1d10b70dd3e6a2acc14e21f214673fe701c272b/pytest_speed-0.3.5.tar.gz", hash = "sha256:e76208eb37362d0de9ce228488d18b5d96b95ea0dec6b0ad0e0f4ddfa359f3b0", size = 8702, upload-time = "2023-01-22T12:09:19.303Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/59/c5/654fe3dae7d791d3a177f8aea58bec6aa72b9d8fdde1e2f30cd2e0c5fe1a/pytest_speed-0.3.5-py3-none-any.whl", hash = "sha256:ef9f17d6800b158e0a78df81bdbfe662a27ef5ddbf86376ff092fd6673135466", size = 9717 }, + { url = "https://files.pythonhosted.org/packages/59/c5/654fe3dae7d791d3a177f8aea58bec6aa72b9d8fdde1e2f30cd2e0c5fe1a/pytest_speed-0.3.5-py3-none-any.whl", hash = "sha256:ef9f17d6800b158e0a78df81bdbfe662a27ef5ddbf86376ff092fd6673135466", size = 9717, upload-time = "2023-01-22T12:09:17.351Z" }, ] [[package]] @@ -834,9 +832,9 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/93/0d/04719abc7a4bdb3a7a1f968f24b0f5253d698c9cc94975330e9d3145befb/pytest-timeout-2.3.1.tar.gz", hash = "sha256:12397729125c6ecbdaca01035b9e5239d4db97352320af155b3f5de1ba5165d9", size = 17697 } +sdist = { url = "https://files.pythonhosted.org/packages/93/0d/04719abc7a4bdb3a7a1f968f24b0f5253d698c9cc94975330e9d3145befb/pytest-timeout-2.3.1.tar.gz", hash = "sha256:12397729125c6ecbdaca01035b9e5239d4db97352320af155b3f5de1ba5165d9", size = 17697, upload-time = "2024-03-07T21:04:01.069Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/03/27/14af9ef8321f5edc7527e47def2a21d8118c6f329a9342cc61387a0c0599/pytest_timeout-2.3.1-py3-none-any.whl", hash = "sha256:68188cb703edfc6a18fad98dc25a3c61e9f24d644b0b70f33af545219fc7813e", size = 14148 }, + { url = "https://files.pythonhosted.org/packages/03/27/14af9ef8321f5edc7527e47def2a21d8118c6f329a9342cc61387a0c0599/pytest_timeout-2.3.1-py3-none-any.whl", hash = "sha256:68188cb703edfc6a18fad98dc25a3c61e9f24d644b0b70f33af545219fc7813e", size = 14148, upload-time = "2024-03-07T21:03:58.764Z" }, ] [[package]] @@ -846,18 +844,18 @@ source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "six" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 } +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 }, + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, ] [[package]] name = "pytz" version = "2024.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3a/31/3c70bf7603cc2dca0f19bdc53b4537a797747a58875b552c8c413d963a3f/pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a", size = 319692 } +sdist = { url = "https://files.pythonhosted.org/packages/3a/31/3c70bf7603cc2dca0f19bdc53b4537a797747a58875b552c8c413d963a3f/pytz-2024.2.tar.gz", hash = "sha256:2aa355083c50a0f93fa581709deac0c9ad65cca8a9e9beac660adcbd493c798a", size = 319692, upload-time = "2024-09-11T02:24:47.91Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/11/c3/005fcca25ce078d2cc29fd559379817424e94885510568bc1bc53d7d5846/pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725", size = 508002 }, + { url = "https://files.pythonhosted.org/packages/11/c3/005fcca25ce078d2cc29fd559379817424e94885510568bc1bc53d7d5846/pytz-2024.2-py2.py3-none-any.whl", hash = "sha256:31c7c1817eb7fae7ca4b8c7ee50c72f93aa2dd863de768e1ef4245d426aa0725", size = 508002, upload-time = "2024-09-11T02:24:45.8Z" }, ] [[package]] @@ -869,107 +867,119 @@ dependencies = [ { name = "pygments" }, { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 } +sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149, upload-time = "2024-11-01T16:43:57.873Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, + { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424, upload-time = "2024-11-01T16:43:55.817Z" }, ] [[package]] name = "ruff" version = "0.9.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/80/63/77ecca9d21177600f551d1c58ab0e5a0b260940ea7312195bd2a4798f8a8/ruff-0.9.2.tar.gz", hash = "sha256:b5eceb334d55fae5f316f783437392642ae18e16dcf4f1858d55d3c2a0f8f5d0", size = 3553799 } +sdist = { url = "https://files.pythonhosted.org/packages/80/63/77ecca9d21177600f551d1c58ab0e5a0b260940ea7312195bd2a4798f8a8/ruff-0.9.2.tar.gz", hash = "sha256:b5eceb334d55fae5f316f783437392642ae18e16dcf4f1858d55d3c2a0f8f5d0", size = 3553799, upload-time = "2025-01-16T13:22:20.512Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/af/b9/0e168e4e7fb3af851f739e8f07889b91d1a33a30fca8c29fa3149d6b03ec/ruff-0.9.2-py3-none-linux_armv6l.whl", hash = "sha256:80605a039ba1454d002b32139e4970becf84b5fee3a3c3bf1c2af6f61a784347", size = 11652408 }, - { url = "https://files.pythonhosted.org/packages/2c/22/08ede5db17cf701372a461d1cb8fdde037da1d4fa622b69ac21960e6237e/ruff-0.9.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b9aab82bb20afd5f596527045c01e6ae25a718ff1784cb92947bff1f83068b00", size = 11587553 }, - { url = "https://files.pythonhosted.org/packages/42/05/dedfc70f0bf010230229e33dec6e7b2235b2a1b8cbb2a991c710743e343f/ruff-0.9.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fbd337bac1cfa96be615f6efcd4bc4d077edbc127ef30e2b8ba2a27e18c054d4", size = 11020755 }, - { url = "https://files.pythonhosted.org/packages/df/9b/65d87ad9b2e3def67342830bd1af98803af731243da1255537ddb8f22209/ruff-0.9.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b35259b0cbf8daa22a498018e300b9bb0174c2bbb7bcba593935158a78054d", size = 11826502 }, - { url = "https://files.pythonhosted.org/packages/93/02/f2239f56786479e1a89c3da9bc9391120057fc6f4a8266a5b091314e72ce/ruff-0.9.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b6a9701d1e371bf41dca22015c3f89769da7576884d2add7317ec1ec8cb9c3c", size = 11390562 }, - { url = "https://files.pythonhosted.org/packages/c9/37/d3a854dba9931f8cb1b2a19509bfe59e00875f48ade632e95aefcb7a0aee/ruff-0.9.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9cc53e68b3c5ae41e8faf83a3b89f4a5d7b2cb666dff4b366bb86ed2a85b481f", size = 12548968 }, - { url = "https://files.pythonhosted.org/packages/fa/c3/c7b812bb256c7a1d5553433e95980934ffa85396d332401f6b391d3c4569/ruff-0.9.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8efd9da7a1ee314b910da155ca7e8953094a7c10d0c0a39bfde3fcfd2a015684", size = 13187155 }, - { url = "https://files.pythonhosted.org/packages/bd/5a/3c7f9696a7875522b66aa9bba9e326e4e5894b4366bd1dc32aa6791cb1ff/ruff-0.9.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3292c5a22ea9a5f9a185e2d131dc7f98f8534a32fb6d2ee7b9944569239c648d", size = 12704674 }, - { url = "https://files.pythonhosted.org/packages/be/d6/d908762257a96ce5912187ae9ae86792e677ca4f3dc973b71e7508ff6282/ruff-0.9.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a605fdcf6e8b2d39f9436d343d1f0ff70c365a1e681546de0104bef81ce88df", size = 14529328 }, - { url = "https://files.pythonhosted.org/packages/2d/c2/049f1e6755d12d9cd8823242fa105968f34ee4c669d04cac8cea51a50407/ruff-0.9.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c547f7f256aa366834829a08375c297fa63386cbe5f1459efaf174086b564247", size = 12385955 }, - { url = "https://files.pythonhosted.org/packages/91/5a/a9bdb50e39810bd9627074e42743b00e6dc4009d42ae9f9351bc3dbc28e7/ruff-0.9.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d18bba3d3353ed916e882521bc3e0af403949dbada344c20c16ea78f47af965e", size = 11810149 }, - { url = "https://files.pythonhosted.org/packages/e5/fd/57df1a0543182f79a1236e82a79c68ce210efb00e97c30657d5bdb12b478/ruff-0.9.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b338edc4610142355ccf6b87bd356729b62bf1bc152a2fad5b0c7dc04af77bfe", size = 11479141 }, - { url = "https://files.pythonhosted.org/packages/dc/16/bc3fd1d38974f6775fc152a0554f8c210ff80f2764b43777163c3c45d61b/ruff-0.9.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:492a5e44ad9b22a0ea98cf72e40305cbdaf27fac0d927f8bc9e1df316dcc96eb", size = 12014073 }, - { url = "https://files.pythonhosted.org/packages/47/6b/e4ca048a8f2047eb652e1e8c755f384d1b7944f69ed69066a37acd4118b0/ruff-0.9.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:af1e9e9fe7b1f767264d26b1075ac4ad831c7db976911fa362d09b2d0356426a", size = 12435758 }, - { url = "https://files.pythonhosted.org/packages/c2/40/4d3d6c979c67ba24cf183d29f706051a53c36d78358036a9cd21421582ab/ruff-0.9.2-py3-none-win32.whl", hash = "sha256:71cbe22e178c5da20e1514e1e01029c73dc09288a8028a5d3446e6bba87a5145", size = 9796916 }, - { url = "https://files.pythonhosted.org/packages/c3/ef/7f548752bdb6867e6939489c87fe4da489ab36191525fadc5cede2a6e8e2/ruff-0.9.2-py3-none-win_amd64.whl", hash = "sha256:c5e1d6abc798419cf46eed03f54f2e0c3adb1ad4b801119dedf23fcaf69b55b5", size = 10773080 }, - { url = "https://files.pythonhosted.org/packages/0e/4e/33df635528292bd2d18404e4daabcd74ca8a9853b2e1df85ed3d32d24362/ruff-0.9.2-py3-none-win_arm64.whl", hash = "sha256:a1b63fa24149918f8b37cef2ee6fff81f24f0d74b6f0bdc37bc3e1f2143e41c6", size = 10001738 }, + { url = "https://files.pythonhosted.org/packages/af/b9/0e168e4e7fb3af851f739e8f07889b91d1a33a30fca8c29fa3149d6b03ec/ruff-0.9.2-py3-none-linux_armv6l.whl", hash = "sha256:80605a039ba1454d002b32139e4970becf84b5fee3a3c3bf1c2af6f61a784347", size = 11652408, upload-time = "2025-01-16T13:21:12.732Z" }, + { url = "https://files.pythonhosted.org/packages/2c/22/08ede5db17cf701372a461d1cb8fdde037da1d4fa622b69ac21960e6237e/ruff-0.9.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b9aab82bb20afd5f596527045c01e6ae25a718ff1784cb92947bff1f83068b00", size = 11587553, upload-time = "2025-01-16T13:21:17.716Z" }, + { url = "https://files.pythonhosted.org/packages/42/05/dedfc70f0bf010230229e33dec6e7b2235b2a1b8cbb2a991c710743e343f/ruff-0.9.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:fbd337bac1cfa96be615f6efcd4bc4d077edbc127ef30e2b8ba2a27e18c054d4", size = 11020755, upload-time = "2025-01-16T13:21:21.746Z" }, + { url = "https://files.pythonhosted.org/packages/df/9b/65d87ad9b2e3def67342830bd1af98803af731243da1255537ddb8f22209/ruff-0.9.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:82b35259b0cbf8daa22a498018e300b9bb0174c2bbb7bcba593935158a78054d", size = 11826502, upload-time = "2025-01-16T13:21:26.135Z" }, + { url = "https://files.pythonhosted.org/packages/93/02/f2239f56786479e1a89c3da9bc9391120057fc6f4a8266a5b091314e72ce/ruff-0.9.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b6a9701d1e371bf41dca22015c3f89769da7576884d2add7317ec1ec8cb9c3c", size = 11390562, upload-time = "2025-01-16T13:21:29.026Z" }, + { url = "https://files.pythonhosted.org/packages/c9/37/d3a854dba9931f8cb1b2a19509bfe59e00875f48ade632e95aefcb7a0aee/ruff-0.9.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9cc53e68b3c5ae41e8faf83a3b89f4a5d7b2cb666dff4b366bb86ed2a85b481f", size = 12548968, upload-time = "2025-01-16T13:21:34.147Z" }, + { url = "https://files.pythonhosted.org/packages/fa/c3/c7b812bb256c7a1d5553433e95980934ffa85396d332401f6b391d3c4569/ruff-0.9.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:8efd9da7a1ee314b910da155ca7e8953094a7c10d0c0a39bfde3fcfd2a015684", size = 13187155, upload-time = "2025-01-16T13:21:40.494Z" }, + { url = "https://files.pythonhosted.org/packages/bd/5a/3c7f9696a7875522b66aa9bba9e326e4e5894b4366bd1dc32aa6791cb1ff/ruff-0.9.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3292c5a22ea9a5f9a185e2d131dc7f98f8534a32fb6d2ee7b9944569239c648d", size = 12704674, upload-time = "2025-01-16T13:21:45.041Z" }, + { url = "https://files.pythonhosted.org/packages/be/d6/d908762257a96ce5912187ae9ae86792e677ca4f3dc973b71e7508ff6282/ruff-0.9.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1a605fdcf6e8b2d39f9436d343d1f0ff70c365a1e681546de0104bef81ce88df", size = 14529328, upload-time = "2025-01-16T13:21:49.45Z" }, + { url = "https://files.pythonhosted.org/packages/2d/c2/049f1e6755d12d9cd8823242fa105968f34ee4c669d04cac8cea51a50407/ruff-0.9.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c547f7f256aa366834829a08375c297fa63386cbe5f1459efaf174086b564247", size = 12385955, upload-time = "2025-01-16T13:21:52.71Z" }, + { url = "https://files.pythonhosted.org/packages/91/5a/a9bdb50e39810bd9627074e42743b00e6dc4009d42ae9f9351bc3dbc28e7/ruff-0.9.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d18bba3d3353ed916e882521bc3e0af403949dbada344c20c16ea78f47af965e", size = 11810149, upload-time = "2025-01-16T13:21:57.098Z" }, + { url = "https://files.pythonhosted.org/packages/e5/fd/57df1a0543182f79a1236e82a79c68ce210efb00e97c30657d5bdb12b478/ruff-0.9.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b338edc4610142355ccf6b87bd356729b62bf1bc152a2fad5b0c7dc04af77bfe", size = 11479141, upload-time = "2025-01-16T13:22:00.585Z" }, + { url = "https://files.pythonhosted.org/packages/dc/16/bc3fd1d38974f6775fc152a0554f8c210ff80f2764b43777163c3c45d61b/ruff-0.9.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:492a5e44ad9b22a0ea98cf72e40305cbdaf27fac0d927f8bc9e1df316dcc96eb", size = 12014073, upload-time = "2025-01-16T13:22:03.956Z" }, + { url = "https://files.pythonhosted.org/packages/47/6b/e4ca048a8f2047eb652e1e8c755f384d1b7944f69ed69066a37acd4118b0/ruff-0.9.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:af1e9e9fe7b1f767264d26b1075ac4ad831c7db976911fa362d09b2d0356426a", size = 12435758, upload-time = "2025-01-16T13:22:07.73Z" }, + { url = "https://files.pythonhosted.org/packages/c2/40/4d3d6c979c67ba24cf183d29f706051a53c36d78358036a9cd21421582ab/ruff-0.9.2-py3-none-win32.whl", hash = "sha256:71cbe22e178c5da20e1514e1e01029c73dc09288a8028a5d3446e6bba87a5145", size = 9796916, upload-time = "2025-01-16T13:22:10.894Z" }, + { url = "https://files.pythonhosted.org/packages/c3/ef/7f548752bdb6867e6939489c87fe4da489ab36191525fadc5cede2a6e8e2/ruff-0.9.2-py3-none-win_amd64.whl", hash = "sha256:c5e1d6abc798419cf46eed03f54f2e0c3adb1ad4b801119dedf23fcaf69b55b5", size = 10773080, upload-time = "2025-01-16T13:22:14.155Z" }, + { url = "https://files.pythonhosted.org/packages/0e/4e/33df635528292bd2d18404e4daabcd74ca8a9853b2e1df85ed3d32d24362/ruff-0.9.2-py3-none-win_arm64.whl", hash = "sha256:a1b63fa24149918f8b37cef2ee6fff81f24f0d74b6f0bdc37bc3e1f2143e41c6", size = 10001738, upload-time = "2025-01-16T13:22:18.121Z" }, ] [[package]] name = "six" version = "1.17.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 }, + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] [[package]] name = "sortedcontainers" version = "2.4.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594 } +sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594, upload-time = "2021-05-16T22:03:42.897Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 }, + { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575, upload-time = "2021-05-16T22:03:41.177Z" }, ] [[package]] name = "tomli" version = "2.2.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077 }, - { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429 }, - { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067 }, - { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030 }, - { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898 }, - { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894 }, - { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319 }, - { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273 }, - { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310 }, - { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309 }, - { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762 }, - { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453 }, - { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486 }, - { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349 }, - { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159 }, - { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243 }, - { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645 }, - { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584 }, - { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875 }, - { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418 }, - { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708 }, - { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582 }, - { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543 }, - { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691 }, - { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170 }, - { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530 }, - { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666 }, - { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954 }, - { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724 }, - { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383 }, - { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257 }, +sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, + { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429, upload-time = "2024-11-27T22:37:56.698Z" }, + { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067, upload-time = "2024-11-27T22:37:57.63Z" }, + { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030, upload-time = "2024-11-27T22:37:59.344Z" }, + { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898, upload-time = "2024-11-27T22:38:00.429Z" }, + { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894, upload-time = "2024-11-27T22:38:02.094Z" }, + { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319, upload-time = "2024-11-27T22:38:03.206Z" }, + { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273, upload-time = "2024-11-27T22:38:04.217Z" }, + { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310, upload-time = "2024-11-27T22:38:05.908Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309, upload-time = "2024-11-27T22:38:06.812Z" }, + { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" }, + { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" }, + { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" }, + { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" }, + { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" }, + { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" }, + { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" }, + { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" }, + { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" }, + { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" }, + { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" }, + { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" }, + { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" }, + { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" }, + { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" }, + { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" }, + { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" }, + { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" }, + { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, ] [[package]] name = "typing-extensions" -version = "4.12.2" +version = "4.14.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } +sdist = { url = "https://files.pythonhosted.org/packages/d1/bc/51647cd02527e87d05cb083ccc402f93e441606ff1f01739a62c8ad09ba5/typing_extensions-4.14.0.tar.gz", hash = "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", size = 107423, upload-time = "2025-06-02T14:52:11.399Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/e0/552843e0d356fbb5256d21449fa957fa4eff3bbc135a74a691ee70c7c5da/typing_extensions-4.14.0-py3-none-any.whl", hash = "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af", size = 43839, upload-time = "2025-06-02T14:52:10.026Z" }, +] + +[[package]] +name = "typing-inspection" +version = "0.4.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f8/b1/0c11f5058406b3af7609f121aaa6b609744687f1d158b3c3a5bf4cc94238/typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28", size = 75726, upload-time = "2025-05-21T18:55:23.885Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, + { url = "https://files.pythonhosted.org/packages/17/69/cd203477f944c353c31bade965f880aa1061fd6bf05ded0726ca845b6ff7/typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", size = 14552, upload-time = "2025-05-21T18:55:22.152Z" }, ] [[package]] name = "tzdata" version = "2025.1" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/43/0f/fa4723f22942480be4ca9527bbde8d43f6c3f2fe8412f00e7f5f6746bc8b/tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694", size = 194950 } +sdist = { url = "https://files.pythonhosted.org/packages/43/0f/fa4723f22942480be4ca9527bbde8d43f6c3f2fe8412f00e7f5f6746bc8b/tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694", size = 194950, upload-time = "2025-01-21T19:49:38.686Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/0f/dd/84f10e23edd882c6f968c21c2434fe67bd4a528967067515feca9e611e5e/tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639", size = 346762 }, + { url = "https://files.pythonhosted.org/packages/0f/dd/84f10e23edd882c6f968c21c2434fe67bd4a528967067515feca9e611e5e/tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639", size = 346762, upload-time = "2025-01-21T19:49:37.187Z" }, ] diff --git a/wasm-preview/run_tests.py b/wasm-preview/run_tests.py index 806e01164..f4a7b3f33 100644 --- a/wasm-preview/run_tests.py +++ b/wasm-preview/run_tests.py @@ -38,7 +38,15 @@ async def main(tests_zip: str, tag_name: str): print(f'Mounted {count} test files, installing dependencies...') await micropip.install( - ['dirty-equals', 'hypothesis', 'pytest-speed', 'pytest-mock', 'tzdata', 'inline-snapshot', pydantic_core_wheel] + [ + 'dirty-equals', + 'hypothesis', + 'pytest-speed', + 'pytest-mock', + 'tzdata', + 'inline-snapshot<0.21', + pydantic_core_wheel, + ] ) importlib.invalidate_caches()