Add legacy/v1 arithmetic convention with deprecation transition#607
Merged
FBumann merged 11 commits intoharmonize-linopy-operations-mixedfrom Mar 10, 2026
Merged
Conversation
- Add `options["arithmetic_join"]` setting (default: "legacy") to control coordinate alignment in arithmetic operations, merge, and constraints - Legacy mode reproduces old behavior: override when shapes match, outer otherwise for merge; reindex_like for constants; inner for align() - All legacy codepaths emit FutureWarning guiding users to opt in to "exact" - Move shared test fixtures (m, x, y, z, v, u) to conftest.py - Exact-behavior tests use autouse fixture to set arithmetic_join="exact" - Legacy test files (test_*_legacy.py) validate old behavior is preserved - All 2736 tests pass Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Restrict options["arithmetic_join"] to {"legacy", "v1"} instead of
exposing all xarray join values (explicit join= parameter still accepts any)
- "v1" maps to "exact" join internally
- Add LinopyDeprecationWarning class (subclass of FutureWarning) with
centralized message including how to silence
- Export LinopyDeprecationWarning from linopy.__init__
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rename setting from 'arithmetic_join' to 'arithmetic_convention' - Update deprecation message: "will be removed in linopy v1" Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
8 tasks
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…y-operations-mixed+transition # Conflicts: # linopy/expressions.py # test/conftest.py # test/test_constraints.py # test/test_linear_expression.py
…n function - Resolve merge conflicts keeping transition layer logic - Restore NaN fillna(0) in _add_constant and _apply_constant_op - Restore simple finisher-based align() function (fixes MultiIndex) - Use check_common_keys_values in merge legacy path - Update legacy test files to match origin/harmonize-linopy-operations Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove dead check_common_keys_values function from common.py - Remove redundant default_join parameter from _align_constant, use options["arithmetic_convention"] directly - Gate fillna(0) calls in _add_constant and _apply_constant_op behind legacy convention check so NaN values propagate correctly under v1 - Fix legacy to_constraint path to compute constraint RHS directly instead of routing through sub() which re-applies fillna - Restore Variable.__mul__ scalar fast path via to_linexpr(other) - Restore Variable.__div__ explicit TypeError for non-linear division - Update v1 tests to expect ValueError on mismatched coords and test explicit join= escape hatches Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolve merge conflicts keeping convention-aware (legacy/v1) code paths. Under v1: exact join enforcement in operators, NaN propagation (no fillna), merge uses outer join for helper dims with pre-validation in __add__. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add return type annotations (Generator) to all v1_convention fixtures - Add importmode = "importlib" to pytest config to fix import mismatch when linopy is installed from wheel and source dir is also present - Use tuple literal in loop to fix arg-type error Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Top-level `import linopy` in conftest.py caused pytest to import the package from site-packages before collecting doctests from the source directory, triggering import file mismatch errors on all platforms. Move the import inside fixture functions where it's actually needed. Also revert the unnecessary test.yml and importmode changes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add a legacy/v1 arithmetic convention transition layer that makes all coordinate alignment behavior convention-aware, enabling a gradual migration to strict coordinate matching.
Core change:
linopy.options["arithmetic_convention"]Two modes:
"legacy"(default) — reproduces current behavior exactly (override join for matching sizes, left/outer otherwise,fillna(0)on NaN). EmitsLinopyDeprecationWarningon every legacy codepath."v1"— strict exact-join semantics: mismatched coordinates raiseValueErrorwith helpful messages suggesting explicitjoin=parameters. NaN values propagate (no implicitfillna).What changed in source
config.py: NewLinopyDeprecationWarningclass,LEGACY_DEPRECATION_MESSAGE, validation forarithmetic_conventionsettingexpressions.py: All arithmetic paths (_align_constant,_add_constant,_apply_constant_op,to_constraint,merge) branch on convention.__add__/__sub__onLinearExpressionandQuadraticExpressionpre-validate coordinates under v1 before callingmerge.common.py:align()reads convention, maps legacy→inner, v1→exact. Refactored to use finisher pattern for cleaner reconstruction.variables.py: Restored scalar fast path in__mul__, explicitTypeErrorin__div__for non-linear division.What changed in tests
test_linear_expression.py,test_constraints.py,test_algebraic_properties.py,test_common.py,test_typing.py): autouse fixture sets v1 convention; tests expectValueErroron coordinate mismatch and test explicitjoin=escape hatchestest_*_legacy.py): validate old behavior is fully preserved under"legacy"conftest.py: shared fixtures (m,x,y,z,v,u), lazyimport linopyto avoid CI doctest collection conflictRollout plan
"legacy"— nothing breaks. Deprecation warnings on legacy codepaths.linopy.options["arithmetic_convention"] = "v1""v1", keep"legacy"available"legacy"mode entirelyTest plan
pytest test/)mypy .)🤖 Generated with Claude Code