Legacy removal checklist (for linopy 1.0)#
The v1 convention ships alongside legacy from 0.x onward and replaces it
entirely at 1.0. This file enumerates everything to delete when that
release happens, in dependency order. Most edits are mechanical;
grep "LEGACY: remove at 1.0" finds every inline marker comment in the
source tree.
Implementation#
linopy/config.py#
Drop
LEGACY_SEMANTICS,V1_SEMANTICS,VALID_SEMANTICSconstants.Drop the
LinopySemanticsWarningclass.Remove the
semanticskey fromoptions. The option no longer exists; callers don’t need to opt in.Remove the v1/legacy validation branch in
set_value.
linopy/semantics.py#
Delete
is_v1()(always true). InlineTrueat the four import sites inexpressions.py/variables.pyor, better, delete the import and the now-deadelsebranches alongside it.Drop the legacy-warn branch from
check_user_nan/check_user_nan_breakpoints— both become a singleraise ValueError(...).enforce_merge_dims: drop its twowarn_legacybranches; the v1 raise on a mismatch or reorder is all that is left.Delete every
_legacy_*_messagehelper andwarn_legacyitself.shared_dim_mismatches,conflicting_aux_coord,absorb_absencestay — they’re v1 enforcement helpers.
linopy/expressions.py#
_add_constant: delete_add_constant_legacy; inline_add_constant_v1into the now-trivial dispatcher (or rename it to_add_constant)._apply_constant_op: same treatment with_apply_constant_op_legacy._align_constant: delete theelsebranch underif join is None:that handles the legacy size-aware default (other.sizes == self.const.sizespositional +reindex_likeleft-join paths). The explicit-join code below stays, as do the_broadcast_and_align/_reindexed_tohelpers.to_constraint: keep theif is_v1():body and delete theelsebranch (the legacy auto-mask: therhs_nan_maskplumbing plus therhs.reindex_like(..., fill_value=np.nan)pad).LinearExpression.isnull: drop the legacy(self.vars == -1).all(...) & self.const.isnull()branch —self.const.isnull()is the v1 answer.merge:The §8 / §11 legacy warns live in
enforce_merge_dims/enforce_aux_conflict; both calls stay, only their legacy branches go.The
skipna = not is_v1()simplifies toskipna = False(v1’s propagation rule).The trailing
if is_v1(): ds = absorb_absence(ds)becomes unconditional.
Drop the legacy
warn_legacymessage imports fromexpressions.py.
linopy/variables.py#
Variable.to_linexpr: drop theelsebranch (legacyreindex_like(fill_value=0).fillna(0)); make the v1reindex_like( fill_value=NaN) → .where(~absent)path unconditional. Theconst = NaN/0assign also becomes unconditional.Drop the
from linopy.semantics import is_v1import.
linopy/alignment.py#
_enforce_implicit_projections: drop the legacywarn_legacy(...)branch — the v1 raise for partial-level / coverage-gap projections becomes unconditional. The projection machinery itself (_project_onto_multiindex_levels,_LevelProjection) stays: full-coverage full-level projections remain legal under v1 (they are the same coordinate spelled differently, §8)._dims_for_unlabeled_operand: drop the legacy positional-pairing fallback (thewarn_legacy(...)branches plusreturn positional); the v1 size-pairing — theis_v1()block that raises on ambiguity / no-match — becomes the whole function. Theas_constant/_pair_axes_by_sizehelpers stay (v1-clean).
linopy/piecewise.py / linopy/sos_reformulation.py#
Nothing to remove; these are v1-clean (the drop=True / assign_coords
fixes from Slice P are correct for both semantics).
Tests#
test/conftest.py#
Drop the
LEGACY_SEMANTICS/V1_SEMANTICS/VALID_SEMANTICSimports and theLinopySemanticsWarningimport.Drop the
legacy/v1marker registration inpytest_configure.Delete the autouse
semanticsfixture entirely (no more parameterization, no more warning suppression).
test/test_legacy_violations.py#
Delete the file. Everything in it either documents legacy behaviour (gone) or tests v1 raises (covered by the per-module test files we add tests to alongside the implementation).
Before deleting, move any v1 tests that don’t have a per-§ home into the appropriate module:
TestExactAlignmentConstant,TestExactAlignmentMerge,TestBroadcastNonSharedDim→test_linear_expression.py.TestConstraintRHS→test_constraints.py.The rest are small enough to fold in alongside related tests.
test/test_convention.py#
Delete the file (it tests the
options["semantics"]framework, which is gone).
Marker stripping#
grep -rn "@pytest.mark.legacy\|@pytest.mark.v1\|pytestmark = pytest.mark.legacy" test/ finds every marker:
@pytest.mark.legacydecorators — delete the decorator (the test body is documenting old behaviour; deleting the whole test is usually right). Spot-check before each delete; a few “legacy” marks turned out to gate on legacy auto-mask semantics and the test itself stays valid under v1.@pytest.mark.v1decorators — strip the decorator (the test stays).pytestmark = pytest.mark.legacyat module level — was only used whilepiecewise.pywas non-v1-aware; removed in Slice P. Verify none remain.
Documentation#
doc/design/goals.rst#
Drop the entire “Transitioning goals” section (the three transitioning goals + the schedule are about the legacy bridge, which is gone).
Goal #4’s mention of
LinopySemanticsWarning(if any) goes.
doc/design/convention.rst#
Drop the
## Legacyframing if it exists. Each § already describes v1 directly; any “where today this does X” asides referencing legacy behaviour can go.Update the intro: “The strict (‘v1’) convention” → “The arithmetic convention” (drops the v1 framing now that there’s only one).
This file (doc/design/legacy-removal.rst)#
Delete after the 1.0 release ships.
Order of operations#
A safe sequence (each step compiles and tests pass):
Delete legacy test infrastructure (
test/conftest.pyfixture,test/test_convention.py,test/test_legacy_violations.pyafter moving v1 tests out).Strip
@pytest.mark.legacydecorators (the tests fail under v1 anyway once the legacy paths are gone — delete or update each).Delete legacy implementation branches in
expressions.py/variables.py.Delete
semantics.pylegacy bits (is_v1,warn_legacy, the_legacy_*_messagehelpers and the warn branches that call them).Delete
config.pysymbols (LEGACY_SEMANTICS, the warning class, the option key).Update
doc/design/goals.rstanddoc/design/convention.rst.Delete this file.