Skip to content

fix: regression with tuple coords entries as xarray's (dim_name, values)#766

Open
FBumann wants to merge 3 commits into
masterfrom
fix/xarray-tuple-coords
Open

fix: regression with tuple coords entries as xarray's (dim_name, values)#766
FBumann wants to merge 3 commits into
masterfrom
fix/xarray-tuple-coords

Conversation

@FBumann
Copy link
Copy Markdown
Collaborator

@FBumann FBumann commented Jun 5, 2026

Mandatory to pull this in before next release.
Fixes a bug which was introduced by the alignment refactor. tuple coords were treated differently. Its now consistent with v0.7.0 and xarray.
And additionally improving and reorganizing test coverage

Note

The following content was generated by AI.

Details

What

_coords_to_dict treated a tuple coords entry as a bare value sequence (like a list), which broke the standard xarray form coords=[("origin", origins)]: a scalar bound against such coords raised an inscrutable numpy "setting an array element with a sequence … inhomogeneous shape" error.

m.add_variables(lower=0, coords=[("origin", origins), ("dest", dests)])  # crashed

v0.7.0 delegated coords to xarray and supported this form; the alignment refactor in #742 (unreleased) regressed it and pinned the value-sequence reading in tests.

Fix

Restore xarray's convention in _coords_to_dict:

  • A tuple entry is (dims, data[, attrs]) — its first element names the dimension.
  • A bare value sequence uses a list (or range / ndarray).
  • Length-1 / scalar-value tuples raise a clear (dim_name, values) error, mirroring xarray's own rejection.

Unnamed pd.Index entries are now named on a copy so an entry's .name matches its dim consistently across forms (no caller mutation).

Tests

  • Dropped the rows that pinned the wrong value-sequence reading; added (name, values) coverage (parse-level + end-to-end), the multi-tuple scalar-bound regression, and tuple edge cases.
  • Restructured test_alignment.py's coords tests into form-parameterized tables and split the end-to-end add_variables checks into their own class.

Full test suite passes (3787 passed, 29 skipped).

Docs

Corrected the unreleased release note to state the xarray (dim_name, values) convention (the prior "bare-tuple entries behave like lists" wording described the regressed behaviour).

FBumann and others added 3 commits June 5, 2026 11:53
_coords_to_dict treated a tuple coords entry as a bare value sequence
(like a list), which broke the standard xarray form
``coords=[("origin", origins)]`` — a scalar bound against such coords
raised an inscrutable "inhomogeneous shape" error from numpy. v0.7.0
delegated to xarray and supported this form; the #742 alignment refactor
regressed it (unreleased) and pinned the value-sequence reading in tests.

Restore xarray's convention: a tuple entry is ``(dims, data[, attrs])``
(first element names the dimension), while a bare value sequence uses a
list. Length-1 / scalar-value tuples raise a clear convention error, as
xarray does. Also name unnamed pd.Index entries on a copy so an entry's
.name matches its dim consistently across forms.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Collapse TestCoordsToDict's per-section single-assertion tests into a few
form-parameterized tests (one table for naming forms, one for the skipped
unlabeled forms, one folding the five scattered "entry raises TypeError"
cases), dropping the # -- section comments in favour of the parametrization.

Move the end-to-end add_variables checks out of TestCoordsToDict into a new
TestAddVariablesCoords class, since they exercise the model wiring rather
than _coords_to_dict, and fold them into a single parametrized test.

No behaviour change and no coverage lost.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The fallback message in _coords_to_dict still advertised `tuple` as a valid
"unnamed sequence", which contradicts the (dim_name, values) tuple handling —
a user following it would hit the tuple-convention error instead. Name the
accurate forms (pd.Index / unlabeled list-range-ndarray / (dim_name, values)
tuple). Adds a scalar-value tuple case to the parametrized raises table.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@FBumann FBumann requested a review from FabianHofmann June 5, 2026 10:20
@FBumann FBumann changed the title Read tuple coords entries as xarray's (dim_name, values) fix: regression with tuple coords entries as xarray's (dim_name, values) Jun 5, 2026
Copy link
Copy Markdown
Collaborator

@FabianHofmann FabianHofmann left a comment

Choose a reason for hiding this comment

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

thanks for the follow-up and the tidying of the tests

Comment thread test/test_alignment.py
Comment on lines +578 to +588
([("x", [0, 1, 2])], None, ("x",)),
([pd.Index([0, 1, 2], name="x")], None, ("x",)),
([pd.Index([0, 1, 2])], ["x"], ("x",)),
([[0, 1, 2]], ["x"], ("x",)),
([range(3)], ["x"], ("x",)),
([np.array([0, 1, 2])], ["x"], ("x",)),
([[0, 1, 2]], None, ("dim_0",)),
([range(3)], None, ("dim_0",)),
([np.array([0, 1, 2])], None, ("dim_0",)),
([pd.Index([0, 1, 2])], None, ("dim_0",)),
([("origin", ["a", "b"]), ("dest", ["x", "y"])], None, ("origin", "dest")),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

crazy how many combinations this supports :D

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes...
But it always has. Its now just really obvious!

FBumann added a commit to fluxopt/linopy that referenced this pull request Jun 5, 2026
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.

2 participants