Skip to content

refactor: remove obsolete length argument from reverse aggregation calls - #1698

Open
samukweku wants to merge 2 commits into
devfrom
audit-rev-ranges-remove-length
Open

refactor: remove obsolete length argument from reverse aggregation calls#1698
samukweku wants to merge 2 commits into
devfrom
audit-rev-ranges-remove-length

Conversation

@samukweku

@samukweku samukweku commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

Summary

Every _*_rev_* wrapper in _agg_functions.py (and the size_rev
equivalents) still declared and forwarded a length: int parameter to
janitor_rs. On the Rust side that parameter was already obsolete
everywhere it survived -- either unused entirely (the plain starts/ends
shape derives its own bound from index.len()) or only ever feeding a
HashMap::with_capacity() preallocation hint, never correctness or
bounds-checking. This is the Python-side half of janitor-rs's own
"drop the unused length parameter from every reverse kernel" change.

What changed

  • Removed length from every _*_rev_* wrapper's signature in
    _agg_functions.py, and from every call site (plus the now-dead
    length = ... local-variable computations that fed them) in
    _get_join_aggs.py. No accumulation logic or output changed.
  • Added tests/functions/test_conditional_join_agg_boundary.py: focused,
    non-hypothesis tests that call each modified _agg_functions wrapper
    directly with a small hand-computed fixture -- one per reverse-aggregation
    shape (no_range, starts, ends, starts_matches, ends_matches,
    starts_ends, starts_ends_matches, positions, plus size's
    no-arr/booleans variants) -- and a parametrized regression guard
    asserting none of the 37 touched wrappers declares a length parameter
    any more. These are intentionally narrower and faster than the existing
    turtle-marked property tests in test_conditional_join.py (which
    already cover this boundary end-to-end and continue to pass unchanged);
    the point here is to catch a Python/Rust signature mismatch specifically
    -- the exact failure mode this whole change is about.

Testing

Verified against a janitor-rs build carrying the matching Rust-side
removal:

  • The 49 new tests in test_conditional_join_agg_boundary.py: all pass.
  • The full existing test_conditional_join.py suite: 242 passed, 1
    skipped. The only 36 failures were ModuleNotFoundError: No module named 'numba' from a missing optional dependency in the verification
    environment -- unrelated to this change (a separate, numba-accelerated
    code path that never touches _agg_functions.py/_get_join_aggs.py).

Before merging

This needs a janitor-rs release with the matching Rust-side length
removal -- until then, every touched call will raise
TypeError: unexpected keyword argument 'length' against the currently
pinned range (janitor-rs>=0.6.1,<0.7). Landing order should be
janitor-rs first, then this.

Scope

Rebased directly onto current dev (previously stacked on the unmerged
1649-simplify-conditional-join-rust-boundary branch, which this no
longer depends on) and expanded to cover every remaining shape that still
had length, not just the narrower no_range/size/prod_starts_matches
subset the branch covered before. #1684, #1686, and #1690 remain separate,
untouched PRs.

Every _*_rev_* wrapper in _agg_functions.py (and the size_rev equivalents)
still declared and forwarded a length: int parameter to janitor_rs. The
Rust side never used it for anything but a HashMap::with_capacity() hint
(or, for the plain starts/ends shape, didn't use it at all) -- see
janitor-rs's own "drop the unused length parameter from every reverse
kernel" change, which this is the matching Python-side half of.

Removed length from every _*_rev_* wrapper's signature and from every
call site in _get_join_aggs.py, including the now-dead length = ...
local-variable computations that fed them. No accumulation logic or
output changed.

Add tests/functions/test_conditional_join_agg_boundary.py: focused,
non-hypothesis tests that call each modified _agg_functions wrapper
directly with a small hand-computed fixture (one per reverse-aggregation
shape), plus a parametrized regression guard asserting none of the 37
touched wrappers declares a length parameter any more. These are
intentionally narrower and faster than the existing `turtle`-marked
property tests in test_conditional_join.py (which already cover this
boundary end-to-end and continue to pass) -- the point here is to catch
a Python/Rust signature mismatch specifically, the failure mode this
whole change is about.

Verified against a janitor-rs build carrying the matching Rust-side
removal: all 49 new tests pass, and the full existing
test_conditional_join.py suite passes (242 passed, 1 skipped; the only
36 failures are a missing optional `numba` dependency in the verification
env, unrelated to this change).

This lands only once janitor-rs ships a release with the matching
Rust-side length removal -- until then it will raise
`TypeError: unexpected keyword argument 'length'` against the currently
pinned janitor-rs range (>=0.6.1,<0.7).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KoekYAMwQGYVJqypwtUJf9
@samukweku
samukweku force-pushed the audit-rev-ranges-remove-length branch from 6922544 to c5cb7e5 Compare August 28, 2026 02:02
@samukweku samukweku changed the title refactor: remove redundant reverse aggregation length arguments refactor: remove obsolete length argument from reverse aggregation calls Aug 28, 2026
@github-actions

github-actions Bot commented Aug 28, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://pyjanitor-devs.github.io/pyjanitor/pr-preview/pr-1698/

Built to branch gh-pages at 2026-08-28 04:36 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant