Skip to content

[MAINT]: Enable ruff preview#55

Open
spencrr wants to merge 16 commits into
microsoft:mainfrom
spencrr:spencrr/ruff-enable-preview
Open

[MAINT]: Enable ruff preview#55
spencrr wants to merge 16 commits into
microsoft:mainfrom
spencrr:spencrr/ruff-enable-preview

Conversation

@spencrr

@spencrr spencrr commented May 20, 2026

Copy link
Copy Markdown
Contributor

Description

Align RAMPART's lint configuration with sibling project PyRIT by enabling ruff preview mode and burning down the global ignore list it surfaces. After this PR, the project lints clean under preview with no broad rule suppressions — only DOC502 (intentional) and RUF076 (autouse-fixture carve-out) remain in extend-ignore.

Tooling

  • pyproject.toml: [tool.ruff.lint] gains preview = true. extend-ignore reduced to two rules (each with rationale). Per-file ignores for tests/** extended to cover DOC201, DOC501, PLC1901, PLC2701.
  • Ruff bumped 0.15.100.15.17 (project + pre-commit hook).
  • Adds typing-extensions>=4.12; python_version < '3.12' runtime dep, sourcing typing.override (PEP 698) under Python 3.11.

Public API factory restructure

Three top-level factory classes moved out of init.py into private modules so the package init files become thin re-export shims (resolves preview rules pushing logic out of init.py):

Class Old location New location
Attacks rampart/attacks/__init__.py rampart/attacks/_factory.py
Probes rampart/probes/__init__.py rampart/probes/_factory.py
Payloads rampart/payloads/__init__.py rampart/payloads/_facade.py

Public import paths (from rampart.attacks import Attacks, etc.) and __all__ are unchanged.

Docstrings: Returns / Raises documented on public APIs

DOC201 / DOC501 (preview) require explicit Returns: and Raises: sections where applicable. Coverage added across:

  • Core: evaluator.py, execution.py, manifest.py, result.py, types.py
  • Drivers: llm.py
  • Evaluators: response_contains.py, side_effect.py, tool_called.py
  • Payloads: _store.py
  • PyRIT bridge: llm_bridge.py
  • Pytest plugin: plugin.py
  • Surfaces: onedrive.py

Code cleanups surfaced by preview

  • @staticmethod on private helpers with no self use (PLR6301): _xpia._adjust_for_observability, _generator._build_user_message, json_file._serialize_turn.
  • @override annotation on the pytest plugin's ResultCollectionHandler.on_event with a sys.version_info >= (3, 12) fallback to typing_extensions.override for Python 3.11 (rampart/pytest_plugin/_collection.py).
  • Modernized stdlib usage: open(path) … f.read()Path(path).read_text(...) (PTH123); tuple membership → set literal (PLR6201); pytest.mark.__getattr__(name)getattr(pytest.mark, name) (B009).
  • Collapsed raise X(msg,) spanning multiple lines to single-line raise X(msg) (UP034/formatter preference).
  • Tests: RUF029 (async with no await) — drop async from sync test callbacks (tests/unit/payloads/test_generator.py, test_payloads.py, tests/unit/core/test_execution.py); pytest.approx(...) adopted for float equality across test_result.py, test_types.py, test_llm_judge.py, test_llm_bridge.py, test_plugin.py. Trailing blank lines removed from package init.py files (W391).
  • Removed redundant # noqa: BLE001 in _session.py, plugin.py, core/execution.py (preview no longer flags the surrounding code).

Breaking changes

None. Public imports (Attacks, Probes, Payloads, XPIAExecution, SingleTurnExecution, PayloadStore, PayloadTemplate) and their signatures are unchanged.

Checklist

  • pre-commit run --all-files passes
  • Tests added or updated for changes — existing unit tests cover the refactored modules; test helpers updated alongside source. No new behavior to test (lint-driven refactor).
  • Documentation updated — N/A; no user-visible API changes.

@spencrr spencrr force-pushed the spencrr/ruff-enable-preview branch from 1d06f03 to 6ac60be Compare May 28, 2026 23:51
@spencrr spencrr force-pushed the spencrr/ruff-enable-preview branch from 6ac60be to 8023cd4 Compare June 16, 2026 20:50
@spencrr spencrr changed the title [MAINT]: Enable ruff preview and address various linting issues [MAINT]: Enable ruff preview Jun 17, 2026
@spencrr spencrr marked this pull request as ready for review June 17, 2026 00:12
@spencrr spencrr requested a review from a team June 17, 2026 00:12
spencrr added 16 commits June 19, 2026 17:05
- Replace bare float == comparisons in tests with pytest.approx().
- Suppress pyright reportUnknownMemberType on the new approx calls
  (matches existing convention used elsewhere in the suite).
- Remove RUF069 from global ruff ignore list.
The five async helpers flagged by RUF029 are sync side_effect callbacks
passed to AsyncMock-backed targets. AsyncMock accepts sync side_effects
and awaits the return value, so dropping 'async' from the helpers is
semantically equivalent.

- Drop async from capture_eval / capture helpers in tests.
- Remove RUF029 from global ruff ignore list.
- Replace open()/read() with Path.read_text() in the one test helper.
- Remove FURB101 from global ruff ignore list.
All 10 violations were in tests, where 'x == ""' asserts an explicit
empty-string contract \u2014 rewriting to 'not x' would silently accept
None / 0 / [] as well.

- Move PLC1901 from global ignore to per-file-ignores[tests/**] with a
  comment explaining the intent.
- Production code remains under PLC1901 enforcement.
Extract logic out of the three package __init__.py files so they
contain only docstrings and re-exports:

- rampart/attacks/__init__.py -> Attacks class moved to
  rampart/attacks/_factory.py.
- rampart/probes/__init__.py -> Probes class moved to
  rampart/probes/_factory.py.
- rampart/payloads/__init__.py -> Payloads class plus the
  _apply_converters_async and _build_text_payload helpers moved
  to rampart/payloads/_facade.py (kept separate from _generator.py
  so the lower-level generator stays focused on LLM I/O).

Public import paths are unchanged (still re-exported via __init__).

- Remove RUF067 from global ruff ignore list.
DOC502 forbids documenting exceptions that propagate from a delegated
callee. That conflicts with Google-style / Sphinx / numpydoc convention,
which deliberately documents such exceptions because they are part of
the caller-visible contract.

All 4 current sites (KeyError from str.format_map, ValueError from a
_validate helper, pytest.UsageError from trial-marker helpers) are
legitimate contract exceptions worth documenting. The rule's
'fixes' (delete the Raises: section, or wrap with try/except + re-raise)
would degrade the docs or add boilerplate that hides the original error.

- Move DOC502 from the TODO ignore list into a separately documented
  'intentionally disabled' extend-ignore with rationale.
Ruff format collapses 'raise X(\n    msg,\n)' to a single line. These
changes were produced by the formatter; no behavioral changes.
Document the Raises: contract for the 10 production functions that
raise exceptions but had no Raises: section. Also add DOC501 to the
tests/** per-file-ignores: test fixture executions (e.g. one-line
_execute_async that just 'raise InfrastructureError(...)') are
self-documenting and don't need contract docstrings.

Files touched (Raises: sections added):
- rampart/core/types.py (Payload.__post_init__, Request.__post_init__,
  EvalContext.current_turn)
- rampart/drivers/llm.py (_ensure_initialized,
  _assert_conversations_consistent, _send_async)
- rampart/payloads/_store.py (_validate_collection_name)
- rampart/pyrit_bridge/llm_bridge.py (_validate)
- rampart/pytest_plugin/plugin.py (_create_trial_clones)
- rampart/surfaces/onedrive.py (InjectionHandle.__aenter__)

- Remove DOC501 from global ruff ignore list.
@spencrr spencrr force-pushed the spencrr/ruff-enable-preview branch from 289c969 to c1d92e5 Compare June 20, 2026 00:33
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