Add sum() to the extended stdlib, refresh dependencies and modernise CI - #39
Merged
Conversation
cargo update within the existing semver ranges: cel 0.14.0 -> 0.14.3, pyo3 0.29.0 -> 0.29.2, plus transitive bumps (regex 1.13, serde 1.0.229, thiserror 2.0, uuid 1.24). Rust tests, clippy, the Python suite (463 tests) and mypy/ty all pass on the refreshed lockfile. Ruff 0.16 started formatting Python code blocks inside Markdown, which made `ruff format --check .` fail on 14 docs/README files even though no Python source changed — the next push to main would have failed the lint job purely from the unpinned `ruff>=0.12.7`. Exclude Markdown from the formatter (doc snippets are still executed by tests/test_docs.py) and pin ruff to the 0.16 line so formatting is reproducible. Also pass a sorted list rather than a generator to `pytest.mark.parametrize` in tests/test_docs.py: passing a non-Collection iterable is deprecated and becomes an error in pytest 10.
Closes the aggregation half of #14. `cel.stdlib`'s `core` library now provides `sum` alongside `min`/`max`, following Kubernetes' CEL list library: all numeric types plus `duration`, `sum([])` == 0, booleans rejected rather than counted as 1/0, and no mixing of numbers with durations. Both call forms work, so `items.map(i, i.weight).sum()` reads the way the issue asked for. `fold`/`reduce` cannot be implemented here. A CEL function receives evaluated arguments, whereas a fold needs its accumulator expression left unevaluated and re-bound per element, and cel 0.14's comprehension macros are expanded by the parser from a fixed table (has/all/exists/existsOne/map/filter) that is not extensible from outside the crate. That is now stated in the stdlib docstring and the standard-library reference, with the upstream pointer. Upstream direction checked while doing this: cel-rust 0.14.0 deliberately dropped `min`/`max` from its default overloads, cel-go keeps only `math.greatest`/`math.least`, and neither has `sum`, `fold` or `reduce` — so aggregations belong in this wrapper's opt-in stdlib, while fold/reduce stay an upstream feature request. Also refreshed the upstream-watch trackers, which still cited cel 0.11: the aggregation xfail is split into a fold/reduce tracker and a native-sum tracker, and the remaining reasons now name 0.14.3 and say when the behaviour is CEL-spec mandated rather than a gap.
- Stop ignoring uv.lock and commit it, so CI resolves the same Python dependencies as local development. Refresh with `uv lock --upgrade`. - Test Python 3.13 and 3.14 in CI alongside 3.11 and 3.12. Verified locally: the extension builds under PyO3 0.29 and the full suite passes on both. - Run the Python security scan as `uvx safety scan`: `safety check` is retired, and using uvx keeps the scanner out of this project's dev dependencies instead of mutating pyproject.toml mid-workflow. - Move the Claude workflow from the deprecated `@beta` tag to `anthropics/claude-code-action@v1`.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 20a90139fe
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…k boundary
Both points raised in review are real in effect but are properties of the
Python-function boundary rather than of sum(): `min`, `max` and `math.abs`
already return an int for uint input, and `cel.evaluate('duration("1ns")')`
already yields timedelta(0) with no stdlib function involved. Python has a single
integer type and timedelta has microsecond resolution, so neither can be fixed
inside a Python callback — the honest fix is to stop implying otherwise.
The module docstring, the standard-library reference and sum()'s own docstring
now state that a uint sum returns an int (so `sum([1u, 2u]) + 1u` has no
overload, while the native `[1u, 2u][0] + 1u` works) and that sub-microsecond
durations are rounded before a function sees them, and both behaviours are
pinned by tests so a future change is deliberate.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #14.
Three related pieces of work: finishing the aggregation functions, refreshing dependencies, and making CI reproducible. Happy to split if you'd rather review them separately.
sum()— closes #14cel.stdlib'scorelibrary now providessumalongsidemin/max, following Kubernetes' CEL list library (the implementation the issue asked to match):All numeric types plus
duration;sum([])is0; booleans are rejected rather than counted as1/0; numbers and durations cannot be mixed. Both call forms work, since CEL treatsx.f()asf(x).Why
fold/reduceare not in this PRThey cannot be implemented in this wrapper:
FunctionContext.argsisVec<Cow<dyn Val>>. A fold needs the accumulator expression left unevaluated and re-bound for each element.has,all,exists,existsOne,map,filter) are expanded by the parser from a fixedmatchinparser/macros.rs, which isn't extensible from outside the crate.So
fold/reducehave to arrive in cel-rust. This is now documented in thecel.stdlibdocstring and in the standard-library reference, and the xfail tracker for it is kept so we notice if upstream adds it.Upstream check (the "implement it upstream instead" question)
Checked against cel-rust
mainat v0.14.3 and cel-go, and the answer differs per function:minormaxby default" — and cel-go's math/lists extensions havegreatest/leastbut nosum. None ofmin/max/sumare in the CEL spec; they're extension-library functions everywhere they exist, which is exactly whatcel.stdlibis. cel-rust's own docs even usepub fn sum(Arguments(args): Arguments)as the example of a user-defined variadic function.fold/reduceare upstream-only, for the reasons above.Dependencies
cargo updateinside the existing semver ranges: cel 0.14.0 → 0.14.3, PyO3 0.29.0 → 0.29.2, plus regex 1.13.1, serde 1.0.229, serde_json 1.0.151, thiserror 2.0.20, uuid 1.24.1.uv.lockis now committed (removed from.gitignore) so CI resolves the same Python dependencies as local development.CI
main. Ruff 0.16 began formatting Python code blocks inside Markdown, so with today's ruffruff format --check .fails on 14 README/docs files even with no Python change — the next push tomainwould have failed the lint job purely from the unpinnedruff>=0.12.7. Markdown is now excluded from the formatter (docs snippets are still executed bytests/test_docs.py) and ruff is pinned to the 0.16 line.uvx safety scan—safety checkis retired, and uvx keeps the scanner out of this project's dev dependencies instead of mutatingpyproject.tomlmid-run.@betatag toanthropics/claude-code-action@v1.tests/test_docs.pypasses a sorted list rather than a generator topytest.mark.parametrize— deprecated, and a hard error in pytest 10.Verification
cargo fmt --check,cargo clippy --all-targets --all-features -D warnings,cargo test,ruff format --check,ruff check,mypy python/cel,uvx ty check, and the full pytest suite (472 passed, 1 skipped, 6 xfailed) — all clean, on Python 3.11, 3.13 and 3.14.Generated by Claude Code