Skip to content

fix: correct errors found while testing the interpretations - #1824

Merged
ariostas merged 4 commits into
scikit-hep:mainfrom
ariostas:fix/interpretation
Nov 10, 2026
Merged

ariostas merged 4 commits into
scikit-hep:mainfrom
ariostas:fix/interpretation

Conversation

@ariostas

@ariostas ariostas commented Nov 6, 2026 •

Copy link
Copy Markdown
Member

🤖 AI text below 🤖

Part of the split of #1814 (the list is in #1834). These bugs were found while writing the coverage tests of #1814, and tests/test_1824_fix_interpretation.py holds their regression tests: every test in it fails on main (for parametrized tests, at least one of their cases).

  • Containers
    • Objectwise std::maps read their string keys and values without a header, and an empty map has the same dtypes as the others.
    • A C array (AsArray) whose header has no byte count raises a DeserializationError instead of reading a wrong length. AwkwardForth finds the end of an array from its byte count rather than the end of the entry, and arrays of a NumPy dtype fall back from AwkwardForth.
    • AsArray and AsDynamic get __eq__ and __hash__, and AsDynamic.typename works for any model.
    • AsFIXME errors carry the chunk, cursor and file.
    • Values that are str subclasses print as strings.
  • Object and strided arrays
    • ObjectArray supports negative indexes, slices (step 1) and iteration from an offset.
    • StridedObjectArray items are recognized as numpy.void.
    • Strided objects with headers come out in native byte order, with their members in offset order.
    • When an object branch falls back from AwkwardForth, its machine is reset.
    • Pandas output of object branches gets the right interpretation.
  • Strings
    • The AwkwardForth reader of AsStrings reads big-endian lengths and accumulates offsets.
    • Baskets that mix StringArrays and Awkward arrays are concatenated.
  • Libraries
    • Awkward jagged and string arrays with 32-bit offsets no longer use ListOffsetArray32/ListOffsetArrayU32, which Awkward 2 doesn't have.
    • how="zip" with no arrays works.
    • The Pandas how docs and error say what a string how actually does.
  • Identification
    • Typename parsing doesn't index past the end of the tokens.
    • A Float16/Double32 title whose brackets don't hold a valid range is treated like one without brackets, instead of raising UnboundLocalError.
    • Leaf-lists with a count leaf are rejected before building their dtype.
    • awkward_form raises a TypeError for a dtype it can't represent.
    • awkward_form_of_iter keeps the fields of records and tuples, and recursively_fix_awkward_form_of_iter (which coffea calls) no longer calls awkward_can_optimize, which doesn't exist.
    • _content_cls_from_name strips suffixes from the right end.
  • Misc
    • JaggedArray.parents_localindex used uproot._util.win, which doesn't exist, so it always raised AttributeError.
    • TLeafG is registered.
    • Version 3 TStreamerElements are read with the range (fXmin, fXmax, fFactor) that only that version writes; reading one used to fail.
    • The str of an AwkwardForth node indents all of its children alike.
    • TRef keeps its reference number in its members, like other models.
    • TBasket.array passes final_array a dict, as every interpretation expects.
    • Unpickling a dynamic model doesn't skip attributes that a base class has.
    • reset_classes also reloads TClonesArray.
    • The TruncatedNumerical and language.python error messages no longer fail while being formatted.
    • CustomInterpretation and AsBinary compare by identity.

The reset_classes fixture in tests/conftest.py now puts the original model classes back afterward. Some tests here need that, because they run in the same process (with pytest-xdist) as a test that reloads the classes. #1823 makes the same change.

@codecov

codecov Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.70130% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 80.06%. Comparing base (39ff721) to head (f179574).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
src/uproot/interpretation/objects.py 90.90% 1 Missing ⚠️
Additional details and impacted files
Files with missing lines Coverage Δ
src/uproot/_awkwardforth.py 93.67% <100.00%> (+2.29%) ⬆️
src/uproot/_util.py 78.09% <100.00%> (+10.36%) ⬆️
src/uproot/containers.py 83.61% <100.00%> (+15.38%) ⬆️
src/uproot/interpretation/custom.py 88.75% <100.00%> (+3.22%) ⬆️
src/uproot/interpretation/identify.py 90.70% <100.00%> (+15.78%) ⬆️
src/uproot/interpretation/jagged.py 96.17% <ø> (+5.90%) ⬆️
src/uproot/interpretation/library.py 74.13% <100.00%> (+4.31%) ⬆️
src/uproot/interpretation/numerical.py 85.49% <ø> (+1.96%) ⬆️
src/uproot/interpretation/strings.py 90.65% <100.00%> (+17.16%) ⬆️
src/uproot/language/python.py 73.21% <ø> (+0.89%) ⬆️
... and 6 more

... and 3 files with indirect coverage changes

ariostas added a commit to ariostas/uproot5 that referenced this pull request Nov 6, 2026
The check that a sequence isn't equal to a string passed for anything but
True. The test of Node.__str__ expected its wrong indentation, which scikit-hep#1824
fixes; it is now there, with the right one. The test of Library equality in
test_0016 is deleted here, as test_names_and_equality covers it.

Assisted-by: Claude Code:claude-opus-5-5
ariostas added a commit to ariostas/uproot5 that referenced this pull request Nov 6, 2026
The edges of the variable-width axis spanned exactly fXmin to fXmax, so the
test couldn't tell the mean of the widths from (fXmax - fXmin) / fNbins. The
files that Rewritable opens are now closed after each test. The test of a
version 3 TStreamerElement leaves for scikit-hep#1824, which reads its range.

Assisted-by: Claude Code:claude-opus-5-5
These were found by the tests of scikit-hep#1814, which are the regression tests here.
The fixes are to containers (std::map, C arrays, AsDynamic and AsArray
equality and hashing), strided and object arrays, the Awkward and Pandas
libraries, string baskets, typename parsing, Float16/Double32 titles, TLeafG,
TRef, TBasket.array, and model pickling.

The reset_classes fixture now puts the original model classes back after
the test, so that tests running after it in the same process (with
pytest-xdist) compare against the classes they looked up.

Assisted-by: Claude Code:claude-opus-5-5
Version 3 of TStreamerElement writes fXmin, fXmax and fFactor after its
type name (later versions take the range from the title instead), and
reading one stopped before them, so a file with version 3 elements failed
to deserialize. The format for them was defined but unused.

Assisted-by: Claude Code:claude-opus-5-5
Children after the first were indented two spaces less than the first.

Assisted-by: Claude Code:claude-opus-5-5
Assisted-by: Claude Code:claude-opus-5-5
@ariostas

Copy link
Copy Markdown
Member Author

pre-commit.ci run

@ianna ianna left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ariostas - Thanks! LGTM.

@ariostas
ariostas merged commit f74da82 into scikit-hep:main Nov 10, 2026
21 checks passed
ianna pushed a commit that referenced this pull request Nov 12, 2026
* test: cover the interpretations

New tests from #1814, apart from the regression tests of its fixes.

Assisted-by: Claude Code:claude-opus-5-5

* test: tighten an equality check and drop the test of Node.__str__

The check that a sequence isn't equal to a string passed for anything but
True. The test of Node.__str__ expected its wrong indentation, which #1824
fixes; it is now there, with the right one. The test of Library equality in
test_0016 is deleted here, as test_names_and_equality covers it.

Assisted-by: Claude Code:claude-opus-5-5
ariostas added a commit to ariostas/uproot5 that referenced this pull request Nov 12, 2026
The edges of the variable-width axis spanned exactly fXmin to fXmax, so the
test couldn't tell the mean of the widths from (fXmax - fXmin) / fNbins. The
files that Rewritable opens are now closed after each test. The test of a
version 3 TStreamerElement leaves for scikit-hep#1824, which reads its range.

Assisted-by: Claude Code:claude-opus-5-5
ariostas added a commit to ariostas/uproot5 that referenced this pull request Nov 12, 2026
The check that a sequence isn't equal to a string passed for anything but
True. The test of Node.__str__ expected its wrong indentation, which scikit-hep#1824
fixes; it is now there, with the right one. The test of Library equality in
test_0016 is deleted here, as test_names_and_equality covers it.

Assisted-by: Claude Code:claude-opus-5-5
ianna pushed a commit that referenced this pull request Nov 12, 2026
* test: cover the interpretations

New tests from #1814, apart from the regression tests of its fixes.

Assisted-by: Claude Code:claude-opus-5-5

* test: tighten an equality check and drop the test of Node.__str__

The check that a sequence isn't equal to a string passed for anything but
True. The test of Node.__str__ expected its wrong indentation, which #1824
fixes; it is now there, with the right one. The test of Library equality in
test_0016 is deleted here, as test_names_and_equality covers it.

Assisted-by: Claude Code:claude-opus-5-5
ariostas added a commit to ariostas/uproot5 that referenced this pull request Nov 12, 2026
The edges of the variable-width axis spanned exactly fXmin to fXmax, so the
test couldn't tell the mean of the widths from (fXmax - fXmin) / fNbins. The
files that Rewritable opens are now closed after each test. The test of a
version 3 TStreamerElement leaves for scikit-hep#1824, which reads its range.

Assisted-by: Claude Code:claude-opus-5-5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/fix PR title type: fix (set automatically)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants