Conversation
…pe checkers Fixes #72. The heatmap CLI's --export-data branch used `plt` at plotting/cli.py:133 without importing it. Every other function in that file imports matplotlib.pyplot locally, but heatmap() does not, and there is no module-level import, so the export path raised NameError: name 'plt' is not defined. No test went through the CLI command, which is why it survived; the existing plotting tests call create_heatmap and export_heatmap_data directly. Adds a regression test that invokes the command with --export-data. Confirmed it fails with that exact NameError without the one-line fix. The three remaining F821 errors are the "pyarrow.Table" return annotations in the Dremio adapter. pyarrow is optional and imported lazily inside the methods that need it, so the names never resolve for a type checker. Adding a TYPE_CHECKING import fixes that without introducing a runtime import or a hard dependency. Ruff violations in the two touched files go from 26 to 25 and from 8 to 5. The lockfile is deliberately untouched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CGdbAo1cW9QBR2u8JBWDdK
There was a problem hiding this comment.
🟡 Changes recommended
The new test’s backend configuration can become collection-order dependent, and there is also an unused import introduced in the touched hunk that should be removed to avoid persistent lint noise.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR addresses the ruff F821 undefined-name crash in the plot heatmap --export-data CLI path (issue #72) by ensuring matplotlib.pyplot is imported before use, and improves static typing for optional pyarrow return annotations in the Dremio store without adding a runtime dependency. It also adds a regression test that exercises the CLI export path via CliRunner.
Changes:
- Fix
heatmapCLI--export-datapath to definepltbefore it’s referenced. - Add a
TYPE_CHECKING-onlypyarrowimport so"pyarrow.Table"annotations resolve for type checkers. - Add a new pytest regression test that invokes the
plot heatmapcommand with--export-data.
File summaries
| File | Description |
|---|---|
tests/test_plotting/test_heatmap_cli_export.py |
New regression test covering the CLI --export-data path. |
src/linkml_store/plotting/cli.py |
Imports matplotlib.pyplot as plt in the export branch to avoid NameError. |
src/linkml_store/api/stores/dremio/dremio_database.py |
Adds TYPE_CHECKING import for pyarrow to satisfy type checkers for "pyarrow.Table". |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| import csv | ||
| from pathlib import Path | ||
|
|
||
| import matplotlib | ||
| import pytest | ||
| from click.testing import CliRunner | ||
|
|
||
| matplotlib.use("Agg") # no display in CI | ||
|
|
||
| from linkml_store.plotting.cli import plot_cli # noqa: E402 |
There was a problem hiding this comment.
Checked this rather than assuming, and the stated failure does not reproduce. On matplotlib 3.11.1, importing matplotlib.pyplot first and then calling matplotlib.use("Agg") switches the backend and raises nothing:
pyplot imported first, backend: macosx
matplotlib.use(Agg) AFTER pyplot: OK, backend now Agg
The concern underneath it is fair though. Setting a backend at module import is a session-wide side effect, and whether it fires depends on which test module loads first. 6a1d444 passes force=False, so if another module has already loaded a backend this leaves it alone instead of switching it out from under other tests. That costs nothing and removes the order dependence regardless of matplotlib version.
Whole plotting suite passes: 7 passed.
…backend Removes `from matplotlib.axes import Axes`, which is imported in the export branch and used nowhere in the module. Pre-existing rather than introduced here, but it sits on the line next to the fix, so it belongs in this hunk. Backend selection now passes force=False. The reviewer's stated failure, that matplotlib.use can raise when pyplot is already imported, does not reproduce on matplotlib 3.11.1, where the switch succeeds. The underlying concern about a session-wide side effect is fair though, and force=False removes it at no cost. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CGdbAo1cW9QBR2u8JBWDdK
plt before use in heatmap export; annotate pyarrow for type checkers
Fixes #72.
One of these is a real crash
plotting/cli.py:133usespltinside the--export-databranch of theheatmapcommand:pltis never bound there. Every other function in that file doesimport matplotlib.pyplot as pltlocally, butheatmap()does not, and there is no module-level import. Checked the enclosing scope directly:heatmap()spans lines 52 to 172 with nopltimport, and no module-level binding exists. So any invocation with--export-dataraisesNameError: name 'plt' is not definedbefore it can export anything.It survived because no test goes through the CLI command. The existing plotting tests call
create_heatmapandexport_heatmap_datadirectly.This PR adds
tests/test_plotting/test_heatmap_cli_export.py, which invokes the command throughCliRunnerwith--export-data. Removing the one-line fix and rerunning gives exactlyNameError("name 'plt' is not defined"), so the test does catch the regression rather than merely passing.The fix adds the missing import in that block, matching the lazy-import convention the rest of the file already uses.
The other three are annotations, not crashes
dremio_database.pyreturns"pyarrow.Table"from three methods.pyarrowis an optional dependency, imported lazily inside the methods that need it, so the name never resolves for a type checker even though nothing fails at runtime.Fixed with a
TYPE_CHECKINGimport, which resolves the annotations without adding a runtime import or making pyarrow a hard dependency. The comment in the file says so, since a bareimport pyarrowunderTYPE_CHECKINGlooks removable otherwise.Checks
Ruff
F821is now clean across the repository.Violations in the two touched files go down, not up:
plotting/cli.pyfrom 26 to 25,dremio_database.pyfrom 8 to 5. The new test file is ruff-clean.uv.lockis deliberately untouched. My local test run rewrote it and I reverted that; it is not part of this change.Scope
Two source lines of real change plus a
TYPE_CHECKINGblock, and one new test.The other lint issues in these files are left alone. The auto-fixable set from #74 and the CI check from #71 are a separate, mechanical change, and I did not want 96 formatting edits sitting on top of a real bug fix in the same review.
🤖 Generated with Claude Code