Skip to content

LinopyYamlError names a dependency the product path does not have #389

Description

@FBumann

The public exception tree is rooted at LinopyYamlError:

LinopyYamlError
├── LanguageError  (SchemaError, DimensionError, PiecewiseExpansionError)
└── DataError

That name is left over from when this package was called linopy-yaml. It is now the sharpest place linopy leaks into a surface that does not use linopy:

  • lps.solve / build / write / check go YAML → polars → HiGHS and import nothing from linopy. The bare-install CI job proves it.
  • lpspec.linopy is not in __all__ — the shim is a submodule you opt into.
  • So on the product path, the only place a user meets the word "linopy" in normal use is the traceback of every error they hit.

A user who never installs the [linopy] extra still catches LinopyYamlError. That is confusing on its own, and actively misleading when the error is about a parquet file.

Why now

The breaking label reads "Changes the YAML surface; land before there are users." The same reasoning applies harder here — an exception class is caught by name in user code, so a rename gets more expensive with every install. docs/design/linopy.md currently has to carry a paragraph explaining the name, which is the tell.

Options

A — rename to LpspecError. Matches the package. Keep LinopyYamlError = LpspecError as a deprecated alias for a release or two, since except LinopyYamlError in user code should not break silently.

B — rename to ModelError. Reads better in a traceback and does not bind the tree to the package name. Risk: generic enough to collide conceptually with LanguageError, and "model" is overloaded (a linopy.Model is a different thing).

C — leave it. Costs nothing today and the docs explain it. Gets worse monotonically.

I lean A: the tree is already named after the package one level down (LanguageError, DataError are generic), so the root is the one place the package name belongs.

Scope

  • rename the class, alias the old name with a DeprecationWarning
  • __all__, errors.py, and the exception-tree line in docs/api.md and ARCHITECTURE's Python-surface table
  • tests/test_architecture.py pins __all__ against that table, so it fails until both move
  • the paragraph in docs/design/linopy.md under "It is not a runtime dependency" goes away

Related: #60 (the other place the two paths visibly differ), and docs/design/linopy.md, which was added to consolidate exactly this kind of thing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:apiNative entry points and CLIbreakingChanges the YAML surface; land before there are usersdecisionA question to be answered, not work to be done; closes by resolutionroadmapDecided yes: on the plan. Applied on resolution, replacing 'decision'

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions