From 86dccb57b725a559b04b9627f38d3939c4494016 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Wed, 9 Sep 2026 08:31:47 +1200 Subject: [PATCH 1/3] Upgrade to cel-rust 0.14.5, refresh dependencies, bump CI actions cel-rust 0.14.4/0.14.5 bring behaviour the wrapper must follow: - Reserved CEL words (var, let, if, ...) are rejected as identifiers at parse time. Tests that used `var` as a variable name are renamed, and the change is called out in the CHANGELOG as user-visible. - type() is native and returns a first-class type value, so the string-returning shim and the identity dyn() shim in cel.stdlib are removed; built-ins already took precedence over them. uint now reports "uint" and null "null_type". - int()/uint() reject out-of-range conversions with a FunctionError whose message ends in "overflow"; map those to OverflowError to match the existing arithmetic overflow mapping. Also moves dev deps to dependency-groups (tool.uv.dev-dependencies is deprecated), refreshes uv.lock and in-range crates, and bumps checkout, setup-python, upload/download-artifact and setup-uv to their current majors. --- .github/workflows/ci.yml | 34 +-- .github/workflows/claude.yml | 2 +- .github/workflows/security.yml | 6 +- CHANGELOG.md | 40 +++ Cargo.lock | 56 ++--- Cargo.toml | 2 +- README.md | 2 +- docs/contributing.md | 1 - docs/reference/standard-library.md | 15 +- pyproject.toml | 6 +- python/cel/stdlib.py | 58 +---- src/lib.rs | 5 + tests/test_basics.py | 2 +- tests/test_cel_014_behaviour.py | 141 +++++++++++ tests/test_dual_mode_comprehensive.py | 6 +- tests/test_enhanced_error_handling.py | 8 +- .../test_issue16_string_literal_regression.py | 12 +- tests/test_upstream_improvements.py | 37 +-- uv.lock | 229 +++++++++--------- 19 files changed, 390 insertions(+), 272 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d32871..e54d390 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,10 +26,10 @@ jobs: matrix: python-version: ["3.11", "3.12", "3.13", "3.14"] steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v7 - name: Install uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@v10 with: version: "latest" @@ -56,10 +56,10 @@ jobs: name: Code Quality & Type Checking runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v7 - name: Install uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@v10 with: version: "latest" @@ -119,8 +119,8 @@ jobs: - runner: ubuntu-latest target: ppc64le steps: - - uses: actions/checkout@v5 - - uses: actions/setup-python@v6 + - uses: actions/checkout@v7 + - uses: actions/setup-python@v7 with: python-version: '3.11' - name: Build wheels @@ -131,7 +131,7 @@ jobs: sccache: 'true' manylinux: auto - name: Upload wheels - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 with: name: wheels-linux-${{ matrix.platform.target }} path: dist @@ -147,8 +147,8 @@ jobs: - runner: windows-latest target: x86 steps: - - uses: actions/checkout@v5 - - uses: actions/setup-python@v6 + - uses: actions/checkout@v7 + - uses: actions/setup-python@v7 with: python-version: '3.11' architecture: ${{ matrix.platform.target }} @@ -159,7 +159,7 @@ jobs: args: --release --out dist --find-interpreter sccache: 'true' - name: Upload wheels - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 with: name: wheels-windows-${{ matrix.platform.target }} path: dist @@ -175,8 +175,8 @@ jobs: - runner: macos-14 target: aarch64 steps: - - uses: actions/checkout@v5 - - uses: actions/setup-python@v6 + - uses: actions/checkout@v7 + - uses: actions/setup-python@v7 with: python-version: '3.11' - name: Build wheels @@ -186,7 +186,7 @@ jobs: args: --release --out dist --find-interpreter sccache: 'true' - name: Upload wheels - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 with: name: wheels-macos-${{ matrix.platform.target }} path: dist @@ -195,14 +195,14 @@ jobs: runs-on: ubuntu-latest needs: [test, lint] steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v7 - name: Build sdist uses: PyO3/maturin-action@v1 with: command: sdist args: --out dist - name: Upload sdist - uses: actions/upload-artifact@v5 + uses: actions/upload-artifact@v7 with: name: wheels-sdist path: dist @@ -222,10 +222,10 @@ jobs: # contents: write lets the last step create the GitHub release for the tag. contents: write steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v7 - name: Collect wheels and sdist - uses: actions/download-artifact@v5 + uses: actions/download-artifact@v8 with: pattern: wheels-* merge-multiple: true diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index 4a23351..20e63f9 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -25,7 +25,7 @@ jobs: id-token: write steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v7 with: fetch-depth: 1 diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index b5bd257..17d1403 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -23,7 +23,7 @@ jobs: issues: write checks: write steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v7 - name: Run Rust security audit uses: rustsec/audit-check@v2.0.0 @@ -31,7 +31,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} - name: Install uv - uses: astral-sh/setup-uv@v7 + uses: astral-sh/setup-uv@v10 with: version: "latest" @@ -56,7 +56,7 @@ jobs: security-events: write steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v7 - name: Initialize CodeQL uses: github/codeql-action/init@v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 36ba955..65830c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **CEL reserved words are now rejected as identifiers.** cel-rust 0.14.4 enforces the + specification's reserved word list (`as`, `break`, `const`, `continue`, `else`, `for`, + `function`, `if`, `import`, `let`, `loop`, `package`, `namespace`, `return`, `var`, + `void`, `while`), so an expression such as `var == "x"` now raises `ValueError` at + parse time even if the context defines `var`. Names that merely contain a reserved + word (`var_2`) and map keys (`{"var": 1}["var"]`) are unaffected. Rename such + variables before upgrading. +- `type()` is now provided natively by cel-rust 0.14.5 and returns a first-class CEL + type value, so `type(x) == int`, `type(1u) == uint` and `type(null) == null_type` + work inside expressions. Returned to Python, a type value arrives as its name. The + string-returning `type()` shim and the identity `dyn()` shim have been removed from + `cel.stdlib`'s `core` library because the native functions take precedence anyway; + the only visible differences are that `uint` is now reported as `"uint"` rather than + `"int"` and `null` as `"null_type"` rather than `"null"`. +- `int()` and `uint()` reject conversions that do not fit the target type (for example + `int(9223372036854775808u)`, `uint(-1)`, `int(1e300)` and `int(double("NaN"))`), + raising `OverflowError` instead of silently wrapping or saturating. +- `duration` and `timestamp` values report their spec type names from `type()`: + `google.protobuf.Duration` and `google.protobuf.Timestamp`. + +### Fixed + +- Negative hexadecimal literals (`-0x10`) parse; stacked unary operators (`--1`, + `!!true`) cancel; `\u` escapes inside bytes literals are rejected per the spec; + and `optional.of(1) == optional.of(1)` compares by content (all from cel-rust + 0.14.4/0.14.5). + +### Updated + +- cel-rust 0.14.3 to 0.14.5 (the minimum is now 0.14.5), plus in-range transitive + bumps (log 0.4.34, uuid 1.26.0, smallvec 1.16.0, cc 1.4.5, syn 3.0.5). +- Python dev dependencies moved from the deprecated `tool.uv.dev-dependencies` to + `dependency-groups.dev`; `uv.lock` refreshed (ruff 0.16.6, typer 0.27.2, + maturin 1.15.0). +- GitHub Actions: `actions/checkout` v7, `actions/setup-python` v7, + `actions/upload-artifact` v7, `actions/download-artifact` v8 (digest mismatches + now fail the job), `astral-sh/setup-uv` v10 (cache disabled on pull requests + from forks and on Dependabot rollups, to guard against cache poisoning). ### Updated - Releases publish to PyPI with diff --git a/Cargo.lock b/Cargo.lock index 013c2d3..7e331b9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -105,9 +105,9 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "cc" -version = "1.4.3" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "509591b7bcd67f4ef775afad7662703b4935daaa6ec0e5605cfb1090b32a2b6d" +checksum = "005ec2760ca554fae18df7a11195552ec576cd665632a881bc011d5bb2fd4d80" dependencies = [ "find-msvc-tools", "shlex", @@ -117,7 +117,7 @@ dependencies = [ name = "cel" version = "0.8.0" dependencies = [ - "cel 0.14.3", + "cel 0.14.5", "chrono", "log", "pyo3", @@ -126,9 +126,9 @@ dependencies = [ [[package]] name = "cel" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82399e72d100a28a0cac14251a8aba16d124af2a237d8a60ab7997ba7380cc3" +checksum = "2ae7daebcd4d032c9a5288790c2facde6fab3f9a9ff8d5028765e8b48a36eeb2" dependencies = [ "antlr4rust", "base64", @@ -171,9 +171,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "find-msvc-tools" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" +checksum = "3e0f1c7c3a72c66fd80abe965175f7523475c0489a87d3ff9d6e8c87d87a9d2d" [[package]] name = "futures-core" @@ -237,9 +237,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.104" +version = "0.3.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +checksum = "ce57d20d1ea864ce2ac172ab472d409214f4fd359f0b2a2775abdf522e2af99e" dependencies = [ "cfg-if", "futures-util", @@ -269,9 +269,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" [[package]] name = "memchr" @@ -523,7 +523,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.5", ] [[package]] @@ -553,9 +553,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.2" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +checksum = "b9be42f50aa861c555654aa3a37f52f4b1074bacf4e48fe0ef7fa584e80f1f0f" [[package]] name = "syn" @@ -570,9 +570,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.3" +version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +checksum = "12df2e0110f65b775f769bb17ef989067a1d931b2eb822bd4346631eeada89f9" dependencies = [ "proc-macro2", "quote", @@ -602,7 +602,7 @@ checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.5", ] [[package]] @@ -619,9 +619,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "uuid" -version = "1.24.1" +version = "1.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cefc03fd367c0c6d4305de1b312cf00248c4114f4a0418ce6a6af769e3b0bd9" +checksum = "b5772d71c9be8a8a6ac2117d949c5b224c1b72241bb611d9a3012edcf8af7812" dependencies = [ "js-sys", "wasm-bindgen", @@ -629,9 +629,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.127" +version = "0.2.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +checksum = "aecb87a33d3b0c5e3b7aa46336eaf486cffafbd281b195e4c8b80d50df2351bf" dependencies = [ "cfg-if", "once_cell", @@ -642,9 +642,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.127" +version = "0.2.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +checksum = "a690d511e3c1a8b3a55e33511e3c2c00c78415cd23650f32b808627f5696b9ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -652,22 +652,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.127" +version = "0.2.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +checksum = "411e4887f0071ef2d2164a9d5fdf2d20efbef78fccd3a78b0c10a1dc5295e48a" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.5", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.127" +version = "0.2.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +checksum = "81941cd78d0c92026c33e5e01312845a4cb1e9af3407f9134b100dd03144103e" dependencies = [ "unicode-ident", ] diff --git a/Cargo.toml b/Cargo.toml index 8747dae..bf79af7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ crate-type = ["cdylib"] [dependencies] pyo3 = { version = "0.29", features = ["chrono", "py-clone"]} -cel = { version = "0.14.0", features = ["chrono", "json", "regex", "bytes"] } +cel = { version = "0.14.5", features = ["chrono", "json", "regex", "bytes"] } log = "0.4.27" pyo3-log = "0.13.4" chrono = { version = "0.4.42", features = ["serde"] } diff --git a/README.md b/README.md index 5536c7c..0a113ed 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ **Fast, Safe, and Expressive evaluation of Google's Common Expression Language (CEL) in Python, powered by Rust.** -The Common Expression Language (CEL) is a non-Turing complete language designed for simplicity, speed, and safety. This Python package wraps the Rust implementation [cel](https://crates.io/crates/cel) v0.14.0, providing microsecond-level expression evaluation with seamless Python integration. +The Common Expression Language (CEL) is a non-Turing complete language designed for simplicity, speed, and safety. This Python package wraps the Rust implementation [cel](https://crates.io/crates/cel) v0.14.5, providing microsecond-level expression evaluation with seamless Python integration. ## 🚀 Use Cases diff --git a/docs/contributing.md b/docs/contributing.md index 13476b5..b4ed0d2 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -158,7 +158,6 @@ def test_lower_ascii_expected_behavior(self): | Category | Status | Impact | |----------|--------|---------| | **String Functions** (`lowerAscii`, `upperAscii`, `indexOf`, etc.) | 8 functions monitored | Medium - String processing | -| **Type Introspection** (`type()` function) | Ready to detect | Medium - Dynamic typing | | **Mixed Arithmetic** (`int + uint` operations) | Comprehensive detection | Medium - Type safety | | **Optional Values** (`optional.of()`, `?.` chaining) | Future feature detection | Low - Advanced use cases | | **🚨 OR Operator** (CEL spec compliance) | **Critical behavioral difference** | **High - Logic errors** | diff --git a/docs/reference/standard-library.md b/docs/reference/standard-library.md index 2e05381..51a27f5 100644 --- a/docs/reference/standard-library.md +++ b/docs/reference/standard-library.md @@ -62,7 +62,7 @@ assert cel.evaluate('charAt("hello", 0)', ctx) == "h" ### core -`bool`, `dyn`, `type`, `min`, `max`, `sum`. +`bool`, `min`, `max`, `sum`. ```python import cel @@ -72,8 +72,6 @@ ctx = cel.Context() add_stdlib_to_context(ctx) assert cel.evaluate('bool("true")', ctx) is True -assert cel.evaluate("dyn(5)", ctx) == 5 -assert cel.evaluate("type(1) == type(2)", ctx) is True assert cel.evaluate("min(3, 1, 2)", ctx) == 1 assert cel.evaluate("max([4, 9, 2])", ctx) == 9 assert cel.evaluate("sum([1, 2, 3])", ctx) == 6 @@ -123,11 +121,12 @@ assert cel.evaluate('sum([duration("1h"), duration("30m")]) == duration("90m")', [upstream](https://github.com/cel-rust/cel-rust) rather than in this wrapper. Most folds in practice are a `map()` plus `sum`/`min`/`max`, as above. -!!! note "`type()` limitations" - `type(x)` returns the CEL type *name* as a string (e.g. `"int"`), so - `type(x) == type(y)` works but comparing against a bare type identifier - (`type(x) == int`) does not. Because Python has a single integer type, a CEL - `uint` is reported as `"int"`. +!!! note "`dyn()` and `type()` are native" + cel-rust provides `dyn()` (since 0.14.1) and `type()` (since 0.14.5) itself, + so neither is part of `cel.stdlib`. The native `type()` returns a first-class + CEL type value: `type(x) == int`, `type(1u) == uint` and + `type(null) == null_type` all work inside an expression. When a type value is + returned to Python it arrives as the type's name, e.g. `"int"` or `"uint"`. ### strings diff --git a/pyproject.toml b/pyproject.toml index 059f483..49a85b4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,15 +38,13 @@ build-backend = "maturin" features = ["pyo3/extension-module"] python-source = "python" -[tool.uv] -dev-dependencies = [ +[dependency-groups] +dev = [ "pytest>=8.4.1", "maturin>=1.8.0", "ruff>=0.16.3,<0.17", "mypy>=1.17.1", ] - -[dependency-groups] docs = [ "mkdocs>=1.5.0", "mkdocs-material>=9.0.0", diff --git a/python/cel/stdlib.py b/python/cel/stdlib.py index 5017706..4f88178 100644 --- a/python/cel/stdlib.py +++ b/python/cel/stdlib.py @@ -15,7 +15,7 @@ ========== ================================================================ Library Functions ========== ================================================================ -core ``bool``, ``dyn``, ``type``, ``min``, ``max``, ``sum`` +core ``bool``, ``min``, ``max``, ``sum`` strings ``charAt``, ``indexOf``, ``lastIndexOf``, ``substring``, ``replace``, ``split``, ``join``, ``lowerAscii``, ``upperAscii``, ``trim``, ``reverse``, ``strings.quote`` @@ -42,11 +42,6 @@ Compatibility notes / known limitations versus cel-go: -* ``type(x)`` returns the CEL type *name* as a string (e.g. ``"int"``) rather - than a first-class CEL type value, so ``type(x) == type(y)`` works but - comparing against a bare type identifier (``type(x) == int``) does not. - Because Python has a single ``int`` type, a CEL ``uint`` is reported as - ``"int"``. * The cel-go ``strings.format`` and ``strings.quote`` verbs are only partially covered: ``strings.quote`` performs CEL-style escaping but ``strings.format`` is not implemented. @@ -73,9 +68,11 @@ cel-rust the comprehension macros (``all``/``exists``/``map``/``filter``) are expanded by the parser from a fixed table, so a ``fold`` macro has to be added upstream: https://github.com/cel-rust/cel-rust -* ``dyn`` is kept for callers that enable the ``core`` library on older builds; - cel-rust ships a native ``dyn()`` since 0.14.1, and the native one is used when - the extensions are not registered. +* ``dyn()`` and ``type()`` are not provided here because cel-rust ships both + natively (``dyn`` since 0.14.1, ``type`` since 0.14.5). The native ``type()`` + returns a first-class CEL type value, so ``type(x) == int`` and + ``type(1u) == uint`` work inside an expression; the value reaches Python as + the type's name (``"int"``, ``"uint"``, ``"null_type"``, ...). """ from __future__ import annotations @@ -115,47 +112,6 @@ def bool_(value: Any) -> bool: raise ValueError(f"cannot convert {type(value).__name__} to bool") -def dyn(value: Any) -> Any: - """Return the value unchanged. - - CEL's ``dyn()`` erases static type information; at runtime it is the - identity function. - """ - return value - - -def type_(value: Any) -> str: - """Return the CEL type name of a value as a string. - - See the module docstring for the limitations of this shim (notably that it - returns a string rather than a CEL type value, and cannot distinguish - ``uint`` from ``int``). - """ - if value is None: - return "null" - if isinstance(value, OptionalValue): - return "optional_type" - if isinstance(value, bool): - return "bool" - if isinstance(value, int): - return "int" - if isinstance(value, float): - return "double" - if isinstance(value, str): - return "string" - if isinstance(value, (bytes, bytearray)): - return "bytes" - if isinstance(value, datetime): - return "timestamp" - if isinstance(value, timedelta): - return "duration" - if isinstance(value, (list, tuple)): - return "list" - if isinstance(value, dict): - return "map" - return type(value).__name__ - - def _flatten_args(args: tuple[Any, ...]) -> list[Any]: """Accept either a single list argument or several scalar arguments.""" if len(args) == 1 and isinstance(args[0], (list, tuple)): @@ -603,8 +559,6 @@ def lists_range(n: int) -> list[int]: EXTENSIONS: dict[str, dict[str, Callable[..., Any]]] = { "core": { "bool": bool_, - "dyn": dyn, - "type": type_, "min": min_, "max": max_, "sum": sum_, diff --git a/src/lib.rs b/src/lib.rs index fc37b89..3e592cd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -687,6 +687,11 @@ fn map_execution_error_to_python(error: &ExecutionError) -> PyErr { "A function was called without a required argument or method target.", ) }, + ExecutionError::FunctionError { function, message } if message.ends_with("overflow") => { + PyOverflowError::new_err(format!( + "Function '{function}' error: {message}. The value is outside the range of the target type." + )) + }, ExecutionError::FunctionError { function, message } => { PyRuntimeError::new_err(format!( "Function '{function}' error: {message}. Check function arguments and their types." diff --git a/tests/test_basics.py b/tests/test_basics.py index 7c1e47b..6b9f16e 100644 --- a/tests/test_basics.py +++ b/tests/test_basics.py @@ -81,7 +81,7 @@ def test_expressions_with_context(expression_context_result): @pytest.mark.xfail( - reason="String indexing not supported in cel 0.14.3 - see test_upstream_improvements.py", + reason="String indexing not supported in cel 0.14.5 - see test_upstream_improvements.py", strict=True, ) def test_str_context_expression(): diff --git a/tests/test_cel_014_behaviour.py b/tests/test_cel_014_behaviour.py index 01ee193..47eb375 100644 --- a/tests/test_cel_014_behaviour.py +++ b/tests/test_cel_014_behaviour.py @@ -9,6 +9,10 @@ * Integer overflow raises rather than wrapping. * Bytes concatenation works. * Logical operators are error-resilient per the CEL spec. +* Since 0.14.4/0.14.5: CEL reserved words are rejected as identifiers, + ``type()`` is a native function returning a first-class type value, + ``int()``/``uint()`` reject out-of-range conversions, negative hex literals + parse, and optional values compare by content. """ import cel @@ -94,3 +98,140 @@ def test_no_signed_unsigned_mix(self): def test_explicit_conversion_works(self): assert cel.evaluate("double(1) + 2.5") == 3.5 assert cel.evaluate("1 + int(2u)") == 3 + + +class TestReservedIdentifiersRejected: + """cel 0.14.4 rejects the CEL spec's reserved words as identifiers. + + This is a parse error, so it surfaces as ``ValueError`` even when the + context defines a variable of that name. + """ + + @pytest.mark.parametrize( + "word", + [ + "as", + "break", + "const", + "continue", + "else", + "for", + "function", + "if", + "import", + "let", + "loop", + "package", + "namespace", + "return", + "var", + "void", + "while", + ], + ) + def test_reserved_word_as_variable(self, word): + with pytest.raises(ValueError, match="reserved identifier"): + cel.evaluate(f'{word} == "x"', {word: "x"}) + + def test_reserved_word_as_function(self): + with pytest.raises(ValueError, match="reserved identifier"): + cel.evaluate("namespace(1)") + + def test_reserved_word_allowed_inside_identifier(self): + assert cel.evaluate("var_2 + 1", {"var_2": 1}) == 2 + assert cel.evaluate('{"var": 1}["var"]') == 1 + + +class TestNativeTypeFunction: + def test_type_names(self): + assert cel.evaluate("type(1)") == "int" + assert cel.evaluate("type(1u)") == "uint" + assert cel.evaluate("type(1.5)") == "double" + assert cel.evaluate('type("x")') == "string" + assert cel.evaluate("type(b'x')") == "bytes" + assert cel.evaluate("type(true)") == "bool" + assert cel.evaluate("type(null)") == "null_type" + assert cel.evaluate("type([1])") == "list" + assert cel.evaluate("type({'a': 1})") == "map" + assert cel.evaluate("type(type(1))") == "type" + assert cel.evaluate("type(optional.of(1))") == "optional_type" + + def test_type_of_time_values_uses_protobuf_names(self): + # cel-spec names these after their well-known protobuf types. + assert cel.evaluate('type(duration("1s"))') == "google.protobuf.Duration" + assert ( + cel.evaluate('type(timestamp("2020-01-01T00:00:00Z"))') == "google.protobuf.Timestamp" + ) + + def test_type_values_compare_with_type_identifiers(self): + assert cel.evaluate("type(1) == int") is True + assert cel.evaluate("type(1u) == uint") is True + assert cel.evaluate("type(1) == uint") is False + assert cel.evaluate("type(null) == null_type") is True + assert cel.evaluate("type(1) in [int, uint]") is True + + def test_type_values_compare_with_each_other(self): + assert cel.evaluate("type(1) == type(2)") is True + assert cel.evaluate('type(1) == type("x")') is False + + def test_type_value_is_not_a_string_inside_cel(self): + # Only the Python conversion turns the type value into its name. + assert cel.evaluate('type(1) == "int"') is False + + def test_type_values_in_containers(self): + assert cel.evaluate("[type(1), type(2u)]") == ["int", "uint"] + assert cel.evaluate("{'k': type(1.0)}") == {"k": "double"} + + +class TestConversionRangeChecks: + """cel 0.14.5 rejects int()/uint() conversions that do not fit the target.""" + + def test_int_of_large_uint_overflows(self): + with pytest.raises(OverflowError, match="integer overflow"): + cel.evaluate("int(9223372036854775808u)") + + def test_int_of_max_fitting_uint(self): + assert cel.evaluate("int(9223372036854775807u)") == 9223372036854775807 + + def test_int_of_huge_double_overflows(self): + with pytest.raises(OverflowError): + cel.evaluate("int(1e300)") + + def test_int_of_nan_and_infinity_overflow(self): + with pytest.raises(OverflowError): + cel.evaluate('int(double("NaN"))') + with pytest.raises(OverflowError): + cel.evaluate('int(double("infinity"))') + + def test_uint_of_negative_overflows(self): + with pytest.raises(OverflowError, match="unsigned integer overflow"): + cel.evaluate("uint(-1)") + + def test_in_range_conversions_still_work(self): + assert cel.evaluate("int(1.9)") == 1 + assert cel.evaluate("uint(3)") == 3 + assert cel.evaluate('int("-42")') == -42 + + +class TestParserFixes: + def test_negative_hex_literal(self): + assert cel.evaluate("-0x10") == -16 + assert cel.evaluate("0x10") == 16 + + def test_stacked_unary_operators_cancel(self): + assert cel.evaluate("--1") == 1 + assert cel.evaluate("!!true") is True + + def test_bytes_literal_rejects_unicode_escape(self): + # Per cel-spec, \u escapes are only valid in string literals. + with pytest.raises(ValueError, match="invalid bytes literal"): + cel.evaluate("b'\\u00e9'") + assert cel.evaluate("b'\\303\\251'") == "é".encode() + + +class TestOptionalEquality: + def test_optional_values_compare_by_content(self): + assert cel.evaluate("optional.of(1) == optional.of(1)") is True + assert cel.evaluate("optional.of(1) == optional.of(2)") is False + assert cel.evaluate("optional.none() == optional.none()") is True + assert cel.evaluate("optional.of(1) == optional.none()") is False diff --git a/tests/test_dual_mode_comprehensive.py b/tests/test_dual_mode_comprehensive.py index 2b649e0..0d62500 100644 --- a/tests/test_dual_mode_comprehensive.py +++ b/tests/test_dual_mode_comprehensive.py @@ -47,7 +47,7 @@ def test_string_literals_preserved_in_strict_mode(self): def test_string_comparisons_work_in_strict_mode(self): """Test that string comparisons work correctly in strict mode.""" test_cases = [ - ('var == "epa1"', {"var": "epa1", "value": 0.4}, True), + ('code == "epa1"', {"code": "epa1", "value": 0.4}, True), ('name == "test123"', {"name": "test123", "num": 3.14}, True), ('id == "42"', {"id": "42", "float_val": 1.5}, True), ('text != "abc123"', {"text": "xyz123", "other": 2.7}, True), @@ -223,11 +223,11 @@ def test_github_issue_16_regression(self): This is the core issue that was fixed - string literals should be preserved. """ # The original issue report case - record = {"var": "epa1", "var_2": 10, "var_3": 0.4} + record = {"code": "epa1", "var_2": 10, "var_3": 0.4} ctx = Context(record) # Test 1: String comparison should work - result = evaluate('var == "epa1"', ctx) + result = evaluate('code == "epa1"', ctx) assert result is True, "String comparison should work in strict mode" # Test 2: String function should preserve string diff --git a/tests/test_enhanced_error_handling.py b/tests/test_enhanced_error_handling.py index e263331..c9ef218 100644 --- a/tests/test_enhanced_error_handling.py +++ b/tests/test_enhanced_error_handling.py @@ -103,13 +103,13 @@ def test_missing_string_function_helpful_message(self): assert "lowerAscii" in error_msg assert "Undefined variable or function" in error_msg - def test_missing_type_function_helpful_message(self): - """Test that missing type() function provides helpful error message.""" + def test_missing_function_helpful_message(self): + """Test that an undefined function provides a helpful error message.""" with pytest.raises(RuntimeError) as exc_info: - cel.evaluate("type(42)", {}) + cel.evaluate("typeName(42)", {}) error_msg = str(exc_info.value) - assert "type" in error_msg + assert "typeName" in error_msg assert "Undefined variable or function" in error_msg def test_mixed_arithmetic_provides_conversion_examples(self): diff --git a/tests/test_issue16_string_literal_regression.py b/tests/test_issue16_string_literal_regression.py index b0a2935..c71d96c 100644 --- a/tests/test_issue16_string_literal_regression.py +++ b/tests/test_issue16_string_literal_regression.py @@ -15,10 +15,10 @@ class TestIssue16StringLiteralRegression: def test_string_comparison_with_float_context(self): """Test that string comparisons work correctly with floats in context.""" - record = {"var": "epa1", "var_2": 10, "var_3": 0.4} + record = {"code": "epa1", "var_2": 10, "var_3": 0.4} ctx = Context(record) - result = evaluate('var == "epa1"', ctx) + result = evaluate('code == "epa1"', ctx) assert result is True, "String comparison should work with floats in context" def test_string_literal_with_number_suffix(self): @@ -102,9 +102,9 @@ def test_escaped_quotes_in_strings(self): def test_control_case_without_floats(self): """Control test: verify behavior without floats in context.""" - ctx = Context({"var": "epa1", "var_2": 10}) # No floats + ctx = Context({"code": "epa1", "var_2": 10}) # No floats - result = evaluate('var == "epa1"', ctx) + result = evaluate('code == "epa1"', ctx) assert result is True, "Control test should pass without floats in context" def test_mixed_expressions_with_actual_numbers(self): @@ -140,11 +140,11 @@ def test_edge_case_empty_strings(self): def test_issue_specific_reproduction(self): """Direct reproduction of the original issue report.""" - record = {"var": "epa1", "var_2": 10, "var_3": 0.4} + record = {"code": "epa1", "var_2": 10, "var_3": 0.4} ctx = Context(record) # Test 1: The main issue - string comparison - result = evaluate('var == "epa1"', ctx) + result = evaluate('code == "epa1"', ctx) assert result is True, "Original issue case should return True" # Test 2: String function behavior diff --git a/tests/test_upstream_improvements.py b/tests/test_upstream_improvements.py index f3d0234..11cac4b 100644 --- a/tests/test_upstream_improvements.py +++ b/tests/test_upstream_improvements.py @@ -52,31 +52,16 @@ def test_substring_not_implemented(self): class TestTypeIntrospection: - """Test missing type introspection that should eventually be implemented.""" + """type() arrived natively in cel 0.14.5; these pin the behaviour we rely on.""" - def test_type_function_not_implemented(self): - """ - Test that type() function is not implemented. - - When this test starts failing, the type() function has been implemented. - """ - with pytest.raises(RuntimeError, match="Undefined variable or function.*type"): - cel.evaluate("type(42)") + def test_type_function_is_native(self): + """type() no longer needs the cel.stdlib shim, which has been removed.""" + assert cel.evaluate("type(42)") == "int" + assert cel.evaluate("type(42u)") == "uint" + assert cel.evaluate("type(null)") == "null_type" - @pytest.mark.xfail( - reason=( - "type() is still not a native function in cel 0.14.3; cel.stdlib provides a " - "string-returning type() as an opt-in extension" - ), - strict=False, - ) def test_type_function_expected_behavior(self): - """ - Test expected behavior of type() function when implemented. - - This test is marked as expected failure and will start passing - when type() is implemented upstream. - """ + """Behaviour previously tracked as an xfail; passes since cel 0.14.5.""" assert cel.evaluate("type(42)") == "int" assert cel.evaluate('type("hello")') == "string" assert cel.evaluate("type(true)") == "bool" @@ -99,7 +84,7 @@ def test_mixed_int_uint_multiplication_fails(self): @pytest.mark.xfail( reason=( - "Mixed signed/unsigned arithmetic still unsupported in cel 0.14.3, and CEL has " + "Mixed signed/unsigned arithmetic still unsupported in cel 0.14.5, and CEL has " "no implicit numeric coercion, so this may never change" ), strict=False, @@ -156,7 +141,7 @@ def test_map_mixed_arithmetic_currently_fails(self): @pytest.mark.xfail( reason=( - "map() with mixed int/double arithmetic still unsupported in cel 0.14.3; CEL " + "map() with mixed int/double arithmetic still unsupported in cel 0.14.5; CEL " "requires an explicit double(x)/int(x) conversion" ), strict=False, @@ -326,7 +311,7 @@ def test_reduce_function_not_available(self): @pytest.mark.xfail( reason=( - "fold()/reduce() need a parser-level comprehension macro. cel 0.14.3 expands " + "fold()/reduce() need a parser-level comprehension macro. cel 0.14.5 expands " "only has/all/exists/existsOne/map/filter, from a fixed table in " "parser/macros.rs, and custom functions receive already-evaluated arguments, " "so a fold has to land upstream: https://github.com/cel-rust/cel-rust" @@ -435,7 +420,7 @@ def test_upstream_improvements_summary(): "Optional values": ["optional.of()", "optional chaining (?.)"], "Map improvements": ["Mixed type arithmetic in map()"], "Bytes operations": ["bytes concatenation with +"], - "Logical operators": ["CEL-compliant behavior verified in cel 0.14.3"], + "Logical operators": ["CEL-compliant behavior verified in cel 0.14.5"], "Math functions": ["ceil()", "floor()", "round()"], "Validation functions": ["isURL()", "isIP()"], } diff --git a/uv.lock b/uv.lock index 252ac76..7d7239a 100644 --- a/uv.lock +++ b/uv.lock @@ -17,66 +17,66 @@ wheels = [ [[package]] name = "ast-serialize" -version = "0.8.0" +version = "0.11.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e1/a9/11851c3e02a3fea2ddc9932d1fdc7d2edaeecc0d2e11bc5f2a7fde2b0934/ast_serialize-0.8.0.tar.gz", hash = "sha256:6c37c43e4004dfb42d321ddedc569dc17ff4259296f3af577c9ea46a809bc010", size = 845638, upload-time = "2026-08-07T11:29:02.152Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7a/c2/feb42ca5bf2335aa16868bc53ec83f114923564763658d6a63e4c4c6ccde/ast_serialize-0.11.0.tar.gz", hash = "sha256:8b4b9862436eaf1442d6a16b7e138d4ff6ae558bdb6fde1c4cd87735093d5744", size = 953724, upload-time = "2026-09-08T14:58:39.804Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/34/16/6e520b57cd8c75914b38c670ad4593d13c22911e4306cc7165dab8b0789b/ast_serialize-0.8.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:3d822605fa7bb326ef868d25fafced7fc660fa46d9b90c02ea86d5e2f5d325f7", size = 863924, upload-time = "2026-08-07T11:27:34.579Z" }, - { url = "https://files.pythonhosted.org/packages/03/e1/48802de9b22a2bcad42ec80601a17e3f69172fe4f590e6311bcc2b323aeb/ast_serialize-0.8.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:2efa40b068197d5efb62655b43baadb842ed71c4958cccd3e8b86a35726f0119", size = 1177662, upload-time = "2026-08-07T11:27:36.196Z" }, - { url = "https://files.pythonhosted.org/packages/38/d4/323438db76bded3a1f3523a3167b8325916b2ddceb2107a330c6ec9fcf4d/ast_serialize-0.8.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:db1b957291bca08c7e72f43a12357b2948e20775d970e3fc3dac0aa3160ab725", size = 1167072, upload-time = "2026-08-07T11:27:37.646Z" }, - { url = "https://files.pythonhosted.org/packages/77/82/53c5400b54144b56de8ed7f957fd1ccd97e42482009292ab46121d15f8dd/ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdc0d5b18ff8fb364e87923e47c0a91d0d69dbcaeaa274591f7fd26892cc3a3a", size = 1225497, upload-time = "2026-08-07T11:27:39.225Z" }, - { url = "https://files.pythonhosted.org/packages/44/5f/36c07327a8b91303fbf1382c7c3e8a2902072dbe1b9546138a5288e75ff0/ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9da7330f3e235bf7da89b8d39205c6350fc0c08a85379743f2df9fff87d6d980", size = 1227101, upload-time = "2026-08-07T11:27:40.799Z" }, - { url = "https://files.pythonhosted.org/packages/9d/48/5adf5c67addc7ddb328122208c6d375a84cf154984f412b4087330a157bd/ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f3186969ee66a9863b00acc6523ace44c56974eecb348a7ea4b228d9f0b80e19", size = 1424001, upload-time = "2026-08-07T11:27:42.708Z" }, - { url = "https://files.pythonhosted.org/packages/38/a1/70074dd3869d2b0e934f91891d8d6b734361cd3b80f85ca7ece2e668ecdd/ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40a57b73731be45da4fa41430c4d5dc94a24b3a4faba7b9e069978c0402064ea", size = 1245545, upload-time = "2026-08-07T11:27:44.4Z" }, - { url = "https://files.pythonhosted.org/packages/e3/be/53b9c0a8a6399950c2e3546bdfab96d2b299d5b114b47eb94fd3c49c4054/ast_serialize-0.8.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5075b9da3ef807eda752502446dfecea3b381c4900b7e27a5d5f4f899eb39951", size = 1248961, upload-time = "2026-08-07T11:27:45.781Z" }, - { url = "https://files.pythonhosted.org/packages/eb/13/3651d3812548a2bda15e26e5dd51aadb48cf682d0865370255fcf0e367dd/ast_serialize-0.8.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:293cc1c5bfa741f8e3fbe8175b9c07beee487c9a6fdbb25a5acad9f1df2d30a9", size = 1243877, upload-time = "2026-08-07T11:27:47.325Z" }, - { url = "https://files.pythonhosted.org/packages/21/a0/521f0bf000f675e9312a4aae2c8ba7a992405d072a85c485e08fd59433b9/ast_serialize-0.8.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e0910c3442a75216dde0f102d854ba2aaa71d2482e0ee213630b9bf29584fba3", size = 1293903, upload-time = "2026-08-07T11:27:49.264Z" }, - { url = "https://files.pythonhosted.org/packages/b1/7e/402fc902568aa2ee65865a3e151f000db0153da8ce6b1be4c9c349025f8d/ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:43dd6d596879bb1cb8a12cc9dae7bb10090a39a35883026c24f82488a195619a", size = 1401070, upload-time = "2026-08-07T11:27:50.947Z" }, - { url = "https://files.pythonhosted.org/packages/ff/7c/97d4b66c057f1706fc8be6dd532cc77c988794357c8f4ffdb6adabb39562/ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:8c9d537f59e936392cfd3597789d1390304dd659efc3c486ce7f40fb6b8a9f53", size = 1502602, upload-time = "2026-08-07T11:27:52.364Z" }, - { url = "https://files.pythonhosted.org/packages/89/6f/72cc3b71562001bba46e898ccfbf1844f7939b3e28912736206102f2e5a8/ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:f0190a33d7f97c65e9069f7a7f40499eea6b5cbe260c558378109caf20ce934b", size = 1495848, upload-time = "2026-08-07T11:27:53.803Z" }, - { url = "https://files.pythonhosted.org/packages/a0/53/d6f629d1e49308b2f363dae028baa213ec222c9106fa1f7f0d1f7b41499a/ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:77308ae6c5cf5264cc0f01a7c556ec77a9e68eb1f61b093534d698139fdc3b14", size = 1556556, upload-time = "2026-08-07T11:27:55.342Z" }, - { url = "https://files.pythonhosted.org/packages/ee/22/340f35dd8dfc6d412d53dc20699ca014b8d228db923e8ed4759c512b162c/ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8d53a23f27e1ed3a36b2d26fd2a1a6228c8e85a1ed62ff7cdb44bd610769f20a", size = 1417822, upload-time = "2026-08-07T11:27:56.712Z" }, - { url = "https://files.pythonhosted.org/packages/11/29/6dde5c13fbebc051d3a6df4ec0a6fd1d5359333cc1193f7f609f3410b4d8/ast_serialize-0.8.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ffa5e7cb08f96fed9121f77b224151e41caf88feab9d652bb46c78202b6fbeda", size = 1445153, upload-time = "2026-08-07T11:27:58.275Z" }, - { url = "https://files.pythonhosted.org/packages/62/c5/f473a8ed030f7a0ca24b9849cca184677a50c053867a7b808c2e1289bbd3/ast_serialize-0.8.0-cp314-cp314t-win32.whl", hash = "sha256:fa70ed4dea0bb18b30a1789c77baa701d0ef30c474f2ccabdea61e25623a8827", size = 1063711, upload-time = "2026-08-07T11:27:59.793Z" }, - { url = "https://files.pythonhosted.org/packages/23/63/39e171fcd38ca057c2e1979d5ee81ac7a3502784abe3d83df7454f7a0978/ast_serialize-0.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d8b3c8eee4c1baef9d4e84d2a59a805501617127be42615cb48970b15b0892b6", size = 1103740, upload-time = "2026-08-07T11:28:01.405Z" }, - { url = "https://files.pythonhosted.org/packages/21/1c/d00762b399e7726d68d0a088cc946e3a4c60f1c6176f557608f672f627f3/ast_serialize-0.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:ac4f0a83c55a9b782f79ad55a5247b7db123c1db405959791c2ef886e9710c9f", size = 1076021, upload-time = "2026-08-07T11:28:02.947Z" }, - { url = "https://files.pythonhosted.org/packages/4c/11/911210c3c78923273a9211a2b6cfc4c8aa723b30dab3e1c8d19afb983b40/ast_serialize-0.8.0-cp315-abi3.abi3t-macosx_10_12_x86_64.whl", hash = "sha256:86b8a1e6d90467345356098b040150e82fbc26d24a7a202224b13dc1f6264ca0", size = 1177715, upload-time = "2026-08-07T11:28:04.654Z" }, - { url = "https://files.pythonhosted.org/packages/77/89/6282881c8587606638db153cbe21e1e0c4d1f3970dee1aa0610a1c62a026/ast_serialize-0.8.0-cp315-abi3.abi3t-macosx_11_0_arm64.whl", hash = "sha256:39e92ff8e8cb45947fe9007174b2950e1fb098e6abd00266a13cd3bcf6675068", size = 1169347, upload-time = "2026-08-07T11:28:06.1Z" }, - { url = "https://files.pythonhosted.org/packages/97/78/a9f846a03a340ff3728c915f23338ca742742f3292700559cdb3ad999b1e/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c85d8d18db5b2dfcb3b7e38a4d600ca35504c0ed8a6f75cd1c811e4ffe248a15", size = 1225916, upload-time = "2026-08-07T11:28:07.654Z" }, - { url = "https://files.pythonhosted.org/packages/c0/15/aba6ef8a988a6eceb6f0359589aac509e29ae2dba67fd9bfd5af0c3f13e7/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9830ff7e764f74d9eefb01170c61a9f0fd2c027dac5fcb72e064decd57d56371", size = 1227135, upload-time = "2026-08-07T11:28:09.504Z" }, - { url = "https://files.pythonhosted.org/packages/94/29/3f63d696ea7c5b8abadcecc3505be51bd900daaccc522ed8322fa5b05a93/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6479d9722a4cd21b578f5478074c41e6169f04811996ec881655560f703a5bba", size = 1425040, upload-time = "2026-08-07T11:28:11.044Z" }, - { url = "https://files.pythonhosted.org/packages/e2/5d/0aac338604ff59df5774d4304307898982252f325ff7cafe31d52fedcb65/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a63bed264e818cd83eec11feed0f50aa162542b91132ef58afebc857182763a5", size = 1246278, upload-time = "2026-08-07T11:28:12.519Z" }, - { url = "https://files.pythonhosted.org/packages/23/ca/9f1ef795bb724719532bd86dbec11e5b66857d3fbe9b6772baec0191a6ed/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d187197d234aa45d6cfa2b096be5f666e8cc2e7eb3722d0ab8926293cf5720c", size = 1250029, upload-time = "2026-08-07T11:28:13.896Z" }, - { url = "https://files.pythonhosted.org/packages/dc/25/5e061372d2ed953b9ba3b9c4f73de3b8e9234cda3f6c088db4686801d0e1/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_31_riscv64.whl", hash = "sha256:2d39a56282cfcc0d8eeea37267c754be59c98d48505c23b1dae5c6011f3813dd", size = 1243575, upload-time = "2026-08-07T11:28:15.37Z" }, - { url = "https://files.pythonhosted.org/packages/a8/c1/ae7da218053120635a4ca802366c69f707203641af95372eeb83f70dfd52/ast_serialize-0.8.0-cp315-abi3.abi3t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f7cc5f10386994c0f4844f1e6d6a97127e9b478660eb6dec2b257644f0acab64", size = 1294396, upload-time = "2026-08-07T11:28:16.813Z" }, - { url = "https://files.pythonhosted.org/packages/2e/89/271d1f49c5269fcddcc789ea3f25be401f6723fc1138aeda539f4d05516d/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_aarch64.whl", hash = "sha256:6102f2f985c2e542be85cd857678ec9356fefa792b93cadfadd31139f5696f27", size = 1401987, upload-time = "2026-08-07T11:28:18.333Z" }, - { url = "https://files.pythonhosted.org/packages/55/be/4e7d77fcf571ac7cb5cf7115a20c36642bd7d29473b45dfaaefeb9618f90/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_armv7l.whl", hash = "sha256:3a8660fe66667b76a6e9dccd1d33e66b229fde3b308db991c041609226c005b6", size = 1502904, upload-time = "2026-08-07T11:28:20.039Z" }, - { url = "https://files.pythonhosted.org/packages/8b/ae/ed1de2db7e019d4236fbc164ffa5ef9a6022a300a342bbf142d21b7c141e/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_i686.whl", hash = "sha256:e7266307e5fba39836edb79def8608887af48820508bff3c5f2941e1e04d1534", size = 1496967, upload-time = "2026-08-07T11:28:21.734Z" }, - { url = "https://files.pythonhosted.org/packages/92/89/5fea507fae5c5f18b7dc7f95e5c00956574b8c717b8fd2049c504fab0b18/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca7e6fd1ad845d1cc649dc2ecd499db2f8f46af5bf8da7b70dd858774cc038b", size = 1559041, upload-time = "2026-08-07T11:28:23.194Z" }, - { url = "https://files.pythonhosted.org/packages/42/71/478d69df21b64e064554a68134c94be304270316ca676a94e63c389a636a/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_riscv64.whl", hash = "sha256:2880350b13d3eae69a0d70bc1fb6c9bfaca4dbd0e20ba8cd1aa483080b56ff06", size = 1417367, upload-time = "2026-08-07T11:28:24.601Z" }, - { url = "https://files.pythonhosted.org/packages/5e/2d/8962dc8d5b3a9dc27b36f9db199afa25264c741505469d9ec10ffbfd2ba7/ast_serialize-0.8.0-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl", hash = "sha256:ab0f9a59f7d63d0d441b56b9a818b273705264352d5115cfee12e940e816d958", size = 1446178, upload-time = "2026-08-07T11:28:26.152Z" }, - { url = "https://files.pythonhosted.org/packages/4f/22/14d2ad4fd1d1bcd0dc687ca268e0630069f45162496260c0efb70ee0ea72/ast_serialize-0.8.0-cp315-abi3.abi3t-win32.whl", hash = "sha256:0485a25ef519c62e749ee3c1ad8070e591b380d67226349eb5a70b228dc1ac4a", size = 1063811, upload-time = "2026-08-07T11:28:27.864Z" }, - { url = "https://files.pythonhosted.org/packages/18/1d/84a327c0202a41aa5fdba3ade33904d6d8f3b9e6806fa83568d835395850/ast_serialize-0.8.0-cp315-abi3.abi3t-win_amd64.whl", hash = "sha256:bd84d60bca7079e741be4ac5dbe237751a59d7f6f9f0126b11880d63822cbe16", size = 1105518, upload-time = "2026-08-07T11:28:29.691Z" }, - { url = "https://files.pythonhosted.org/packages/8c/92/74556dec52fde85a2ad84ed159991b916241043788609c15d8b77e14570b/ast_serialize-0.8.0-cp315-abi3.abi3t-win_arm64.whl", hash = "sha256:057769b5921336eb2d9124f2a731b42ed05ffdac559b840dbdf6f3937cf153dc", size = 1076319, upload-time = "2026-08-07T11:28:31.282Z" }, - { url = "https://files.pythonhosted.org/packages/d1/5d/c650b1f2cc1e75193358da95a080261422e8cd10b66d7370b1688c9915c5/ast_serialize-0.8.0-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:a02cbed7d8bfdcdee88edaac12bd50d53d9953aaa2e1852ef078625be5f1c0b5", size = 852914, upload-time = "2026-08-07T11:28:32.929Z" }, - { url = "https://files.pythonhosted.org/packages/d9/e3/6142e920fec6ef7bccabd8c24ed8ed99f8bdc6cb8b065e1df7c6a3b2d667/ast_serialize-0.8.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:e1bd223df0f6c96b396975fa604cb33bce53d9b4a0185490be4c4a289f7c9c87", size = 1184007, upload-time = "2026-08-07T11:28:34.654Z" }, - { url = "https://files.pythonhosted.org/packages/a6/e9/6e8be8df02b35d85e2b8809f7f1cfa290bdf5882b55127a539d049482db0/ast_serialize-0.8.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:ddd3b61f45c132da66c5476b281891e08c1fd87fbdabe8a6973e1622efc85f06", size = 1177588, upload-time = "2026-08-07T11:28:36.318Z" }, - { url = "https://files.pythonhosted.org/packages/8c/80/7e0fd2e2e2aba257820db4a8657c4c356844d36b914b20a4af294bcfb902/ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f9caa63fad8241257ae401b5ff0a64026c6adb36b8e86cbe8782d9ea505daf6", size = 1234575, upload-time = "2026-08-07T11:28:37.772Z" }, - { url = "https://files.pythonhosted.org/packages/b0/6a/3bae0af06f9b1bae3001c44d64215f5b567877e7aae9ffd45db11c3a7647/ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3926fa117b5e65019853a2969966d11c7175af377a3425991f3fe73784412405", size = 1236015, upload-time = "2026-08-07T11:28:39.14Z" }, - { url = "https://files.pythonhosted.org/packages/6f/c4/ce2d41a1bc22508e82618901f7e10f2a5e2f9556553fea90624daf9875e2/ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:485f1113af805e9e170b95ef993ca3fbd4f89c04bab25c58b4fc632d854801ab", size = 1432808, upload-time = "2026-08-07T11:28:40.664Z" }, - { url = "https://files.pythonhosted.org/packages/1a/90/f5058f209756dd70e958b7538aaa82d25d24944baf9ec8ae6f27b06fcacc/ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3ccebbed24f1281062d5852353c72c47502955926cfcb8345ffb3a44d87ff3d3", size = 1256251, upload-time = "2026-08-07T11:28:42.223Z" }, - { url = "https://files.pythonhosted.org/packages/bf/32/7f77ea87fa0836daab706ed5cb7f903bb25fa26a77439011aee626af11d8/ast_serialize-0.8.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:252f883290d1cdb728eb7fe1d9a7221b88af5a329aae0bc91ddee4dafb820331", size = 1258574, upload-time = "2026-08-07T11:28:43.751Z" }, - { url = "https://files.pythonhosted.org/packages/eb/5a/75b82ad2725b5e8e8c742732f9e76c6738a292d0709e1f60d10a973730b4/ast_serialize-0.8.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:96abc072ad29db8d02194afd47d68987322622787daceae82398d7b69f3ba2e6", size = 1254075, upload-time = "2026-08-07T11:28:45.28Z" }, - { url = "https://files.pythonhosted.org/packages/4e/54/8c20ed4eea805516a3fd23dd4a721ce28c64f50f0e4b359969f60a8c97a6/ast_serialize-0.8.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9118ad3e369727060b2696fc4078f250ecffca4248ba87f537f55cea9f9dce06", size = 1301018, upload-time = "2026-08-07T11:28:46.851Z" }, - { url = "https://files.pythonhosted.org/packages/cb/5b/9f14430f12fe830b656fb38f8e2e05ee13b02a88967660bef46af0ab22a8/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f359df4bd921918af8bebd142a376c77511d7151cc8ba852760b587b5a4a54f3", size = 1409951, upload-time = "2026-08-07T11:28:48.312Z" }, - { url = "https://files.pythonhosted.org/packages/2d/3d/084882eca93c842bd4262591a071ec7f825340644035e51501208cc5a8d4/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:e94f9121d13fa36cbf21314783c77d05ae3a0868decd18cf5233fdcc6de49ac8", size = 1509544, upload-time = "2026-08-07T11:28:49.847Z" }, - { url = "https://files.pythonhosted.org/packages/ce/73/ea84852096c2036c61cc0b2f97b90242207419f534dc671060ee1c8e05cb/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:54f95b486018d262bcb387a9afd96f0da74508b442762b80c769454a6fbb3ee3", size = 1505671, upload-time = "2026-08-07T11:28:51.239Z" }, - { url = "https://files.pythonhosted.org/packages/cb/88/287b9a5300c1f2f651d259f670931b63110adc265b7613c885b44c5bc53d/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:4c38b915511e32bc718c49dbce98ff9af36bac0ad6a604f58000cd5e3aecdba7", size = 1563685, upload-time = "2026-08-07T11:28:53.112Z" }, - { url = "https://files.pythonhosted.org/packages/ee/f3/1bc3a79afcf0c2a8d2c37182d0d659d1545a9d7f7f6dc9cf3e63d6c17135/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:9a2ef9cf12f2de4f1028c42c1dd7d775255e0fb3e5bb48896c97e35ef52366fe", size = 1427977, upload-time = "2026-08-07T11:28:54.418Z" }, - { url = "https://files.pythonhosted.org/packages/5c/cd/440c798957e14e31776bfeb024d8fafe0bb1d5b89c51c2f067e69938f7b0/ast_serialize-0.8.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6f18048fe9f6dd266bd577cdec48bdcecb74faaa01fe941324435483b013ed2a", size = 1454335, upload-time = "2026-08-07T11:28:55.968Z" }, - { url = "https://files.pythonhosted.org/packages/4f/4a/587eb36dcc240a54c8660f599464516b469ecad96f0dbdb6bccbedb50745/ast_serialize-0.8.0-cp39-abi3-win32.whl", hash = "sha256:31883542dd6c94d178f5db3d32fbd69c5eb88b3a7c018e7ac8cc0c45195ddbed", size = 1068858, upload-time = "2026-08-07T11:28:57.541Z" }, - { url = "https://files.pythonhosted.org/packages/5f/a4/3e887bbd92164e183cb6e412c6a3e9198ddd446d7fe405958293ef5ef49c/ast_serialize-0.8.0-cp39-abi3-win_amd64.whl", hash = "sha256:861794565b06337005c1447ef23103a3d5a627d08bdc827870d00d0b28ef5f51", size = 1111839, upload-time = "2026-08-07T11:28:59Z" }, - { url = "https://files.pythonhosted.org/packages/25/6c/b400476d3ceba681ab929787edc9554f6d88fcc69435eb681b00fc0457a5/ast_serialize-0.8.0-cp39-abi3-win_arm64.whl", hash = "sha256:b2a5978662fd4db463dfb4b974d2b10ac6430b98f5333aabc7051909df3561d0", size = 1083655, upload-time = "2026-08-07T11:29:00.349Z" }, + { url = "https://files.pythonhosted.org/packages/b1/3f/5600ad9b3595277b305504b66b1470265ca41bab565e90b038fc5cf9357b/ast_serialize-0.11.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:9c47daae633c843dec15c5ff5f8ec9c471deecc5257dc1f47156ebb7cc8c5b91", size = 896402, upload-time = "2026-09-08T14:57:19.222Z" }, + { url = "https://files.pythonhosted.org/packages/35/0b/36fe3a3416cda93ac3a8a258b4649f508e9320a3a22f33a547c41dd59a97/ast_serialize-0.11.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:d9c73f6e08778d696f7452f9c61e914b3a0c5ec3f24f9664785550b001bb6bb6", size = 1234077, upload-time = "2026-09-08T14:57:20.683Z" }, + { url = "https://files.pythonhosted.org/packages/70/3c/31d83cade9cb7f31058f6bcd3d3a3cbf98da3306651fa09bbe99ee2e6743/ast_serialize-0.11.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:781657cd74567f5b814ce3529c636bb205824bdb86951e79a05d58190ce2599b", size = 1213612, upload-time = "2026-09-08T14:57:22.207Z" }, + { url = "https://files.pythonhosted.org/packages/9c/37/0d71b6c967e39fe6e27ca3d531777b6b27bb00b70bbd2eed307f8f486e35/ast_serialize-0.11.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79baeca550ad2d2eac4619e8b848a9ebe01c6c72bf90549dbb7935df83db8e29", size = 1280212, upload-time = "2026-09-08T14:57:23.655Z" }, + { url = "https://files.pythonhosted.org/packages/67/ba/6bc0ca3e5ac32fbb8fddd00e39fc7aa15176d82b5b224b7e535697000066/ast_serialize-0.11.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aea29e01c9ef7f9c46da1fccdbed1811cc2a85233d0c0d4ac9c04ffaf3c3352a", size = 1284422, upload-time = "2026-09-08T14:57:25.033Z" }, + { url = "https://files.pythonhosted.org/packages/5e/69/6e78c003ccd2fe991a63eeda10253c078648fa3a1b7b62be02a740138bd2/ast_serialize-0.11.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3e50f6d77d8f619e04625db5a72ab5c5256ab1b13d6de3dadbcaf3547711631d", size = 1552917, upload-time = "2026-09-08T14:57:26.423Z" }, + { url = "https://files.pythonhosted.org/packages/21/a3/5a6d829d097632983bbd40a97fc092789b4f015343f59a2415ec0ecb5af2/ast_serialize-0.11.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d13a1350eb5767501d4a32bbb31ae63c17ab1c9f13f41c08e7d28150f73ac138", size = 1300642, upload-time = "2026-09-08T14:57:27.869Z" }, + { url = "https://files.pythonhosted.org/packages/3f/0e/799dfe0f2fd481493b706daa69ce7e9b7f18d2479b1bb0d2f4046840e4cd/ast_serialize-0.11.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:09c38f1aa78fd664028486ad1e8e7567b88a47adf373a9e56cf1395012108edf", size = 1299654, upload-time = "2026-09-08T14:57:29.463Z" }, + { url = "https://files.pythonhosted.org/packages/a9/5f/86aa2ce867e8c1dbcf303bd6882be5ee2766c3c568ca8616cf3b99ba4d65/ast_serialize-0.11.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:666be7180941373dbef1083b6d5f8b566c8257afa96b21ac521df96272d4e8ef", size = 1307010, upload-time = "2026-09-08T14:57:30.891Z" }, + { url = "https://files.pythonhosted.org/packages/91/be/ad009798d604db9df3ea437b946cf8f13da06ef4d5074f99ed07a7be3fdd/ast_serialize-0.11.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5b08b50d364d80dfe49002c683e9753f6e703b6c9e230737fe22fc5272235448", size = 1355782, upload-time = "2026-09-08T14:57:32.201Z" }, + { url = "https://files.pythonhosted.org/packages/86/5f/be0b8ce90b2664af793bd19b38d95dfeee3565824f423d84d257d2c476f4/ast_serialize-0.11.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:f02d0905a1c1b81ead9b277a4b35c62698619a0625a73c114b81b26f75612a2d", size = 1457533, upload-time = "2026-09-08T14:57:33.746Z" }, + { url = "https://files.pythonhosted.org/packages/34/d7/350fe12e018a6a1d2d00190ba2ae8f186ab8d48d71bfb53e5fdf7c394f05/ast_serialize-0.11.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:635d63498882a5ba3b1170c6eaf1aa1c78026267e40dcbbdf4bc42b6d7babeeb", size = 1561072, upload-time = "2026-09-08T14:57:35.146Z" }, + { url = "https://files.pythonhosted.org/packages/38/fb/67c7a0186a4706a17b81a44faef1cb4600f8ce64d4c7dd6da137a18d5f0a/ast_serialize-0.11.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ed1a8c44bc0557bdc3dbcf9d38df843b72f9950ef1f92d95db7c45cc8efbf136", size = 1554747, upload-time = "2026-09-08T14:57:36.675Z" }, + { url = "https://files.pythonhosted.org/packages/bb/49/4792e5eaf90829342180e391db6637f59da8b13883ac785d5dabaaa90727/ast_serialize-0.11.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:c590495b1212d91bf696b3333c31ca1765c1b980d07bf5825f9278030211df67", size = 1686453, upload-time = "2026-09-08T14:57:37.959Z" }, + { url = "https://files.pythonhosted.org/packages/d8/0a/9fa47457229daf39b8d4e3aff4acea3f2339d9de526f1d0a68993563e687/ast_serialize-0.11.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:b19176a6f04aadca38a80ed4e070fef896db47901257df513dceb9c7fc4751ed", size = 1480191, upload-time = "2026-09-08T14:57:39.681Z" }, + { url = "https://files.pythonhosted.org/packages/b1/ba/5524a98069e865c8a79f9759574dd48d901852329bb89aee1eac7ddaf682/ast_serialize-0.11.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:1e185d0dc0712e8568eb0477bb29583341fb00542eff3246a39d3841ee9a0d9c", size = 1498159, upload-time = "2026-09-08T14:57:41.126Z" }, + { url = "https://files.pythonhosted.org/packages/6a/71/29a30eadded02092bbfa3a86a52b1040c6d6b166bc215703454c3b50b66b/ast_serialize-0.11.0-cp314-cp314t-win32.whl", hash = "sha256:01d6b2aaa91810a377ea06524388e2e77af3a32dd9e1870e38b3627534f195ce", size = 1117988, upload-time = "2026-09-08T14:57:42.431Z" }, + { url = "https://files.pythonhosted.org/packages/18/01/ef0a6955b5cd9880f699aa0c07a18cbbf783151399d1787dca6dae581ba4/ast_serialize-0.11.0-cp314-cp314t-win_amd64.whl", hash = "sha256:c077a1c8bb3645e49256f4d31679fa4a3cfe1455cbf99080ddb3bbd40afa2457", size = 1154448, upload-time = "2026-09-08T14:57:43.902Z" }, + { url = "https://files.pythonhosted.org/packages/9c/d7/d7662e3ab68ab03411e54defaff94a089732290778c74641657e46f63931/ast_serialize-0.11.0-cp314-cp314t-win_arm64.whl", hash = "sha256:9e488e94ba0fe4cef06391702387656e283a3fe77653976a9a95a92a15e6ff39", size = 1126018, upload-time = "2026-09-08T14:57:45.483Z" }, + { url = "https://files.pythonhosted.org/packages/2a/e1/cf820beb541ab4177a3566be92478e2f5cadfc1306c0cc5300c174dde1a3/ast_serialize-0.11.0-cp315-abi3.abi3t-macosx_10_12_x86_64.whl", hash = "sha256:75d12e18c8d6691ceda09f514de2effcac628b217c0b3ea17851d217bfdbdab8", size = 1234341, upload-time = "2026-09-08T14:57:47.197Z" }, + { url = "https://files.pythonhosted.org/packages/89/01/8859ba83facbb1d57720eec1262d01547df3f9269d527eba36b785137a29/ast_serialize-0.11.0-cp315-abi3.abi3t-macosx_11_0_arm64.whl", hash = "sha256:ee8928ae9305f921484239a97030146dbb674cc10327fdf84124c4a20f73382e", size = 1212409, upload-time = "2026-09-08T14:57:48.459Z" }, + { url = "https://files.pythonhosted.org/packages/91/b5/2938098537ea94c204f85cc34acc41fec8a7bd3986b8d617f84cf25e802c/ast_serialize-0.11.0-cp315-abi3.abi3t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c345fb4e035ca5db948b781d894f5d98d8a271497ce0fee319f9375d5d358c9b", size = 1280678, upload-time = "2026-09-08T14:57:49.787Z" }, + { url = "https://files.pythonhosted.org/packages/41/7b/4d36b08ecad936af6f09dac75ed30198ec9f6c615ffe9e478ed6dd1450bc/ast_serialize-0.11.0-cp315-abi3.abi3t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7523fce1258c810c277799557771e35a851e5c1f132d0a68ca4551675f868b7", size = 1286678, upload-time = "2026-09-08T14:57:51.106Z" }, + { url = "https://files.pythonhosted.org/packages/95/ea/2fc504ddb5ed27c78f9de75c1835c365973d16d8d7f94a10ddf47f903c42/ast_serialize-0.11.0-cp315-abi3.abi3t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d861d8232f6c1661b805f22c96c3923a76c8feed1a4e504cecc0eaa3cd4077e", size = 1556836, upload-time = "2026-09-08T14:57:52.564Z" }, + { url = "https://files.pythonhosted.org/packages/c0/56/36bd4b5a73178ffede18e20020a73e153809b4d4d44ba8b5cfa2f80be6d6/ast_serialize-0.11.0-cp315-abi3.abi3t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:93206e8059d23952475099967174b7a3f573ca7dc19bdcaa59dbfbf86d76e52b", size = 1301292, upload-time = "2026-09-08T14:57:54.052Z" }, + { url = "https://files.pythonhosted.org/packages/f1/b8/88fb5bb26cf5614174b74172118461c17511dbbd8f827f0bde4da7280da2/ast_serialize-0.11.0-cp315-abi3.abi3t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18e28f523669d07547795aac3d9a5cf9e7c8d6ddf3dd48fe2090009ab35d0f69", size = 1299691, upload-time = "2026-09-08T14:57:55.67Z" }, + { url = "https://files.pythonhosted.org/packages/81/45/382d0e3426efefda064ef24036c2ca5905f4e8efeadd87ef73df55e010da/ast_serialize-0.11.0-cp315-abi3.abi3t-manylinux_2_31_riscv64.whl", hash = "sha256:cd6b802249a22d0f44cee22452910a653493e4b974a8dbe401f6b85cb4d74219", size = 1308581, upload-time = "2026-09-08T14:57:57.061Z" }, + { url = "https://files.pythonhosted.org/packages/43/d0/71e43cd333fe46c984233819891a22648d4c7c1c3a7ae98d6e3945386c81/ast_serialize-0.11.0-cp315-abi3.abi3t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3f552edbf9e7e0fe69b1eda569cf775c2279e5f0b839727d63c39a73adaef966", size = 1356809, upload-time = "2026-09-08T14:57:58.494Z" }, + { url = "https://files.pythonhosted.org/packages/22/bc/b916b5a3ce58a2b540611dd7ece93e4015c30328f3d6459f79fc252d0825/ast_serialize-0.11.0-cp315-abi3.abi3t-musllinux_1_2_aarch64.whl", hash = "sha256:0ecc5e1282b8ce7c73fc204bde4eb3bad500784e1f0e14f0b9ea624124095821", size = 1458221, upload-time = "2026-09-08T14:57:59.798Z" }, + { url = "https://files.pythonhosted.org/packages/b4/bc/3173921ff69ad214bc54172c572719f792faf118bca3485f412bbf26716f/ast_serialize-0.11.0-cp315-abi3.abi3t-musllinux_1_2_armv7l.whl", hash = "sha256:2110f04937ac932c03839af266a57a8b29fd97b0789d500fa92782bdad70f475", size = 1562074, upload-time = "2026-09-08T14:58:01.096Z" }, + { url = "https://files.pythonhosted.org/packages/4f/69/49cbb574085b5d08f9384d1066f5041fea42e0d79d1f4f39c95cafb54897/ast_serialize-0.11.0-cp315-abi3.abi3t-musllinux_1_2_i686.whl", hash = "sha256:2fc6fcdbf95a358f3be9af5ee8ccad40e0ef61ed6b84b942003e5bd983ac4cc9", size = 1556027, upload-time = "2026-09-08T14:58:02.581Z" }, + { url = "https://files.pythonhosted.org/packages/cb/59/13a559d9a28ef6ea38904ee4e766b49860ba046a12842d7620668f3c57b7/ast_serialize-0.11.0-cp315-abi3.abi3t-musllinux_1_2_ppc64le.whl", hash = "sha256:6a5879e45a85c0cce453c1302250a9d644bab59c2d615e6720da03c2d1baffe3", size = 1689378, upload-time = "2026-09-08T14:58:03.889Z" }, + { url = "https://files.pythonhosted.org/packages/da/20/77d92e56456dc047c673fd9d1d2adfb64d767479ad4a4e1d7089e95030c0/ast_serialize-0.11.0-cp315-abi3.abi3t-musllinux_1_2_riscv64.whl", hash = "sha256:6cf3edf38d808e3f26094473f593feb3c05d68d4c53b366c9c3a1c3284438f71", size = 1482258, upload-time = "2026-09-08T14:58:05.219Z" }, + { url = "https://files.pythonhosted.org/packages/8c/41/eca650f9ed98f3c84f8d498b8f1268388090b71606afb0dede4eb977b449/ast_serialize-0.11.0-cp315-abi3.abi3t-musllinux_1_2_x86_64.whl", hash = "sha256:c912d84a7eed20aa51ce864a37e60c275a3c4f972056aab20247ec8d01b8457e", size = 1499691, upload-time = "2026-09-08T14:58:06.772Z" }, + { url = "https://files.pythonhosted.org/packages/9d/79/94e77924e793ca881d240f71fd5cf0929f05bcaf8e293b134ef8254643ad/ast_serialize-0.11.0-cp315-abi3.abi3t-win32.whl", hash = "sha256:f504a2c787d22822fcfa4297bbb014cef1dc06962a30d2710c8c1cd5cf8326ec", size = 1118536, upload-time = "2026-09-08T14:58:08.478Z" }, + { url = "https://files.pythonhosted.org/packages/be/f1/024c32d13b5c62df0bbc4bb37eea7b1b49068d77bacfbb1e82a83fb2260e/ast_serialize-0.11.0-cp315-abi3.abi3t-win_amd64.whl", hash = "sha256:d0ee62b0149144785e2ea158cade30a41d90446cbaeae5745cb996adcee99c68", size = 1155492, upload-time = "2026-09-08T14:58:10.016Z" }, + { url = "https://files.pythonhosted.org/packages/cd/14/671534a8129604577e1c1ada3f21b32982c46d18c21e4e3511c2da8011bf/ast_serialize-0.11.0-cp315-abi3.abi3t-win_arm64.whl", hash = "sha256:2468e68d7f5b6d80fb619f614734f46ab8c2d474437bcba16cf3f63b5e1b3f79", size = 1126547, upload-time = "2026-09-08T14:58:11.361Z" }, + { url = "https://files.pythonhosted.org/packages/c4/87/8e8fd3da5f5123e6ce75e60460a1e5580a203b0598ee6787f9cb86888186/ast_serialize-0.11.0-cp315-cp315-pyemscripten_2026_5_wasm32.whl", hash = "sha256:ce35aa812044357c2a2767964def40c06c7b1ecbb94d98c73715b7978a460beb", size = 896502, upload-time = "2026-09-08T14:58:12.761Z" }, + { url = "https://files.pythonhosted.org/packages/a5/52/0e5e3afe70f9bded7a4643734c685ddd2e33932e3fed9b29836fc87238fc/ast_serialize-0.11.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:d2e3fb7476f2ccc2c2e40155f8e04e6110be98b6f51e52cc5476f3be5b1a1956", size = 1238152, upload-time = "2026-09-08T14:58:14.081Z" }, + { url = "https://files.pythonhosted.org/packages/6a/91/0fc54081b97feb2fe440aa1b84f32920608fb5b93a25b42cee0b55a4900a/ast_serialize-0.11.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:fc0a2fc3335a72a750c84e2a8cf113e4265edc930ac1b64b5f52fb7685070e3a", size = 1227156, upload-time = "2026-09-08T14:58:15.406Z" }, + { url = "https://files.pythonhosted.org/packages/96/8b/fe9a2da2839f2b94db49ebbd3404aefc43daaa91d250116c1a8817b908e9/ast_serialize-0.11.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26803ffd2daac676b4acf6683d527af091ed2fbf1c7eca861216702c3296d408", size = 1289363, upload-time = "2026-09-08T14:58:16.804Z" }, + { url = "https://files.pythonhosted.org/packages/cb/41/b4d53de75b60e5b4bdffab76acfd4d25cde840080a1f5741f37f8d6dad42/ast_serialize-0.11.0-cp39-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c394f64c4a7aba67173dda8b70087b37c82dc899265dca160a9ccd0d2c9e1ff5", size = 1293293, upload-time = "2026-09-08T14:58:18.174Z" }, + { url = "https://files.pythonhosted.org/packages/b1/d6/337593438d847e78c93f26fc2eb670680759fe9c19e0975a82720e850b0c/ast_serialize-0.11.0-cp39-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce307fe34458a9fb87c660730796e55f977acf5c4e9c645a806faf3436d402a9", size = 1564305, upload-time = "2026-09-08T14:58:19.481Z" }, + { url = "https://files.pythonhosted.org/packages/cd/51/40aec6d8c3afc2e6cba24fe496ae43b43dfdcb3f84de96e0746bc4f83cd6/ast_serialize-0.11.0-cp39-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:82f67de691ae29aa44afc6fff5d7c77f93bd5218954757a9453ebdbe924cfb12", size = 1307996, upload-time = "2026-09-08T14:58:20.91Z" }, + { url = "https://files.pythonhosted.org/packages/6a/7a/53e67994ed4d19972f958cc69759caf71c28d3f7d094152affc1d47006c7/ast_serialize-0.11.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2605d538e17e9569643b5c0722da8d39b1d758391e2a1902f44abfe42b8f7f78", size = 1309997, upload-time = "2026-09-08T14:58:22.463Z" }, + { url = "https://files.pythonhosted.org/packages/b9/50/d3555436b54feb7a11affe579113f6fcacd848be2a505592162e5930fcca/ast_serialize-0.11.0-cp39-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:8dcae98b677ca0ed9988d09b83394db65385ca6f45b0ee8892e68c90e5d8df74", size = 1318566, upload-time = "2026-09-08T14:58:24.106Z" }, + { url = "https://files.pythonhosted.org/packages/a1/f6/e45e90b6c7798d9c042c3e8c12357edd16131f7ea779228d79caf0bb858c/ast_serialize-0.11.0-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8a2ed2669adf5e92f4d0cfd70a72c8f949c66309657eabb54a2c7a0ba2577f8d", size = 1364618, upload-time = "2026-09-08T14:58:25.582Z" }, + { url = "https://files.pythonhosted.org/packages/71/90/2f8705717d6816ed77d2378f118b9e7664dc73a2d34bd2a668dc0b8e7bfd/ast_serialize-0.11.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:60d3fd70362b539318e1149ca09df0d0f9ff03e7ea72b117453003a9d8598ab7", size = 1466509, upload-time = "2026-09-08T14:58:27.109Z" }, + { url = "https://files.pythonhosted.org/packages/80/72/fde49aae39cfddf9736df4911e12f66120c99ff6e002690e50cd24697417/ast_serialize-0.11.0-cp39-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:1241b3963a07bd474f0a5d53f054bbbda278c805efd1d7b4ce41d0d3c5becc1e", size = 1571073, upload-time = "2026-09-08T14:58:28.444Z" }, + { url = "https://files.pythonhosted.org/packages/25/87/f5a9d0ce56d417ea831d4627358884af3695db682f7f7bb167751e79f891/ast_serialize-0.11.0-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:a2fbc5cbff379354d6e07296f0f953955543f60134ffd91fb8f14fc0b4f1aeaa", size = 1566781, upload-time = "2026-09-08T14:58:29.713Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b0/af07c6974ef839dd2d4f2a2123e106a9a484a42786855b7a59281f8fe1f3/ast_serialize-0.11.0-cp39-abi3-musllinux_1_2_ppc64le.whl", hash = "sha256:0cc0c793063fe07e52244c66ceb2b2c5eecaa826dbb250fdeb7f0502e5697782", size = 1696239, upload-time = "2026-09-08T14:58:30.948Z" }, + { url = "https://files.pythonhosted.org/packages/20/67/c8b17c359650809ee00badf2179d90222f09e889662bead41a4695b0c00c/ast_serialize-0.11.0-cp39-abi3-musllinux_1_2_riscv64.whl", hash = "sha256:d475173e59fec5dd1bad84d8351c7f5230119b1d5c68bad93264657589a93043", size = 1491560, upload-time = "2026-09-08T14:58:32.576Z" }, + { url = "https://files.pythonhosted.org/packages/04/71/29ca37b4bc78d924e54d2a5d4daa6d5a142daf0b7f614996b651225079e3/ast_serialize-0.11.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:26bd819c06ee10df68dbcf2fb12c8fd2249bcadffe25ba7011f0686cbfd69b94", size = 1507743, upload-time = "2026-09-08T14:58:33.827Z" }, + { url = "https://files.pythonhosted.org/packages/54/5b/8f3381e22b86e3bdb74898ea4f7a15b54cca308a63e9e02753f99d6dd4fe/ast_serialize-0.11.0-cp39-abi3-win32.whl", hash = "sha256:4c4c2df749d1dc6bba9a9e8cc4b5c3dfc39a351fbfe4ce22ca49c2d488c7a7ce", size = 1124421, upload-time = "2026-09-08T14:58:35.332Z" }, + { url = "https://files.pythonhosted.org/packages/3a/b0/1ddfbc7aec32df2ed87ad830ee55854ddeceb2e8a8fcfae9b6ed57be0b4b/ast_serialize-0.11.0-cp39-abi3-win_amd64.whl", hash = "sha256:dd3c69e27b1be3172880bce2867c359106c28c5909f1ca6154bb7bf89847c419", size = 1162052, upload-time = "2026-09-08T14:58:36.674Z" }, + { url = "https://files.pythonhosted.org/packages/34/0b/32f3c8162cb5b33f24bea94503dbdd6b55aee72d367d23a55f1338f3e1b7/ast_serialize-0.11.0-cp39-abi3-win_arm64.whl", hash = "sha256:eb22d9300e7a064fa8c45e2c1e568a4e36c4c91487ea0da5e7f589905365c866", size = 1134422, upload-time = "2026-09-08T14:58:38.267Z" }, ] [[package]] @@ -259,14 +259,11 @@ wheels = [ [[package]] name = "click" -version = "8.4.2" +version = "8.5.0" source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/76/d4/81420972a676e8ffea40450d8c8c92943e7218a78fe9b64359836cc9876b/click-8.4.2.tar.gz", hash = "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", size = 338000, upload-time = "2026-06-24T17:45:15.148Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c7/0e/7fa0ef50764b67090eca4114772a2abf8b6148198475e54c660b97caeee6/click-8.5.0.tar.gz", hash = "sha256:ba0d2089de75ea0310e2dde03160e6ca10009947fb95a182f9b54021bb272e34", size = 382235, upload-time = "2026-08-26T13:33:14.56Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/fb/e2/79c688af8b210d232694e31e59da9f6ec747bae31c3f5946e4e9b98860d5/click-8.4.2-py3-none-any.whl", hash = "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76", size = 119243, upload-time = "2026-06-24T17:45:13.73Z" }, + { url = "https://files.pythonhosted.org/packages/58/50/6c0d534c5f134586a8e1ba4e330569e32f057e33372ae556463212fb4cd3/click-8.5.0-py3-none-any.whl", hash = "sha256:255bc9599cf7748b4b1a446ccc735421bd08a2ae529a8b88597d3de5664ee360", size = 125251, upload-time = "2026-08-26T13:33:12.928Z" }, ] [[package]] @@ -342,11 +339,11 @@ wheels = [ [[package]] name = "griffelib" -version = "2.2.0" +version = "2.3.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f0/b4/a767e91c606deefc447a96eaf59edd77397960b1d677dffd833ee8449831/griffelib-2.2.0.tar.gz", hash = "sha256:e1bc36fe9cd21d4b6b659b456346755e4cfdc5676c0a5214083126ee12612b3c", size = 227048, upload-time = "2026-08-16T14:04:58.383Z" } +sdist = { url = "https://files.pythonhosted.org/packages/27/af/018c10bc9edd42b6ef6db2e96b09542050d5253f9b195e74bc910b2d13ab/griffelib-2.3.0.tar.gz", hash = "sha256:7b0952caf5bca6afa4bb5ee8c6a2d183fe3f21b62efc5f6c7243cb2b26d2d115", size = 234534, upload-time = "2026-09-04T15:08:17.472Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f6/b6/f65ac785d4ac90dcf7c831ac6256f5dd4a19780f4e1575b2c0d6eeebe319/griffelib-2.2.0-py3-none-any.whl", hash = "sha256:d71c3bc2bbed9f958488634fe788b843a9f705d6d2838ca32cd6c25eeb64dfc4", size = 166779, upload-time = "2026-08-16T14:04:54.365Z" }, + { url = "https://files.pythonhosted.org/packages/41/63/e876e789525063c840ccfa8857febdabd6523bcef9ce7eb979b9305ea895/griffelib-2.3.0-py3-none-any.whl", hash = "sha256:1b8f9cd525681c26b1d6d574faa1371651e8459ca51d209684f50b8096ae06e0", size = 169423, upload-time = "2026-09-04T15:08:12.956Z" }, ] [[package]] @@ -592,23 +589,23 @@ wheels = [ [[package]] name = "maturin" -version = "1.14.1" +version = "1.15.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e7/b3/addd877f871fb1860d46d3a4f206ecb10b946c85846805e6367631926fd3/maturin-1.14.1.tar.gz", hash = "sha256:9d6577a62cd08e0ceba7a0db06fb098e0c9b1b3429bad747a4f3a18215a1b3df", size = 369637, upload-time = "2026-06-19T05:19:49.774Z" } +sdist = { url = "https://files.pythonhosted.org/packages/b9/c8/22e5e21b2679c9bce6415ca578034ca2cc9316be0642ae21e051a2d5198c/maturin-1.15.0.tar.gz", hash = "sha256:94b26cc8e8aba61a5f2099715fe640e18c5f678e9a500408b38761263954228a", size = 385504, upload-time = "2026-08-24T12:11:22.665Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/f4/f0/97c5a5bd9c71653a066c0976a484eaaae50b9369557838a4176b7b0bdaa5/maturin-1.14.1-py3-none-linux_armv6l.whl", hash = "sha256:522292398945442cdafa9daeb2271b2340fbde57027b818f923f88eab04174f8", size = 10207496, upload-time = "2026-06-19T05:19:09.321Z" }, - { url = "https://files.pythonhosted.org/packages/fe/83/294bca639b0e052f1e2f65199b3db258780c7d4e31408b934c9c974a1379/maturin-1.14.1-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:ffe5ad71f21d1e6603c4dd75f7fee34adf5ed5ebcebb692886549888ebb329ed", size = 19680113, upload-time = "2026-06-19T05:19:13.43Z" }, - { url = "https://files.pythonhosted.org/packages/43/b6/79c881410a3b1c187f7eb3d407aecae646c6a4433d630d72200359015e83/maturin-1.14.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:f3306078070c1508fd715b9116070cbcaff5959024272a9f1e6f5cb29768b86c", size = 10169205, upload-time = "2026-06-19T05:19:16.615Z" }, - { url = "https://files.pythonhosted.org/packages/93/9d/44b6f26dcb7f7a04c5501ac2dbb6ca1490150682baa525ca5860504f9eab/maturin-1.14.1-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:cd457cd88961156e26379e1155bd287cc0ec1c8b2f1582b0660fb31b87c8842d", size = 10188098, upload-time = "2026-06-19T05:19:19.736Z" }, - { url = "https://files.pythonhosted.org/packages/1a/bd/9c0d5d6983905ce2c9edaa073a7e89355a9cf7f396988e05d32f1c37785d/maturin-1.14.1-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:dfc54ae32e6fcb18302193ab9a30b0b25eefffba994ae13238974805533ef75e", size = 10627576, upload-time = "2026-06-19T05:19:22.713Z" }, - { url = "https://files.pythonhosted.org/packages/e5/33/b096412bd6a7cb399652b260666f901adf88a687181a6dbd6a3f89f0a94e/maturin-1.14.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:a131d912b5267e640bc96d70f4914e10590aed64082ec9abacba7cea52004224", size = 10085181, upload-time = "2026-06-19T05:19:25.69Z" }, - { url = "https://files.pythonhosted.org/packages/56/8d/08c3bf469c38a23c9e6c877e338193001eb604d010fedc08341974e38528/maturin-1.14.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:be18fc568fb76884c0205456336892a75105ec398e6b667cd777c6268bd06d69", size = 10026363, upload-time = "2026-06-19T05:19:28.904Z" }, - { url = "https://files.pythonhosted.org/packages/3a/a4/c4d1a92839f8745ab4aab988a7db884a79d6d710bd3b286fcf9316dece1a/maturin-1.14.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:994a0c8ba3ad8a92b3a9ee1b02645d200d610216b15cff5102b0fe65e8e08666", size = 13321347, upload-time = "2026-06-19T05:19:32.411Z" }, - { url = "https://files.pythonhosted.org/packages/b3/fa/170f04624d03fd07d2a8b1b67de83a127af93aef9eaa425839553347297b/maturin-1.14.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:be80866363e605d137991b491a741a84cde9ae350183c4c85f49690ca9aaaa65", size = 10877609, upload-time = "2026-06-19T05:19:35.448Z" }, - { url = "https://files.pythonhosted.org/packages/61/ad/1ae2e1d0ded282bf2c55ac13f0811d87deb425e200ae64a15785675dede9/maturin-1.14.1-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:5282dffd4b539d2be245f4e5b1a5ab6bc1033b58f4a4872f5833f9d43c954aa4", size = 10417316, upload-time = "2026-06-19T05:19:38.28Z" }, - { url = "https://files.pythonhosted.org/packages/fb/27/bf677183920718da49cd7982d6a3ffc440aad8919329f571d189f81b7bdf/maturin-1.14.1-py3-none-win32.whl", hash = "sha256:1a04de0a20188f95c721b5702eed18140bdcccb28c386797093eca3f62f4d4e0", size = 8931293, upload-time = "2026-06-19T05:19:41.183Z" }, - { url = "https://files.pythonhosted.org/packages/63/4b/585adeb9167b08d3cdff0032a938b0e72655c92003df4f52c3f696a1bcc2/maturin-1.14.1-py3-none-win_amd64.whl", hash = "sha256:3c9f94640ecc4895e94abaf834a0684430032c865b2748a36c12461fd9252fdd", size = 10314067, upload-time = "2026-06-19T05:19:44.389Z" }, - { url = "https://files.pythonhosted.org/packages/51/d4/dac8c0720ae246be1700afb6fbdbbea20fe35b13f6570b2f70faa005df77/maturin-1.14.1-py3-none-win_arm64.whl", hash = "sha256:15cea8fcb3ba47dd636f50092bb34baea8b04ac777392f23e6bf8a9a61efb894", size = 9718943, upload-time = "2026-06-19T05:19:47.49Z" }, + { url = "https://files.pythonhosted.org/packages/14/69/5c01b461044eb1f45ddcce006706eb88110c793cdb11c7ae0b5e08492e94/maturin-1.15.0-py3-none-linux_armv6l.whl", hash = "sha256:6bf6dc62e22d4dcfd5a51244ff0d58975fa4979c48209fe84159617648956d82", size = 10206220, upload-time = "2026-08-24T12:10:53.327Z" }, + { url = "https://files.pythonhosted.org/packages/eb/1f/2b431554e11687cdb1077e0cdadcc118c53f611086b3af00c8545a67c6a5/maturin-1.15.0-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:cd35772633f489841132bc8e71d6fc7f842df30b9c05cd5cdf1ee1ddcb744cc7", size = 19416513, upload-time = "2026-08-24T12:10:56.126Z" }, + { url = "https://files.pythonhosted.org/packages/51/36/e23a21cb34a648b711036b9b2fe1d4f3f4ee24f8db54215d73f1a9a3a3ec/maturin-1.15.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:c40b4eae7bf5ef1f4b1af8d623fe4105016f93578fb15b764e741d08ec3b92dd", size = 10014962, upload-time = "2026-08-24T12:10:58.486Z" }, + { url = "https://files.pythonhosted.org/packages/8c/80/33b15cb2d8f30f12c807955e8f2fd775027692904e30ec0784744ce8cd83/maturin-1.15.0-py3-none-manylinux_2_12_i686.manylinux2010_i686.musllinux_1_1_i686.whl", hash = "sha256:7eb066372f541f8eb4909c79c5d9bd0b9e8125980bdf1ec9e8aba23c6c8d6c55", size = 10196223, upload-time = "2026-08-24T12:11:00.696Z" }, + { url = "https://files.pythonhosted.org/packages/fe/91/b495e19e2f5c503b540452b2039115e7b2363867e8c5ad4179eb752fa92c/maturin-1.15.0-py3-none-manylinux_2_12_x86_64.manylinux2010_x86_64.musllinux_1_1_x86_64.whl", hash = "sha256:653020a63525bb224e5ab0adf02e17a2e08bc86dbea7fc1399c9a56d7529b99e", size = 10541186, upload-time = "2026-08-24T12:11:02.857Z" }, + { url = "https://files.pythonhosted.org/packages/5d/2b/2abff58037188d852b124871b1f0d720e1c2bfb3d4f1b03d87c52cd66488/maturin-1.15.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:0ebf9767892725083138e671c34482c660317a2f3d6a29fc0e0f34e9d8c99136", size = 10083468, upload-time = "2026-08-24T12:11:05.012Z" }, + { url = "https://files.pythonhosted.org/packages/3f/07/b7e9f8be99a6627849e81ac7b6694876bce8f50a92995fe17e3cf2610f0a/maturin-1.15.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.musllinux_1_1_armv7l.whl", hash = "sha256:7ab7eebffd7b8debca2265985de4eaeb332141276d24b9560b5ad484d4b3add1", size = 10047786, upload-time = "2026-08-24T12:11:07.042Z" }, + { url = "https://files.pythonhosted.org/packages/ca/ab/167e3cb7accee11b507dbe53e0e87aeccb376d44ae66284c96ee4df3a9fd/maturin-1.15.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.musllinux_1_1_ppc64le.whl", hash = "sha256:126e12e618b4db42f68c779a56d41f82a390145ba36ac3f621d057eb34f5ad9d", size = 13315332, upload-time = "2026-08-24T12:11:09.433Z" }, + { url = "https://files.pythonhosted.org/packages/14/4d/801379f646cbc6b00998e5289b0630a886be3a4ee4c75b6bc9b87478a7f1/maturin-1.15.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4f9d33e6c3f9615c8caceecbbbd440f8eb25a3ddeb687077682cd5eca2e9ae15", size = 10807183, upload-time = "2026-08-24T12:11:11.73Z" }, + { url = "https://files.pythonhosted.org/packages/89/27/2e612e1cbd1580e9e94d4722c227b5180dca27b32b955a34b79918aa1292/maturin-1.15.0-py3-none-manylinux_2_31_riscv64.musllinux_1_1_riscv64.whl", hash = "sha256:bf29beddd0c6708f112db51d5275fc28b28b9e9c9c5faae387eaef662918b176", size = 10413274, upload-time = "2026-08-24T12:11:14.04Z" }, + { url = "https://files.pythonhosted.org/packages/70/d8/202a7b4d75a51f20f84ec9ce3b7345b12b822207072164e2b1c6ef665125/maturin-1.15.0-py3-none-win32.whl", hash = "sha256:da649988be98e87e009e51b1bf0d301b6a301bc0cecbdd60d40d8ba60748d1ca", size = 8928744, upload-time = "2026-08-24T12:11:16.269Z" }, + { url = "https://files.pythonhosted.org/packages/40/dc/4e90da594986ba78dd3bc8a5921ecdcdb11085b22b02a412caab3b225601/maturin-1.15.0-py3-none-win_amd64.whl", hash = "sha256:552c2be4afd43fe8d5c9f3ec8d4c4756d973b8dcbe94c14084390301f50243e1", size = 10335085, upload-time = "2026-08-24T12:11:18.326Z" }, + { url = "https://files.pythonhosted.org/packages/8b/10/15d4314edf130955edf2dc237aa393a8a7c10f2b9b57b89fa2f61f915659/maturin-1.15.0-py3-none-win_arm64.whl", hash = "sha256:c7dc0c66c78d3debdd9c5aa807e861fbcbf07f3505d34b125df74c03986b0f48", size = 9713795, upload-time = "2026-08-24T12:11:20.83Z" }, ] [[package]] @@ -731,16 +728,16 @@ wheels = [ [[package]] name = "mkdocstrings-python" -version = "2.0.7" +version = "2.0.8" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "griffelib" }, { name = "mkdocs-autorefs" }, { name = "mkdocstrings" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/90/5d/1be1c7a49d8fa13dc80f66a85f53333d52cf5206911412006ffdff8fb9a0/mkdocstrings_python-2.0.7.tar.gz", hash = "sha256:8c49faf66d243072d7590a1b5dea028d9d7425fac191f54f096123a4a9c1a783", size = 201598, upload-time = "2026-08-17T16:56:18.239Z" } +sdist = { url = "https://files.pythonhosted.org/packages/c5/65/0db919b7c91bf033b42d04f15ff16a56f4edd6afb26e84d448359660ece3/mkdocstrings_python-2.0.8.tar.gz", hash = "sha256:34545b54681cf0b212aab95394d37b0f5326a93b102f6ad1df3d965c79384c9d", size = 201771, upload-time = "2026-08-31T20:16:06.698Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/b2/6d/77546d8c26f038fce314a507106954f76270f6c182488bcf9ac9721175df/mkdocstrings_python-2.0.7-py3-none-any.whl", hash = "sha256:1fce5fbfe4ffa6e8136a35351cdc97c3bf55219c7efbd3f92a82260f93235d60", size = 105387, upload-time = "2026-08-17T16:56:16.813Z" }, + { url = "https://files.pythonhosted.org/packages/0b/b7/a5a854d4e44853f26decc0c5e0d68df052399f3da344a313da4178f00816/mkdocstrings_python-2.0.8-py3-none-any.whl", hash = "sha256:e555d9ef53b0febdeae4dd603144d4f86ec90fef672276645ea3bb61232c3d24", size = 105443, upload-time = "2026-08-31T20:16:05.25Z" }, ] [[package]] @@ -850,11 +847,11 @@ wheels = [ [[package]] name = "platformdirs" -version = "4.11.3" +version = "4.11.7" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b8/d7/e7bfbc86e9f99ff7807e24de7703f032e9c9ba80bb355cf26e0e9bc5a75e/platformdirs-4.11.3.tar.gz", hash = "sha256:66a73d38a849810252df809a3d8bcbda8e26f6c189920e7535ad608a48dbb5ab", size = 33050, upload-time = "2026-08-13T22:43:27.52Z" } +sdist = { url = "https://files.pythonhosted.org/packages/69/b7/802a56eca9f2fac455b8bab5375a2647b0f0e14a2cd63ef077de3c4a7658/platformdirs-4.11.7.tar.gz", hash = "sha256:4f41487eeeeeb07f3a6625e61d9bc0ae6809f92d3386dbd74392fbb76108104d", size = 35127, upload-time = "2026-09-01T13:35:10.502Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/19/a9/c34aebedd3a4c9afe5101b1b8713710b3fec18087c8a36c35d2f909861bd/platformdirs-4.11.3-py3-none-any.whl", hash = "sha256:5ed065d443751de711da036041a7a214122efc4a4de393b3f4137ba5576540e7", size = 23491, upload-time = "2026-08-13T22:43:26.121Z" }, + { url = "https://files.pythonhosted.org/packages/27/6e/80993e10a0482f630cef528635789233224f36b1ffd11592aa15d13ff9ce/platformdirs-4.11.7-py3-none-any.whl", hash = "sha256:8a02cb259042c79d1cd0450facc2fe6dc9d303ae7901afbe33bf8ea0b188cef6", size = 23938, upload-time = "2026-09-01T13:35:09.02Z" }, ] [[package]] @@ -889,15 +886,15 @@ wheels = [ [[package]] name = "pymdown-extensions" -version = "11.0.1" +version = "11.0.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown" }, { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/21/a9/5f0c535ba3b08fe09270c16808e053a968868242ecbd5676d4e3a488bf28/pymdown_extensions-11.0.1.tar.gz", hash = "sha256:dd2905ae6fc5b75582fafb139a1266ffc754705efa902aa50067fa7ff4f94ec0", size = 857113, upload-time = "2026-07-02T17:59:22.955Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ad/17/2db4b414de89659144488e0d9c6c0bf0c8395841dc12d81d0532cc6ef310/pymdown_extensions-11.0.2.tar.gz", hash = "sha256:9506fcbe66fa355a775b768084334238dd6805020ac4b92bea0c0dda6f8f223d", size = 855419, upload-time = "2026-08-22T19:28:47.236Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/d6/54/da572c98c0b77626a91b5d3b89f0231d8bff5125c225420908632f8b342d/pymdown_extensions-11.0.1-py3-none-any.whl", hash = "sha256:db3943a62bab7e03af1364f0c4083e64b91fb097675a4b6cceccfbe9a77e5eb2", size = 269455, upload-time = "2026-07-02T17:59:21.271Z" }, + { url = "https://files.pythonhosted.org/packages/a6/43/9f45ec4d14e596efc32c925a78104934790438b0c0628b70d741016734ad/pymdown_extensions-11.0.2-py3-none-any.whl", hash = "sha256:259910762019732caa1dfd76f3faa62c59f191d46573e80bcb1d13c0f675bbe5", size = 269929, upload-time = "2026-08-22T19:28:45.389Z" }, ] [[package]] @@ -1025,27 +1022,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.16.3" +version = "0.16.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/61/b3/3213589383f8f1b3938781bd1278713f6d18621a14992b3e81fefb8a5ef9/ruff-0.16.3.tar.gz", hash = "sha256:e76d33a347661a84b5be6d043d0347fdc745dfdcf825a8f4fed64b5e26eebdf2", size = 4891904, upload-time = "2026-08-13T15:17:13.381Z" } +sdist = { url = "https://files.pythonhosted.org/packages/a4/7c/6adb35d70e7c027e308274557901c7e00fb3407750faf3620c184ae058cb/ruff-0.16.6.tar.gz", hash = "sha256:dcf8a73d2ff77e99dde91244b4da16feba7f14e6beeb4015dee7c5a909e99050", size = 4921251, upload-time = "2026-09-03T16:57:29.037Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/96/493770daebd68c0a67f1549fdf519f53be51fc435186c0585bcc272fd76c/ruff-0.16.3-py3-none-linux_armv6l.whl", hash = "sha256:0c5710e247a58a4521e66e124ba9a74655b414f61ba3a2e9e3811e11098f48f7", size = 10902799, upload-time = "2026-08-13T15:16:27.382Z" }, - { url = "https://files.pythonhosted.org/packages/5e/e6/2becf3942fddc29a29b8df47691d456fb1085391a694f74d84513251418c/ruff-0.16.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fe155130631a2471fd2e14a7a664a4dfbd7194b8229c3d7b2a40b21178639081", size = 11135539, upload-time = "2026-08-13T15:16:30.87Z" }, - { url = "https://files.pythonhosted.org/packages/3e/1e/4b8b72f0d006dbf19326aa99f9ca0ee2ff374187c4d301cf529a51aa06fe/ruff-0.16.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e2ed719e14aa64d895c2ee922594a90a43c861a93f0575a95ff8c47cdbd13eb9", size = 10475095, upload-time = "2026-08-13T15:16:33.259Z" }, - { url = "https://files.pythonhosted.org/packages/92/32/2201fa49ba1f6c101ee321e83f051ac7a4b8d07b0ef6b4d3f2772b302275/ruff-0.16.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e0b1da805eb043654645d74d5de1e5ce2edc686e40790d2b86f56d71cc06a84", size = 10668771, upload-time = "2026-08-13T15:16:35.65Z" }, - { url = "https://files.pythonhosted.org/packages/c3/66/4afc5c8363bd04d45effce1b7c8713ca037d7a6740b7451a2403a6e3a972/ruff-0.16.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a37bdea0bbe21780f590bf437d6412c8c4e1b6cd010f91a65c2c40c5e5f5f870", size = 10699568, upload-time = "2026-08-13T15:16:38.195Z" }, - { url = "https://files.pythonhosted.org/packages/53/fd/c67d246bf36bf1698551c56de39e95cd07f70e64433e0098e6267d77061b/ruff-0.16.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09571e6d1288ed9be475207a3ac04ada404f1cd898104be0f6ab8d7df438575b", size = 11499365, upload-time = "2026-08-13T15:16:40.623Z" }, - { url = "https://files.pythonhosted.org/packages/67/0b/00ecbceb99a263af7b12f6f05ac3c92bc47b905e91adc3f207a836e3bc01/ruff-0.16.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c18c5a101eb540010638cc1ff3c84944d3adb3df62b8d98ca8f22ba484d3413", size = 12311728, upload-time = "2026-08-13T15:16:43.564Z" }, - { url = "https://files.pythonhosted.org/packages/54/b2/b7b3bb54f4d3f7db504e476ad4ab8de530dceebe2c061384b2757ee419e8/ruff-0.16.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8457c44f15033c85ddbb77b15d451df9e24e4bd03b628396dd3610cedc3b8f82", size = 11699896, upload-time = "2026-08-13T15:16:46.209Z" }, - { url = "https://files.pythonhosted.org/packages/c7/30/4c468429ac195addc5ee1b717b6ab1b66632786737ca3b2ed3443fb0c26a/ruff-0.16.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:294b95c4ae0cda9388525c2047778aa758d6b8d4bb876fd4e9eaa3ebc92343eb", size = 11058736, upload-time = "2026-08-13T15:16:48.823Z" }, - { url = "https://files.pythonhosted.org/packages/43/67/7a113cdaddf24b64d7f75b1242a99d04c82fcef4f6921fdbb832beaffb5f/ruff-0.16.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:3d0c7c40c87c2a820509c31ba007968da6e1306468c067b2d82fbfdbcd0e8474", size = 11586911, upload-time = "2026-08-13T15:16:51.913Z" }, - { url = "https://files.pythonhosted.org/packages/f1/c1/2e66f24c0f3ead25a5e660111778685e505e5da353c82802bf49f0cbe7b9/ruff-0.16.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:9f738c0fdfa8eed0b2ce7fb27ee7258208a92a68d7949e62aa15164bc7b389da", size = 10954265, upload-time = "2026-08-13T15:16:54.763Z" }, - { url = "https://files.pythonhosted.org/packages/c2/ba/4cee23bf52cba9a058d3726de623624daf50ef9638868edd86f4126157f6/ruff-0.16.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fb785f0be25abe69d320415cd4f833b59e17ba7613d9ba6a958023b6bceb0a50", size = 10709886, upload-time = "2026-08-13T15:16:57.339Z" }, - { url = "https://files.pythonhosted.org/packages/82/df/7da7194fa5d9dc0a285f7e6fa5a4722e7c63faac0b45b614ded9314363a1/ruff-0.16.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c5536e3acfbf9563085aa2be7b13c629c3077e902afc5b941ac44024dbb9f506", size = 11210392, upload-time = "2026-08-13T15:17:00.171Z" }, - { url = "https://files.pythonhosted.org/packages/35/85/7795f6e817af050e7517bf3e7aa9b061cce70ef33d280aad902c956c1ecf/ruff-0.16.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a2d85c02f9b8e165d85e6779184d38c4132de12603dab59c51c28e22584f9e4d", size = 11626910, upload-time = "2026-08-13T15:17:03.299Z" }, - { url = "https://files.pythonhosted.org/packages/78/9b/475b927cf27a5cbbda3c7bafb69ed6ff77e1d7923d5d85f17c2749d7ae32/ruff-0.16.3-py3-none-win32.whl", hash = "sha256:388cdf2166642bd9b13d52b5932d3170f34f8abed7e8d9a855f1d84b83645a0a", size = 10931415, upload-time = "2026-08-13T15:17:05.726Z" }, - { url = "https://files.pythonhosted.org/packages/b2/99/e2a2bfc4fbf0a1e8a916bc9ebe6fe6c58cc34c28e0ffc6ce281d572d1c2e/ruff-0.16.3-py3-none-win_amd64.whl", hash = "sha256:e80a7d69ca2a6d1c4d352ec91458cdca6e56c83cdbcabd93e4abe1e53591d948", size = 11445993, upload-time = "2026-08-13T15:17:08.353Z" }, - { url = "https://files.pythonhosted.org/packages/69/3e/4132e539aed78c148854d4997a2685b0ed4dc4e87110b59ce528564e184e/ruff-0.16.3-py3-none-win_arm64.whl", hash = "sha256:b8ca152da82c1acc1fa8d5874b15951935f0eef46f10e6954c83859011b6178a", size = 11399302, upload-time = "2026-08-13T15:17:10.908Z" }, + { url = "https://files.pythonhosted.org/packages/a4/28/9cc1b79639e284ec103f43c88c644db4eb58cbd0ea1ca11f1193435369ac/ruff-0.16.6-py3-none-linux_armv6l.whl", hash = "sha256:61c368c26bf8e973e5ab14a2772de587bc068ea3f9a277f673380749b4898fb8", size = 10015638, upload-time = "2026-09-03T16:56:40.986Z" }, + { url = "https://files.pythonhosted.org/packages/71/11/627d342ef727ea7794edf74fe23d60a074b02c3acc2e9436684e782286ca/ruff-0.16.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ecf4f068e2e123e43a26e9db4e19524cc56563912404e83bbfca375757e45a32", size = 10220762, upload-time = "2026-09-03T16:56:44.681Z" }, + { url = "https://files.pythonhosted.org/packages/43/d9/b75668ce41e4c8d073d18d6d08672ba6906ce45d5c06ea4fdb2e84ce3853/ruff-0.16.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:99b62ea33baf130f50368798d841f0d95527b6d817bf31817b65dd058f1d314c", size = 9835082, upload-time = "2026-09-03T16:56:47.142Z" }, + { url = "https://files.pythonhosted.org/packages/99/97/123ab10b05cde889c107c20f5a9774955104b5552796a2a8584b089ae8eb/ruff-0.16.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fbf89013f2bb3f6835a6038ff658dc8a1b38c98dc8e724b964168ad4e881876", size = 9949304, upload-time = "2026-09-03T16:56:49.813Z" }, + { url = "https://files.pythonhosted.org/packages/3e/58/a4a2c59dd2e5b85929c912d9cac3056eb9ee8c7e75e9b9fe3e109174966b/ruff-0.16.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:56a67065e22efa6bc4d498299d3bb06c0c90aace8fac2068b5a12f9dc4d8d51d", size = 9840612, upload-time = "2026-09-03T16:56:52.368Z" }, + { url = "https://files.pythonhosted.org/packages/61/6a/ff8c8626a786c4f49d48ced4a752dadbca65f5263005f9c2416578194694/ruff-0.16.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e25cc89174874b176a157e4428d66761c2c0c006654419bf384f967f361ff1b1", size = 10543465, upload-time = "2026-09-03T16:56:55.089Z" }, + { url = "https://files.pythonhosted.org/packages/ad/bb/c47535923365f337b82e28192e4e9eef2176511007cfd99a62fc22df5dad/ruff-0.16.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0700580ed5303723cb3c11c2f1d2a8913ce77b7ea86646dddb887f5417a9ba70", size = 11267576, upload-time = "2026-09-03T16:56:57.791Z" }, + { url = "https://files.pythonhosted.org/packages/ba/50/e5119a5212b5cd63b51e1f4b25e7bd636a6668fc069a3160b108ad7e3c16/ruff-0.16.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:15f1d0b6e165a6e56567befb6629f8209271311d990bae0f37e6d065035ef5f3", size = 10781993, upload-time = "2026-09-03T16:57:00.666Z" }, + { url = "https://files.pythonhosted.org/packages/8b/98/083d8b4ef3c51a0d19db84367791cbe9f44e4b53343d19dfa83556e1cd9a/ruff-0.16.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d72c591a96986ee4268860e2b7235082129ca5e4cb9cbba653a4b57c11893757", size = 10317748, upload-time = "2026-09-03T16:57:03.428Z" }, + { url = "https://files.pythonhosted.org/packages/9a/29/68f7ff2c5ad95f19f00627ac2de95644e25fe47371ea60b2db1fd952315e/ruff-0.16.6-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:65a006baa18f33324325814c864daef03541d51564b98c517610ea756ab7003e", size = 10540096, upload-time = "2026-09-03T16:57:06.182Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f9/79a8f6de85968641d68a7863aeec577551924ef066a990a48ff93167beab/ruff-0.16.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:cd02a7bf1a21a8735228a3e8c95a9dc5cf86bd2a52194f4aaae2a5755b4de0f4", size = 10100494, upload-time = "2026-09-03T16:57:09.194Z" }, + { url = "https://files.pythonhosted.org/packages/d9/e8/b81a22d9b90c00b892ccf2fa2ac36fa95de4c13ab85aea3e73795cfe4651/ruff-0.16.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:31b36f1e5ad85e0737f09d2be4e512e2e283583c14015da3b9dc07359ac0fc88", size = 9843663, upload-time = "2026-09-03T16:57:12.168Z" }, + { url = "https://files.pythonhosted.org/packages/39/aa/54f516ec5e5a11c4afdceb1c454ebb054ffb96e4f4a1705580b4346abd35/ruff-0.16.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:61029b4ab4aa723fd3064fab96b1d814492596bf0c792679fffcbde1e1679953", size = 10282461, upload-time = "2026-09-03T16:57:15.077Z" }, + { url = "https://files.pythonhosted.org/packages/52/0b/38d0aa8aa32372b96dc44f97b22e576c4147808271aab7b2cb1e353d4445/ruff-0.16.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:9ac8998457832c2061709d900856b7ad271dace0cb41f346588d540162bfa718", size = 10728808, upload-time = "2026-09-03T16:57:17.797Z" }, + { url = "https://files.pythonhosted.org/packages/5e/e5/9e274e24eeb027640ffc7442f21239f16d17f47acec15ae34f32e03a5c79/ruff-0.16.6-py3-none-win32.whl", hash = "sha256:0b87d9d16fcb63e8018423ca1d50b7260f15cb2da33e30db4baad4183a948c25", size = 10049212, upload-time = "2026-09-03T16:57:20.55Z" }, + { url = "https://files.pythonhosted.org/packages/22/31/72472449414223ed1a2da236b992adbb1a2ae59e34794574810f60ce068e/ruff-0.16.6-py3-none-win_amd64.whl", hash = "sha256:10d21c51c3495d8eaea7b703a16592117ea6eb1d649e36335aa965ff1173eb39", size = 10556402, upload-time = "2026-09-03T16:57:23.501Z" }, + { url = "https://files.pythonhosted.org/packages/fc/07/d781f8f8e1ac24bef9f3269cf62ffb1407ca24c3a8f12e5e22874f90528c/ruff-0.16.6-py3-none-win_arm64.whl", hash = "sha256:7a976c79b958f94e50a022a19f0f8c87387448020935ec14fc74331bd0a7f2c5", size = 10412850, upload-time = "2026-09-03T16:57:26.416Z" }, ] [[package]] @@ -1068,7 +1065,7 @@ wheels = [ [[package]] name = "typer" -version = "0.27.1" +version = "0.27.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "annotated-doc" }, @@ -1076,9 +1073,9 @@ dependencies = [ { name = "rich" }, { name = "shellingham" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/ae/40/4a3db7990d1f62a53182aa96eaef57aeb2886a27f90a195bc66713565d31/typer-0.27.1.tar.gz", hash = "sha256:a79bef8469a79c45498e7b814ecf8d603cc7644e9acbd9e19cac0334240b18df", size = 203994, upload-time = "2026-08-03T14:41:03.438Z" } +sdist = { url = "https://files.pythonhosted.org/packages/16/f7/57713ba479fd405eb76de31404b2c744c289e336b2d999511ebf51e496f7/typer-0.27.2.tar.gz", hash = "sha256:269b7eb9d3c202ca84b4bc9618cb04ebb43d3d4d1e567e4c768607232c05f945", size = 204045, upload-time = "2026-08-28T10:26:55.046Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/43/89/9518bc0c3929bee36b3a4a8e3daddd6e03f92f9961c66d4983b837160543/typer-0.27.1-py3-none-any.whl", hash = "sha256:53150287edd11baeb4e4722c8e394fcdf8181c0ae89485cba8d25c778d5edd56", size = 122874, upload-time = "2026-08-03T14:41:04.391Z" }, + { url = "https://files.pythonhosted.org/packages/dc/bf/205d0004930ede8f542fb58f601526fccf4ae7626075ca1e6c4de5d3d652/typer-0.27.2-py3-none-any.whl", hash = "sha256:b3a5fc4342d5fc8fda8fc3010b1cf117e9249aab7fae800c2eff62fd3842d97d", size = 123130, upload-time = "2026-08-28T10:26:53.752Z" }, ] [[package]] @@ -1128,9 +1125,9 @@ wheels = [ [[package]] name = "wcwidth" -version = "0.8.2" +version = "0.8.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/34/74/c6428f875774288bec1396f5bfcbc2d925700a4dad61727fd5f2b12f249d/wcwidth-0.8.2.tar.gz", hash = "sha256:91fbef97204b96a3d4d421609b80340b760cf33e26da123ff243d76b1fda8dda", size = 1466253, upload-time = "2026-06-29T18:11:11.601Z" } +sdist = { url = "https://files.pythonhosted.org/packages/36/57/ed58088fafdf4c55a0ad6bde846502567645424d7ebf325230b9237f4085/wcwidth-0.8.3.tar.gz", hash = "sha256:d128512515fbf4612e0ff21fd6380399210318b7b54a9af59dff8454cf9730eb", size = 1458450, upload-time = "2026-08-28T18:10:06.875Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/96/42/3e5985a0a7e57de470b320c6d6a1a67c844f6737a587f3d44dd13d1819e7/wcwidth-0.8.2-py3-none-any.whl", hash = "sha256:d63947694a0539a1d51e01eda7caf800c291020e6cdd7e28ad7b14dd33ad4f85", size = 323166, upload-time = "2026-06-29T18:11:09.888Z" }, + { url = "https://files.pythonhosted.org/packages/c4/0e/57f6bb3024a597b2e8ec4aee710ffe62ddc95af2e2bb1ee7a7abdc22c68c/wcwidth-0.8.3-py3-none-any.whl", hash = "sha256:d5b73dba6158a595ec9370350e7f2637bcac8d6c5e4fde34f30fcffb6103a5e4", size = 331669, upload-time = "2026-08-28T18:10:04.909Z" }, ] From bb1691b75ceaa735849169e8250c60d4beb3be33 Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Wed, 9 Sep 2026 08:38:44 +1200 Subject: [PATCH 2/3] Pin setup-uv to v10.0.1; the action publishes no floating major tag past v7 --- .github/workflows/ci.yml | 4 ++-- .github/workflows/security.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e54d390..46ad906 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: - uses: actions/checkout@v7 - name: Install uv - uses: astral-sh/setup-uv@v10 + uses: astral-sh/setup-uv@v10.0.1 with: version: "latest" @@ -59,7 +59,7 @@ jobs: - uses: actions/checkout@v7 - name: Install uv - uses: astral-sh/setup-uv@v10 + uses: astral-sh/setup-uv@v10.0.1 with: version: "latest" diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 17d1403..a8cab5f 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -31,7 +31,7 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} - name: Install uv - uses: astral-sh/setup-uv@v10 + uses: astral-sh/setup-uv@v10.0.1 with: version: "latest" From db0e48ace835060fe85d5dc9b5f2d1a8c8c8d42e Mon Sep 17 00:00:00 2001 From: Brian Thorne Date: Wed, 9 Sep 2026 08:45:48 +1200 Subject: [PATCH 3/3] Map only the native int()/uint() range errors to OverflowError A Python callback raising an exception whose text ends in "overflow" was being reclassified as OverflowError by the suffix match. Match the two exact upstream messages instead, and pin the callback case with a test. --- src/lib.rs | 8 +++++++- tests/test_cel_014_behaviour.py | 12 ++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 3e592cd..f93f8c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -687,7 +687,13 @@ fn map_execution_error_to_python(error: &ExecutionError) -> PyErr { "A function was called without a required argument or method target.", ) }, - ExecutionError::FunctionError { function, message } if message.ends_with("overflow") => { + // cel-rust reports out-of-range int()/uint() conversions as a FunctionError with + // these exact messages. Match narrowly so a user callback whose own error text + // happens to end in "overflow" still surfaces as RuntimeError. + ExecutionError::FunctionError { function, message } + if (function == "int" && message == "integer overflow") + || (function == "uint" && message == "unsigned integer overflow") => + { PyOverflowError::new_err(format!( "Function '{function}' error: {message}. The value is outside the range of the target type." )) diff --git a/tests/test_cel_014_behaviour.py b/tests/test_cel_014_behaviour.py index 47eb375..a44f692 100644 --- a/tests/test_cel_014_behaviour.py +++ b/tests/test_cel_014_behaviour.py @@ -207,6 +207,18 @@ def test_uint_of_negative_overflows(self): with pytest.raises(OverflowError, match="unsigned integer overflow"): cel.evaluate("uint(-1)") + def test_user_function_overflow_message_stays_runtime_error(self): + # Only the native conversions map to OverflowError; a Python callback whose + # error text ends in "overflow" is an ordinary function failure. + context = cel.Context() + + def boom(_value): + raise RuntimeError("buffer overflow") + + context.add_function("boom", boom) + with pytest.raises(RuntimeError, match="buffer overflow"): + cel.evaluate("boom(1)", context) + def test_in_range_conversions_still_work(self): assert cel.evaluate("int(1.9)") == 1 assert cel.evaluate("uint(3)") == 3