Skip to content

MAINT: Migrating AttackResult to Pydantic#1899

Merged
rlundeen2 merged 8 commits into
microsoft:mainfrom
rlundeen2:rlundeen2/phase-6-plan
Jun 3, 2026
Merged

MAINT: Migrating AttackResult to Pydantic#1899
rlundeen2 merged 8 commits into
microsoft:mainfrom
rlundeen2:rlundeen2/phase-6-plan

Conversation

@rlundeen2
Copy link
Copy Markdown
Contributor

This converts AttackResult to a Pydantic BaseModel. It is phase 6 of the pyrit.models refactor:

https://gist.github.com/rlundeen2/3e8daa8e12a11b4b6e52587b3c9b1dca

rlundeen2 and others added 5 commits June 2, 2026 15:17
Move AttackResult, AttackOutcome, and StrategyResult into a new
pyrit.models.results sub-package, mirroring the pyrit.models.messages
reorganization. The old pyrit/models/attack_result.py and
pyrit/models/strategy_result.py modules become silent backward-compat
shims that re-export from the new location, so existing deep-path imports
keep working.

Classes remain @DataClass for now; the Pydantic v2 conversion lands in a
follow-up once Score (Phase 5) is merged.

Also add a .gitignore negation so the new package dir is not caught by the
existing runtime 'results/' ignore rule.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Complete the Phase 6 Pydantic conversion: StrategyResult and AttackResult
(relocated into pyrit.models.results) are now Pydantic v2 BaseModels with
extra='forbid', naive-timestamp coercion, and a deprecated attack_identifier
kwarg/property that promotes to atomic_attack_identifier. to_dict/from_dict are
retained as deprecated shims preserving the legacy wire shape. The before-
validators copy the input dict so model_validate never mutates caller payloads.

De-dataclass all StrategyResult/AttackResult subclasses so their Pydantic
__init__ works correctly: Crescendo/TAP/Sequential attack results, Workflow/XPIA
results, and PromptGenerator/GCG/Fuzzer/Anecdoctor results. Context classes
remain dataclasses. field(default_factory=...) becomes pydantic Field(...).

Fix tests that relied on the old dataclass accepting type-invalid values, and
add pre-existing None-guards in crescendo/tree_of_attacks surfaced by ty once
these files entered the changed-file set. Add conversion tests covering silent
shims, extra='forbid', timestamp coercion, to_dict/from_dict deprecation, deep-
copy independence, and combined validator / no-mutation behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use plain AwareDatetime (matching Score/MessagePiece) instead of a custom
_coerce_naive_timestamp model_validator. Naive timestamps from the DB are
already normalized to UTC by AttackResultEntry.get_attack_result via
_ensure_utc before the constructor runs, so the model can stay strict.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread .gitignore Outdated
Comment thread pyrit/auxiliary_attacks/gcg/generator.py Outdated
Comment thread pyrit/models/results/attack_result.py Outdated
Comment thread tests/unit/executor/attack/component/test_simulated_conversation.py
rlundeen2 and others added 3 commits June 3, 2026 08:59
Address review feedback on AttackResult and GCGResult: replace the
Optional[...] type annotations with the modern union syntax (X | None)
mandated by the PyRIT style guide.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The bare results/ pattern matched a directory named results at any depth,
which swallowed the new pyrit/models/results/ source package and required a
!pyrit/models/results/ negation. Anchor it as /results/ so it only ignores
the top-level runtime output dir (memory results_path), and drop the
negation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rlundeen2 rlundeen2 added this pull request to the merge queue Jun 3, 2026
Merged via the queue into microsoft:main with commit e6f1a32 Jun 3, 2026
52 checks passed
@rlundeen2 rlundeen2 deleted the rlundeen2/phase-6-plan branch June 3, 2026 16:51
romanlutz added a commit to romanlutz/PyRIT that referenced this pull request Jun 4, 2026
Merge 26 commits from main, including:
- MAINT Breaking: Convert ScenarioResult to Pydantic (microsoft#1908)
- MAINT: Migrating Seed classes to Pydantic (microsoft#1898)
- MAINT: Migrating AttackResult to Pydantic (microsoft#1899)
- MAINT: Bump ty-pre-commit v0.0.32 -> 0.0.43 (microsoft#1919)
- FEAT: Realtime streaming session support and server-side barge-in attack (microsoft#1766)
- FEAT text adaptive scenario (microsoft#1760)
- FIX: Integration Test Fixes (microsoft#1907)
- DOC: Scoring Docs Refactor (microsoft#1892)
- Various dependency bumps

Conflicts (15 files) resolved by taking main's version + re-running
ruff --fix to re-apply PEP 604 typing modernization on the incoming code
(177 violations auto-fixed). All resolved files re-staged.

Local verification:
- ruff check: All checks passed
- ruff format: clean
- pytest tests/unit -n 8: 9550 passed, 6 skipped

Known issue (pre-existing on main, not caused by this merge):
- ty 0.0.43 enabled missing-override-decorator rule, which flags hundreds
  of pre-existing methods across the codebase. Main's own CI is currently
  failing on this. Our PR will inherit the same failure since touched
  files come into pre-commit scope. Fixing this rule globally is a
  separate, large mechanical change orthogonal to typing modernization.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.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.

2 participants