Skip to content

feat(tooling): bump ruff 0.9.7 -> 0.15.20 (HYBIM-777)#66

Merged
etserend merged 1 commit into
mainfrom
HYBIM-777-bump-ruff
Jul 7, 2026
Merged

feat(tooling): bump ruff 0.9.7 -> 0.15.20 (HYBIM-777)#66
etserend merged 1 commit into
mainfrom
HYBIM-777-bump-ruff

Conversation

@etserend

@etserend etserend commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Bumps ruff 0.9.70.15.20 in .pre-commit-config.yaml and pyproject.toml
  • Bumps openapi-python-client 0.26.10.29.0 (0.26.x capped ruff<0.14, blocking the upgrade)

Violations fixed by new rules

Rule Fix
F401 Remove unused timezone import from utils/__init__.py
PLW1641 Add __hash__ to Message class (defines __eq__ without __hash__)
PLC0415 in src/ Add experiment.py and metric.py to per-file-ignores (circular import pattern)
PLC0415 / RUF043 / E402 in tests/ Add to test per-file-ignores (pytest.importorskip conditional imports)
Multiple rules in examples/ Extend examples/**/*.py per-file-ignores (ANN, ASYNC, S, etc. — examples are docs not prod code)
E402 in create_sample_logs.py Add # ruff: noqa: E402 (file-level, load_dotenv() must precede imports)

Test plan

  • CI green (all Python versions / OS matrix)
  • ruff check passes locally ✅
  • ruff format applied ✅ (92 files reformatted)
  • Test suite passes locally ✅ (1516 passed, pre-existing langchain/openai-agents skips unchanged)

….26.1 -> 0.29.0 (HYBIM-777)

openapi-python-client 0.26.x capped ruff<0.14; bump to 0.29.0 removes the
conflict. Fix new violations introduced by ruff 0.13-0.15:
- Remove unused timezone import (F401)
- Add __hash__ to Message.__eq__ class (PLW1641)
- Suppress PLC0415/RUF043/E402 in tests (importorskip pattern)
- Suppress new rules in examples per-file-ignores (examples are docs)
- Add PLC0415 suppression for experiment.py and metric.py (circular imports)
- Add ruff: noqa comment in create_sample_logs.py (load_dotenv before imports)

@fercor-cisco fercor-cisco left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 This review was generated by the Astra agent (claude-opus-4-8). It may contain mistakes.

Verdict: approve — Well-scoped tooling bump; substantive src changes (StrEnum, datetime.UTC, hash, F401) are behavior-preserving and correctly scoped.

Follow-ups

Suggested follow-up work that could be tracked as Shortcut stories:

  • pyproject.toml:248-263: The new examples/**/*.py per-file-ignore list is broad — it silences whole rule families including S (security), B (bugbear), E722 (bare except), and ASYNC. That's a defensible tradeoff for demo code, but wholesale-disabling security/bugbear linting means genuinely buggy example patterns (e.g. broken async, resource leaks) will never surface even when they mislead users copying the examples. Consider narrowing to the specific rule codes actually triggered rather than entire prefixes, so future real issues in examples still get flagged.

Comment on lines +26 to +27
def __hash__(self) -> int:
return hash((self.content, self.role, self.tool_call_id))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 minor (bug): __hash__ will raise TypeError: unhashable type: 'list' when content is a list (the multimodal list[ContentPart] / IngestMessageContent case that LoggedMessage explicitly supports). This isn't a regression — the class was fully unhashable before (defined __eq__ without __hash__) — but by adding __hash__ you invite callers to put Message in a set/dict key, which will then blow up only for multimodal messages. Consider normalizing list content to a hashable form so the method is total, e.g.:

def __hash__(self) -> int:
    content = tuple(self.content) if isinstance(self.content, list) else self.content
    return hash((content, self.role, self.tool_call_id))

(and if elements aren't hashable, hash their serialized form). At minimum, worth a test covering a list-content Message to document the intended behavior.

Suggested change
def __hash__(self) -> int:
return hash((self.content, self.role, self.tool_call_id))
def __hash__(self) -> int:
content = tuple(self.content) if isinstance(self.content, list) else self.content
return hash((content, self.role, self.tool_call_id))

🤖 Generated by Astra

@fercor-cisco fercor-cisco left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll create follow-up tickets for the 2 notes from the review agent.

@etserend etserend merged commit e121f41 into main Jul 7, 2026
21 checks passed
@etserend etserend deleted the HYBIM-777-bump-ruff branch July 7, 2026 18:33
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 7, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants