Skip to content

fix: correct awkward backend field-leak, behavior, and dict-input bugs#718

Draft
henryiii wants to merge 1 commit into
mainfrom
fix/awkward-backend
Draft

fix: correct awkward backend field-leak, behavior, and dict-input bugs#718
henryiii wants to merge 1 commit into
mainfrom
fix/awkward-backend

Conversation

@henryiii

Copy link
Copy Markdown
Member

🤖 AI text below 🤖

Part of #711.

Fixes several bugs in the Awkward backend (each verified before/after).

1. _wrap_result leaked stale px/py fields (HIGH)

The five per-branch "extra field" exclusion tuples in _wrap_result omitted the px/py momentum aliases, so the pre-computation px/py were carried into the output alongside the freshly computed x/y.

vector.register_awkward()
arr = ak.zip({"px": [1.0], "py": [2.0], "pz": [3.0]}, with_name="Momentum3D")
arr.rotateZ(0.1).fields  # before: ['x','y','px','py','pz']  -> after: ['x','y','pz']

Fixed structurally: the five hand-copied tuples are replaced with shared, geometry-tiered module-level frozensets (_azimuthal_fields, _longitudinal_fields, _temporal_fields and their unions) that include all generic and momentum-alias coordinate names. The tiering is preserved per branch (a pure-azimuthal return still carries longitudinal/temporal coordinates as extras).

2. Record methods lost behavior (MEDIUM)

When inputs are ak.Records/scalars, _wrap_result rebuilds length-1 arrays via ak.Array(...), which dropped the behavior dict. Without global registration the output was a behavior-less Record, so chaining a second method raised AttributeError.

# no register_awkward()
r = vector.Array([{"x":1.0,"y":2.0,"z":3.0}])[0].rotateZ(0.1)
r.rotateZ(0.1)  # before: AttributeError: no field named 'rotateZ'

Fixed by capturing the input record's behavior and passing it to the ak.Array(...) rebuilds. Regression test runs in a subprocess so global registration state cannot leak in.

3. vector.Array(dict) crashed (MEDIUM)

The docstring promises all ak.Array signatures, but only list/ndarray args were converted; a dict-of-columns raised AttributeError: 'dict' object has no attribute 'type'.

vector.Array({"x":[1.0,2.0],"y":[3.0,4.0]})  # before: AttributeError -> after: VectorArray2D

Fixed by also converting dict inputs via awkward.Array(...) (dask arrays still pass through unchanged).

4. __builtins__["zip"] (LOW)

dict(__builtins__["zip"](...)) relied on __builtins__ being a dict (a CPython implementation detail). Replaced with import builtins + builtins.zip(...).

5. Dead behavior-mutation loop (LOW)

The loop in vector.Array that set .behavior on temporary projected column arrays had no observable effect, since the final awkward.with_name(..., behavior=...) unconditionally replaces the output behavior. Removed.

Docstring fixes

Corrected copy-pasted docstrings: TemporalAwkward ("longitudinal" -> "temporal"), VectorAwkward4D (described itself as a momentum class), MomentumAwkward2D/3D/4D cross-references (Vector/Momentum swapped), and MomentumArray2D.allclose ("MomentumArray4D" -> "MomentumArray2D").

Tests

Added regression tests to tests/backends/test_awkward.py covering all five fixes. Full suite (--ignore=tests/test_notebooks.py): 817 passed, 3 skipped (dask_awkward/optree/jax not installed). Doctests and prek -a pass.

🤖 Generated with Claude Code

Fixes several bugs in the Awkward backend:

- _wrap_result leaked stale px/py coordinate fields, since the
  per-branch exclusion tuples omitted the px/py momentum aliases.
  Replace the five hand-copied tuples with shared, geometry-tiered
  frozensets that include all momentum aliases.
- Record methods lost their behavior: rebuilding scalar results via
  ak.Array dropped the behavior dict, so chaining two methods on an
  ak.Record raised AttributeError when vector was not globally
  registered. Preserve the input record's behavior on rebuild.
- vector.Array(dict) crashed with AttributeError; now dict-of-columns
  inputs are converted to ak.Array like lists/ndarrays.
- Replace __builtins__["zip"] (a CPython dict implementation detail)
  with builtins.zip.
- Remove a dead behavior-mutation loop in vector.Array whose effect was
  unconditionally overwritten by the final with_name(..., behavior=...).
- Fix copy-pasted docstrings (TemporalAwkward, VectorAwkward4D,
  Momentum cross-references, MomentumArray2D.allclose).

Assisted-by: ClaudeCode:claude-opus-4-8
@codecov

codecov Bot commented Jun 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.13%. Comparing base (3e32955) to head (0c83531).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #718      +/-   ##
==========================================
+ Coverage   87.09%   87.13%   +0.03%     
==========================================
  Files          96       96              
  Lines       11231    11229       -2     
==========================================
+ Hits         9782     9784       +2     
+ Misses       1449     1445       -4     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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