Skip to content

[OPIK-8379] [SDK] chore: enable ruff PLE1205/PLE1206 to catch logging format-arg mismatches - #8323

Merged
JetoPistola merged 1 commit into
mainfrom
danield/OPIK-8379-ruff-logging-format-rules
Sep 15, 2026
Merged

JetoPistola merged 1 commit into
mainfrom
danield/OPIK-8379-ruff-logging-format-rules

Conversation

@JetoPistola

@JetoPistola JetoPistola commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Details

image

Enables ruff's PLE1205 (logging-too-many-args) and PLE1206 (logging-too-few-args) for the Python SDK, so a logging call whose positional arguments don't match its format-string placeholders fails pre-commit and the 🐙 Code Quality check.

This defect has shipped twice. When a message with no %s is passed a positional argument, logging defers msg % args to the handler, so the interpolation raises inside Handler.emit, handleError() prints a --- Logging error --- block to stderr, and the record — including its exc_info traceback — is never emitted. Nothing propagates to the caller, so the only diagnostic for a mid-stream failure is silently lost.

It was swept once across twelve call sites in #7850, then reintroduced in two new call sites by the Cerebras integration (#7342), which landed after that sweep and was fixed in #8238. Nothing but human code review was enforcing the invariant, so each recurrence cost a bug report, a fix PR, and a review cycle.

Configured in .ruff.toml, not pyproject.toml. Worth calling out, because the obvious approach silently does nothing: a .ruff.toml is present for this package and takes precedence, so a [tool.ruff] section added to pyproject.toml is ignored — the hook still passes and the rules never run.

Deliberately scoped to PLE1205/PLE1206. The G / flake8-logging-format ruleset does not catch this defect (verified against the exact Cerebras code) and reports ~200 pre-existing violations (111 G004, 86 G201, 2 G002, 1 G202), so it would be a separate cleanup rather than a guard against this bug.

Change checklist

  • User facing
  • Documentation update

Issues

AI-WATERMARK

AI-WATERMARK: yes

  • Tools: Claude Code
  • Model(s): Claude Opus 5
  • Scope: full implementation
  • Human verification: pre-commit hooks run locally against the full tracked Python tree, plus a deliberate-failure control

Testing

No new tests. This is lint configuration; there is no new code path to exercise, and the rules themselves are ruff's.

Verified by running the real pre-commit hooks rather than ruff directly:

  • All three ruff hooks (🐍 python sdk, 🤖 optimizer, 🛡️ guardrails) over every tracked .py file in the repo → Passed. The SDK is already clean under both rules, so this lands with no code changes.
  • Deliberate-failure control: a file containing both defect shapes (a positional arg with no placeholder, and two placeholders with one arg) → hook Failed, exit 1, reporting PLE1205 and PLE1206. This is the part that makes the green run meaningful — a clean pass alone would also be the result of the rules being silently ignored, which is exactly the pyproject.toml trap described above.
  • Negative control: the mistral and anthropic Beta stream wrappers pass only exc_info=True as a keyword rather than a positional arg, so they are correct as written → not flagged.
  • Confirmed the rules appear in ruff's resolved settings as logging-too-many-args (PLE1205) / logging-too-few-args (PLE1206).

Measured against the two known-bad call sites: 2 violations before #8238, 0 after — matching an independent AST pass over the same tree.

Documentation

N/A — the change is a lint rule with an explanatory comment at the config site.

Enable logging-too-many-args and logging-too-few-args so a logging call
whose positional arguments do not match its format-string placeholders
fails pre-commit and the Code Quality check.

The defect these catch has shipped twice. A message with no %s that is
passed a positional argument raises inside Handler.emit, so handleError()
prints a "--- Logging error ---" block to stderr and the record, including
its exc_info traceback, is never emitted. Nothing propagates to the caller,
so the only diagnostic for a mid-stream failure is lost. It was swept once
across twelve call sites, then reintroduced by an integration that landed
after that sweep, because nothing but code review was enforcing it.

The rules are configured in .ruff.toml rather than pyproject.toml: a
.ruff.toml is present for this package and takes precedence, so ruff
silently ignores a [tool.ruff] section in pyproject.toml.

The SDK is already clean under both rules, so this is configuration only
with no code changes required.

Implements OPIK-8379: enable ruff PLE1205/PLE1206 to catch logging
format-argument mismatches in the Python SDK

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

⏱️ pre-commit per-hook timing

Hook Description Result Duration
🐍 fix end of files — python sdk Ensure files end in a newline ✅ 0.02s
🐍 trim trailing whitespace — python sdk Strip trailing whitespace ✅ 0.02s
Total (2 ran) 0.04s
⏭️ 42 skipped (no matching files changed)
Hook Description Result
🐍 ruff — python sdk Lint + autofix Python (ruff) ⏭️
🐍 ruff-format — python sdk Format Python code (ruff) ⏭️
🐍 mypy — python sdk Static type check ⏭️
🤖 trim trailing whitespace — optimizer Strip trailing whitespace ⏭️
🤖 fix end of files — optimizer Ensure files end in a newline ⏭️
🤖 check yaml — optimizer Validate YAML syntax ⏭️
🤖 check json — optimizer Validate JSON syntax ⏭️
🤖 check toml — optimizer Validate TOML syntax ⏭️
🤖 check for added large files — optimizer Block large files (>1MB) ⏭️
🔐 detect private key — optimizer Block committed private keys ⏭️
🤖 check for merge conflicts — optimizer Block merge-conflict markers ⏭️
🤖 check for case conflicts — optimizer Block case-only name clashes ⏭️
🤖 pyupgrade — optimizer Modernize Python syntax ⏭️
🤖 ruff — optimizer Lint + autofix Python (ruff) ⏭️
🤖 ruff-format — optimizer Format Python code (ruff) ⏭️
🤖 mypy — optimizer Static type check ⏭️
📓 nbstripout — optimizer notebooks Strip notebook output ⏭️
📝 markdownlint — optimizer Lint Markdown ⏭️
🔤 codespell — optimizer Fix common misspellings ⏭️
📊 radon cc — optimizer Cyclomatic-complexity gate ⏭️
📊 radon raw — optimizer Raw size metrics gate ⏭️
📊 xenon — optimizer Fail on complexity thresholds ⏭️
📊 lizard — optimizer Cyclomatic-complexity gate ⏭️
🧹 vulture — optimizer Find dead code ⏭️
🛡️ trim trailing whitespace — guardrails Strip trailing whitespace ⏭️
🛡️ fix end of files — guardrails Ensure files end in a newline ⏭️
🛡️ ruff — guardrails Lint + autofix Python (ruff) ⏭️
🛡️ ruff-format — guardrails Format Python code (ruff) ⏭️
🛡️ mypy — guardrails Static type check ⏭️
⚓ helm-docs Regenerate Helm chart README ⏭️
block non-public FE plugins Block non-public FE plugins ⏭️
☕ spotless — java backend Format Java code ⏭️
🧪 pre-commit wrapper smoke tests Self-test the wrapper scripts ⏭️
🧪 rebaseline script tests Self-test the changelog re-baseline script ⏭️
🌐 eslint — frontend Lint + autofix JS/TS ⏭️
🌐 typecheck — frontend Whole-project tsc type check ⏭️
📘 eslint — typescript sdk Lint + autofix JS/TS ⏭️
📘 typecheck — typescript sdk Whole-project tsc type check ⏭️
⚙️ actionlint — github workflows Lint GitHub Actions workflows ⏭️
🐳 hadolint — dockerfiles Lint Dockerfiles ⏭️
🌈 zizmor — github workflows security Security-scan GitHub Actions workflows ⏭️
🛡️ semgrep — java backend sql Enforce the repo's own backend Java rules ⏭️

@JetoPistola
JetoPistola marked this pull request as ready for review September 15, 2026 06:23
@JetoPistola
JetoPistola requested a review from a team as a code owner September 15, 2026 06:23
@CometActions

CometActions commented Sep 15, 2026 •

Copy link
Copy Markdown
Collaborator

No test needed here.

No product surface in this PR — only docs, CI, tests, lockfiles or other non-product files.

Run

Advisory, from the QA test radar. Nothing here blocks this PR, and anything it proposes is a draft for review.

Re-checked after a push on 15 Sep 06:37 UTC.

@JetoPistola
JetoPistola marked this pull request as draft September 15, 2026 06:27
@JetoPistola
JetoPistola marked this pull request as ready for review September 15, 2026 06:34
@JetoPistola
JetoPistola merged commit a15fae1 into main Sep 15, 2026
193 of 229 checks passed
@JetoPistola
JetoPistola deleted the danield/OPIK-8379-ruff-logging-format-rules branch September 15, 2026 08:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants