Skip to content

Lint Jupyter notebooks: put *.ipynb in ruff's include - #412

Merged
jmccreight merged 4 commits into
DOI-USGS:developfrom
jmccreight:lint_notebooks
Aug 26, 2026
Merged

Lint Jupyter notebooks: put *.ipynb in ruff's include#412
jmccreight merged 4 commits into
DOI-USGS:developfrom
jmccreight:lint_notebooks

Conversation

@jmccreight

@jmccreight jmccreight commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Notebooks were never linted. [tool.ruff] include listed only *.py, so
ruff check . — and therefore CI — skipped every .ipynb. The pre-commit hook
passed staged notebook paths explicitly, which overrides include, so it did
lint them. Notebook problems were invisible until someone edited a notebook and
was met with errors they had not caused.

This adds **/*.ipynb to include, with two rules exempted for notebooks:

  • E501 — wrapping narrative cells to 79 columns hurts readability and churns
    diffs for no correctness gain.
  • I001 — several notebooks import a module purely for its side effect
    (hvplot.xarray registers a .hvplot accessor) and must do so after the
    module it extends; sorting moves those imports above their dependency.

Notebooks are linted but not auto-formatted: the formatter wraps to
line-length regardless of the E501 exemption, which would reflow every cell
in every notebook.

Turning the lint on surfaced four broken cells that no test covered — two stray
), a string opened with " and closed with ', and a use of pl.Path with
no import pathlib. Three notebooks needed further cleanup once the syntax
errors stopped masking it: unused imports, unused assignments, a
semicolon-joined statement, and bare except clauses narrowed to
except AssertionError. It also repairs four malformed # noqa directives
(including a # noaq typo) that ruff silently ignored — which meant the
unused-import fixer would have deleted the hvplot imports those directives
were meant to protect.

.github/scripts/ruff_check.sh gains --force-exclude so the pre-commit hook
honors [tool.ruff.format] exclude when paths are passed explicitly. The
MAINTENANCE.md change is unrelated bookkeeping carried on this branch: the
conda-forge feedstock item moved to Done.

  • Closes #xxxx
  • Tests added
  • Performance benchmarks added
  • Performance regression benchmarks run
  • User visible changes (including notable bug fixes) are documented in whats-new.rst
  • New functions/methods are listed in api.rst or it's sub rsts?

Docs

Look for this PR number in our read-the-docs builds where you can browse on-line.

You can alternatively get a CI-build of the docs by entering the PR number for the ### in https://github.com/DOI-USGS/pywatershed/pull/###/checks then clicking on Documentation Build and finally looking for the documentation-html artifact which will download as a zip file.

The feedstock PR DOI-USGS#14 upload landed (pyprms >=0.10.0 replaces
packaging <26.3), so the last packaging <26.3 pin anywhere is gone.
Move the item from Open to Done.
[tool.ruff] include covered only *.py, so `ruff check .` and CI never
linted notebooks. But .github/scripts/ruff_check.sh greps for .ipynb and
passes those paths explicitly, which overrides include, so the
pre-commit hook did lint them. Notebook problems were invisible until
someone edited a notebook and got a wall of errors they had not caused.

Notebooks now go in include, with two rules exempted:

  E501 - they are narrative; wrapping cells to 79 columns hurts
         readability and churns diffs for no correctness gain.
  I001 - several notebooks import a module purely for its side effect
         (hvplot.xarray registers a .hvplot accessor) and must do so
         after the module it extends. Sorting moves those imports above
         their dependency, which was verified against 06.

For the same line-length reason notebooks are linted but not
auto-formatted: [tool.ruff.format] excludes them, and ruff_check.sh
passes --force-exclude so the hook honors that despite naming paths
explicitly.

This surfaced three broken cells that no test covers, all in notebooks
CI does not run:

  - a stray ")" in prms_5.2.1_performance.ipynb
  - a string opened with " and closed with ' in
    sagehen-postprocess-maps.ipynb
  - pl.Path used with no `import pathlib` in
    plot_4_performance_domains.ipynb

Four malformed # noqa directives are also repaired, including a "# noaq"
typo. Ruff rejects "# noqa, after xr" as malformed and silently ignores
it, so the unused-import fixer would have deleted the very hvplot
imports those comments existed to protect -- which would have broken
06_flow_graph_starfit.ipynb, one of the notebooks CI runs. Per review,
the explanatory comments now sit above the import and the directives are
spelled `# noqa: F401`.

The remaining 32 unused imports were audited individually rather than
blind-fixed; none are side-effect imports. Every notebook referencing
hvplot still imports it. The notebooks were not executed as part of this
change.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jmccreight and others added 2 commits August 25, 2026 21:01
A stray ) in prms_5.2.1_performance.ipynb was a syntax error that
masked the rest of its cell. With it gone: a semicolon-joined
statement, unused imports and assignments, and bare except clauses
narrowed to except AssertionError.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jmccreight jmccreight changed the title Lint notebooks Lint Jupyter notebooks: put *.ipynb in ruff's include Aug 26, 2026
@jmccreight
jmccreight merged commit 2d32c50 into DOI-USGS:develop Aug 26, 2026
32 checks passed
jmccreight added a commit to jmccreight/pywatershed that referenced this pull request Aug 26, 2026
…-ups

whats-new.rst: replace the :pull:`XXX` placeholders with 414.

CLAUDE.md: always carry the PR template's checklist into a PR body,
even when nothing in it applies, rather than dropping the section.

MAINTENANCE.md: park PR DOI-USGS#412's two deferred follow-ups -- the
pre-commit ruff-check hook's types: [python] may skip notebook-only
commits, and pyproject's optional extra lacks the holoviews floor the
environment files carry.
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.

1 participant