Skip to content

ci: add a ruff lint gate, and clear what it found - #135

Merged
shigechika merged 2 commits into
mainfrom
chore/ruff-lint-gate
Jul 28, 2026
Merged

ci: add a ruff lint gate, and clear what it found#135
shigechika merged 2 commits into
mainfrom
chore/ruff-lint-gate

Conversation

@shigechika

Copy link
Copy Markdown
Owner

This repository had no ruff configuration and no lint step. Turning the check
on surfaced nine findings, cleared here so the gate starts green.

What it found

where fix
8 × F401 unused import 1 in junos_ops/common.py, 7 across tests/ removed
1 × E741 ambiguous name l tests/test_check.py comprehension renamed to line

The source-file one was checked before removing rather than auto-fixed on
trust: ConnectClosedError could plausibly have been imported into
common.py as a re-export. It is not — cli.py and rsi.py import it
straight from jnpr.junos.exception, and common.py declares no __all__,
so nothing reached it through that module. 379 tests pass after the change.

Why select is stated rather than inherited

Ruff's default rule set is not stable across releases. 0.16 widened it to
include UP, B, SIM, BLE and RUF, so a repository relying on the
default goes red on an upgrade without a line of its own code changing.

That is not hypothetical: the sibling repositories that already run
ruff check . with no select pass only because their lockfiles hold them on
0.15.x. Pinning the ruff version alone does not fix it, it defers it to
whoever bumps the pin. The version is pinned in CI as well, so both failure
modes are covered.

Why ruff format is not gated

Recorded in ruff.toml. It would rewrite 22 of 37 files here — a reformat
commit of its own, and a decision separate from turning linting on.
line-length is left unset for the same reason.

Noticed, not changed

except (ConnectClosedError, Exception): appears throughout cli.py and
rsi.py. The tuple is redundant — Exception already catches
ConnectClosedError — so the specific name reads as intent that the code does
not actually express. Pre-existing and outside this change; worth a look on
its own.

Verification

Run with the pinned 0.16.0, the same command CI runs: clean. Then broken on
purpose — an unused import and an undefined name are both reported, and the
gate returns to green once removed.

🤖 Generated with Claude Code

https://claude.ai/code/session_01YVg3toYKK6J2J9ggdrzYVf

Nothing checked for unused imports, undefined names or unreachable code here,
and turning the check on surfaced nine findings that had to be cleared first
so the gate starts green.

Eight were unused imports — one in junos_ops/common.py and seven across the
tests. The source one was verified not to be a re-export before removal: cli.py
and rsi.py import ConnectClosedError straight from jnpr.junos.exception, and
common.py declares no __all__, so nothing was reading it through that module.

The ninth was `l` as a comprehension variable in tests/test_check.py, renamed
to `line`.

select is stated rather than inherited: ruff's default set is not stable
across releases (0.16 widened it to UP, B, SIM, BLE, RUF), so relying on the
default means going red on an upgrade without any of this code changing.
Sibling repositories pass with no select only because their lockfiles hold
them on 0.15. The CI pin covers the other half.

ruff format is not gated; ruff.toml records why.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YVg3toYKK6J2J9ggdrzYVf
@github-actions

Copy link
Copy Markdown
Contributor

AI review (gpt-5.6-sol)

  • junos_ops/common.py, import-removal hunk: Removing ConnectClosedError is a backward-incompatible module API change, not merely lint cleanup. Without __all__, the imported name was still available via both from junos_ops.common import ConnectClosedError and wildcard imports; absence of __all__ does not make it private. Any downstream consumer using that import will now fail with ImportError. Preserve it as an explicit re-export (for example, using an alias Ruff recognizes) or document/deprecate the removal separately.

Advisory first-pass review generated by ai-review.yml — verify findings before acting.

@shigechika

Copy link
Copy Markdown
Owner Author

The mechanism is right and I had not considered it — my check was "nothing in this repository reads it", which says nothing about downstream consumers. Without __all__, from junos_ops.common import ConnectClosedError did work.

I am not restoring it, for two reasons.

junos_ops.common is not an API surface. This package ships a console script (junos-ops = junos_ops.cli:main) and nothing else; neither README documents importing from it, and inside the repository only the tests import common — none of them for this name. An incidental unused import is not a published interface just because Python makes it reachable.

The suggested remedy would create the commitment rather than preserve it. ConnectClosedError belongs to jnpr.junos.exception; adding an explicit re-export or an __all__ entry would newly promise that this package keeps forwarding a third-party symbol. Anyone who wants it imports it from PyEZ, which is what cli.py and rsi.py already do.

What would change the answer: common being documented as importable, or a known consumer. If either turns up, restoring it as a deliberate re-export with __all__ is the right fix — but then it should be a decision made on purpose, not an unused import that survived because a linter never ran.

@shigechika
shigechika merged commit 5dacb6e into main Jul 28, 2026
7 checks passed
@shigechika
shigechika deleted the chore/ruff-lint-gate branch July 28, 2026 00:05
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