feat(paf): @stat(pushdown=...) declares engine push-down support#788
feat(paf): @stat(pushdown=...) declares engine push-down support#788paddymul wants to merge 4 commits into
Conversation
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: eaf8081fe1
ℹ️ 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".
| stat_func = StatFunc(name=func.__name__, func=func, requires=requires, provides=provides_keys, | ||
| needs_raw=needs_raw, column_filter=column_filter, quiet=quiet, default=default) | ||
| needs_raw=needs_raw, column_filter=column_filter, quiet=quiet, default=default, | ||
| pushdown=tuple(pushdown)) |
There was a problem hiding this comment.
Guard against string input in
pushdown normalization
pushdown=tuple(pushdown) treats a single backend string like an iterable of characters, so @stat(pushdown="xorq") is stored as ('x','o','r','q') instead of ('xorq',). This silently corrupts the metadata and will prevent downstream push-down matching when callers use the natural single-string form for one backend. Consider special-casing str (or validating input types) before tuple normalization.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Resolved in e811b0f (the commit after the one Codex reviewed): pushdown_norm = (pushdown,) if isinstance(pushdown, str) else tuple(pushdown). Codex's P2 caught the bug between the failing-test commit and the fix commit on the same PR.
📦 TestPyPI package publishedpip install --index-strategy unsafe-best-match --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ buckaroo==0.14.3.dev26198814263or with uv: uv pip install --index-strategy unsafe-best-match --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ buckaroo==0.14.3.dev26198814263MCP server for Claude Codeclaude mcp add buckaroo-table -- uvx --from "buckaroo[mcp]==0.14.3.dev26198814263" --index-strategy unsafe-best-match --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ buckaroo-table📖 Docs preview🎨 Storybook preview |
Codex P2 on #788: ``tuple(pushdown)`` treats a single backend string as an iterable of characters, so ``@stat(pushdown="xorq")`` is silently stored as ``('x','o','r','q')``. Pin the natural single-string form so the fix in the next commit is regression-protected. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Codex P2 on #788. ``@stat(pushdown="xorq")`` was silently stored as ``('x','o','r','q')`` because ``tuple(str)`` iterates a string into characters. Treat ``str`` as the single-backend form before the tuple normalisation. List/tuple inputs are unaffected. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Extends
@stat()with apushdown=parameter so individual stat functionscan declare which backends they support engine-side push-down on (e.g.
("xorq", "polars")). Stored asStatFunc.pushdown: Tuple[str, ...],default
()(pandas-only / requires materialization).Foundation for an upcoming protocol extension that will let lazy /
deferred backends compute summary stats by pushing the aggregation down
to the engine rather than materializing the frame. This PR is just the
metadata plumbing — no scheduler / consumer code yet.
Changes
pushdown: Tuple[str, ...]field onStatFuncdataclass.pushdown=kwarg on thestat()decorator. Tuple-normalised so acaller can pass a list without breaking hashability downstream.
Tests
empty pushdown, explicit pushdown round-trip, and list-to-tuple
normalisation.
stat_func.pychanges. All three tests pass.🤖 Generated with Claude Code