Skip to content

Fix Ruff's broad-except, security, print and private-access findings (BLE, S, T20, SLF) - #67

Merged
anth-volk merged 6 commits into
mainfrom
claude/ruff-safety
Nov 3, 2026
Merged

anth-volk merged 6 commits into
mainfrom
claude/ruff-safety

Conversation

@anth-volk

@anth-volk anth-volk commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #66

Part of #53.

What this does

The fourth of the pull requests stacked on #55 that fix the Ruff findings #55 leaves ignored. It covers the findings in BLE, S, T20 and SLF: 131 on #55, and 130 here, since #65 moved the root conftest.py under the tests' exemptions. Afterwards pyproject.toml no longer ignores those four families. Stacked on #65.

The emitter catches broad exceptions and prints to standard error on purpose: no call may raise into the build, a module's failure must not stop the host, and a failed cycle must leave the work queued. So most findings are kept with a # noqa, each with its reason in a comment above it, taken from the code. The fixes that change code don't change what a caller sees under the normal interpreter.

  • Two per-file ignores, each registered:
    • emitter.quality.program-ruff-exemptions (new): microcosm_emitter.cli and microcosm_emitter.host.__main__ run as programs (each has if __name__ == "__main__":), so they may print (T201), as the Public API's modules that run as programs do. This covers 6 findings. orrery/cli.py has no such guard, so its two prints keep a # noqa.
    • emitter.quality.installed-smoke-ruff-exemptions (new): SLF001 for tools/installed-smoke.py and tools/installed-interface-smoke.py, which read the clients' private members to check the processes they started, as tests do. This covers 4 findings. check-installed.py has none, so it is not covered (round 1).
  • BLE001 (61): 60 handlers keep except Exception with # noqa: BLE001, because narrowing them would let exceptions reach the build, the host or the queue. The reasons fall into a few kinds: no call raises into the build, and the failure is reported instead; a failure rejects only this request; a failed cycle leaves the job queued for the next one. One try/except/pass becomes contextlib.suppress(Exception), which behaves the same and also clears its S110.
  • S101 (21):
    • 19 become explicit checks. Each invariant assert x is not None, "message" in package code becomes if x is None: raise AssertionError(...), with the same message. Under the normal interpreter this behaves the same. Under python -O the check now runs, where the assert was skipped.
    • The other two too (round 1): the runtime's worker shutdown gets its dispatcher from a new _started_requests helper, which raises the same AssertionError outside the try block, as the stack handles TRY301 elsewhere. The sanitizer's invariant is an explicit check that raises AssertionError, with # noqa: TRY004 and its reason, as Fix Ruff's exception-raising findings (EM, RSE, TRY) #58 handles type checks that keep their exception.
  • T201 (16 more): messages written on purpose keep print, with # noqa: T201. One note per module, after its imports, says why: each print marked so writes one of its messages to standard error on purpose, and none is leftover debugging output. orrery/cli.py's two prints write the command's receipt on standard output. (Round 1 removed 14 copies of a comment claiming print cannot raise on a missing sys.stderr, which was not the reason and not exact.)
  • S105 (13): environment variable names, a URL path, status codes and messages whose constant names contain "TOKEN". None is a secret, and the constants keep their names.
  • S603 (2): both launchers run the emitter's own command.
  • S310 (1): an origin the code checked first.
  • S506 (3, tests): yaml.BaseLoader stays. It keeps YAML's on key a string, as GitHub reads it.
  • S324 (1, a test fake): SHA-1 is called with usedforsecurity=False, which changes no digest.
  • SLF001 (1 more): the host client's ModuleClient calls SocketClient._request in the same module.
  • Ruff no longer ignores BLE, S, SLF and T20.

A helper agent wrote the suppressions and reasons from a brief I gave it, with the decisions above. I checked the result: of the 36 changed Python files, 28 changed only in comments or layout (their syntax trees are identical). The other 8 hold the explicit checks, contextlib.suppress and usedforsecurity.

Test-first record

There is no red step, since nothing changes behaviour under the normal interpreter.

Commit Result
9478355 The fixes and the two per-file ignores ruff check . and ruff format --check . pass. All five guards pass with GITHUB_BASE_REF=main. The 8 test functions whose source lines changed (only comments, in their except lines) pass by node ID (9 cases).
59fc416 Merge of #65's round 1 ruff check . and ruff format --check . pass.
faa6a99 The changelog fragment tools/bump-version.py --check passes.

Review round 1:

Commit Result
5b2be26 The last two asserts, the narrower SLF001 exemption, one print note per module, the configuration comment and the fragment ruff check ., ruff format --check . and the five guards pass. No test function changed.

No other test was run; CI runs them.

CI

No workflow, trigger or script changes, and no environment variable or secret is read differently.

Release

The fragment is changelog.d/ruff-safety.changed.md. With #65's added fragment below it in the stack, merging releases a minor version (0.12.0 now); on its own this fragment would give a patch bump.

🤖 Generated with Claude Code

@anth-volk
anth-volk added this pull request to stack #46 October 30, 2026 20:50
@anth-volk anth-volk changed the title claude/ruff safety Fix Ruff's broad-except, security, print and private-access findings (BLE, S, T20, SLF) Oct 30, 2026
@anth-volk
anth-volk removed this pull request from stack #46 November 2, 2026 14:03
@anth-volk
anth-volk added this pull request to stack #72 November 2, 2026 14:04
@anth-volk
anth-volk force-pushed the claude/ruff-safety branch 4 times, most recently from 91ee7e6 to ee81944 Compare November 2, 2026 17:47
Base automatically changed from claude/ruff-typing to main November 3, 2026 14:22
anth-volk and others added 5 commits November 3, 2026 18:22
- BLE001: the broad excepts stay, since narrowing them would change
  what reaches the build, the host or the queue; each has
  `# noqa: BLE001` and its reason above it. One try/except/pass becomes
  contextlib.suppress(Exception) (also S110).
- S101: 19 asserts in package code become explicit checks raising the
  same AssertionError with the same message, so they also hold under
  python -O. Two stay, with reasons: an explicit raise there would
  trigger TRY301 or TRY004.
- T201: microcosm_emitter.cli and microcosm_emitter.host.__main__, which
  run as programs, may print (emitter.quality.program-ruff-exemptions,
  as in the Public API). Elsewhere the prints are warnings and answers
  on purpose and keep print, which does not raise when sys.stderr is
  None, with `# noqa: T201`.
- S105 (environment variable names, paths, codes and messages), S603
  (the emitter's own command), S310 (an origin checked first) and S506
  (yaml.BaseLoader in tests) keep their code with reasons; S324 passes
  usedforsecurity=False.
- SLF001: the installed-artifact checks may read the clients' private
  members (emitter.quality.installed-checks-ruff-exemptions); host
  client's ModuleClient keeps its call to SocketClient._request.
- Ruff no longer ignores BLE, S, SLF and T20.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…stay

- The runtime's worker shutdown gets its dispatcher from a new
  _started_requests helper, which raises the same AssertionError, so the
  try block no longer holds a raise (TRY301). The sanitizer's invariant
  is an explicit check raising AssertionError, with `# noqa: TRY004`
  and its reason, as #58 handles type checks that keep their exception.
- SLF001 applies only to tools/installed-smoke.py and
  tools/installed-interface-smoke.py, under the new rule
  emitter.quality.installed-smoke-ruff-exemptions; check-installed.py
  needs it for nothing.
- The 14 copies of an inaccurate comment about print and a missing
  sys.stderr are replaced by one note per module: each print marked
  `# noqa: T201` writes one of its messages to standard error on
  purpose.
- The Ruff configuration comment includes modules that run as programs,
  and the changelog fragment says all 21 asserts are converted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The notes quoted the suppression comment itself, which Ruff parsed as a
`# noqa` directive and warned was invalid on every run, once per module.
They now say "suppresses Ruff's T201" in words; ruff check prints no
warning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The rebase left docs/generated/rules.md's summary counting 56 rules,
48 of them enforced and 49 blocking; the registry holds 57, 49
enforced and 50 blocking. python -m scripts.rules render brings it back
to the registry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk added a commit that referenced this pull request Nov 3, 2026
#67 and #69 were rebased onto main after #65 merged, so this merge
conflicted in the 9 files this branch had changed on top of #69. Each
keeps this branch's side, plus the release's version bump in
pyproject.toml; python -m scripts.rules render left the rules views as
they were. The tree differs from 54f2464 exactly by main's release
(e233d97..d79aa4d).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@anth-volk
anth-volk marked this pull request as ready for review November 3, 2026 16:31
@anth-volk
anth-volk merged commit 77f5ccc into main Nov 3, 2026
12 checks passed
@anth-volk
anth-volk deleted the claude/ruff-safety branch November 3, 2026 16:32
anth-volk added a commit that referenced this pull request Nov 3, 2026
#69 was rebased onto main after #67 merged, so this merge conflicted in
the 5 files this branch had changed on top of #69. Each keeps this
branch's side, plus the release's version bump in pyproject.toml;
python -m scripts.rules render left the rules views as they were. The
tree differs from ca655a7 exactly by main's release (6625a18..72205e8).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.

Fix Ruff's broad-except, security, print and private-access findings (BLE, S, T20, SLF)

1 participant