Skip to content

MAINT: Making Message a Pydantic model#1885

Merged
rlundeen2 merged 3 commits into
microsoft:mainfrom
rlundeen2:rlundeen2/message-refactor-plan
Jun 2, 2026
Merged

MAINT: Making Message a Pydantic model#1885
rlundeen2 merged 3 commits into
microsoft:mainfrom
rlundeen2:rlundeen2/message-refactor-plan

Conversation

@rlundeen2
Copy link
Copy Markdown
Contributor

@rlundeen2 rlundeen2 commented Jun 2, 2026

This converts Message to a Pydantic BaseModel. I also moved to the pyrit.models.messages namespace (although imports work the same).

It is phase 4 of the pyrit.models refactor: https://gist.github.com/rlundeen2/3e8daa8e12a11b4b6e52587b3c9b1dca

rlundeen2 and others added 3 commits June 1, 2026 14:59
Mirror the MessagePiece shape: Message is now a BaseModel with a single
message_pieces field, model_config(arbitrary_types_allowed, extra=forbid),
a model_validator(after) enforcing piece-consistency invariants, and a
before-validator that accepts the legacy to_dict() payload shape.

- Keep a deprecated positional/skip_validation __init__ shim that warns.
- Add duplicate() (renames duplicate_message, which is now a warn-shim).
- Move flatten_to_message_pieces/get_all_values to module-level free
  functions (exported), with on-class deprecated staticmethod shims.
- Keep public validate() instance method (production code depends on it).
- Inline combine_dict in construct_response_from_request and clear the
  pyrit.models.message -> pyrit.common.utils import-boundary violation.
- Migrate internal pyrit/ call sites off positional Message(),
  skip_validation, and duplicate_message.
- Update/extend tests for the new BaseModel behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…conversations.py

Move message.py and message_piece.py into a new pyrit/models/messages/
subpackage (mirroring the seeds/ package), extract the collection/factory
free functions into conversations.py, and add back-compat shim modules at
the old pyrit/models/message.py and pyrit/models/message_piece.py paths so
existing imports keep working. Everything remains re-exported from
pyrit.models.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…actor-plan

# Conflicts:
#	pyrit/models/__init__.py
#	pyrit/models/message_piece.py
Comment thread pyrit/models/messages/message.py
@rlundeen2
Copy link
Copy Markdown
Contributor Author

There is a failing test, but not in this PR. Fixed here: #1866

@rlundeen2 rlundeen2 added this pull request to the merge queue Jun 2, 2026
Merged via the queue into microsoft:main with commit f43855b Jun 2, 2026
47 of 48 checks passed
@rlundeen2 rlundeen2 deleted the rlundeen2/message-refactor-plan branch June 2, 2026 18:16
romanlutz added a commit to romanlutz/PyRIT that referenced this pull request Jun 2, 2026
…refactor

The Pydantic refactor (PRs microsoft#1871, microsoft#1885) moved the real Message and MessagePiece
classes from pyrit/models/message.py and pyrit/models/message_piece.py into
pyrit/models/messages/message.py and pyrit/models/messages/message_piece.py,
leaving the old module paths as backward-compatibility shims with __getattr__
fallbacks.

My test patches at 'pyrit.models.message.datetime' and 'pyrit.models.message_piece.datetime'
were setting attributes on those shims, which the real datetime.now() calls in the
relocated modules never saw -- the patches silently no-op'd. Update the paths to
point at the new module locations so the patches actually intercept the calls.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
rlundeen2 added a commit to riedgar-ms/PyRIT that referenced this pull request Jun 4, 2026
Reconciles the JSON-schema-on-seeds refactor with main's Seed-to-Pydantic
migration (microsoft#1898), Message module rename (microsoft#1885), and pyrit.common
import-boundary cleanup.

Conflict resolutions:
- pyrit/models/seeds/seed_prompt.py: ported response_json_schema and
  response_json_schema_name from dataclass/InitVar/__post_init__ onto
  main's Pydantic model. Used @model_validator(mode='before') to pop
  response_json_schema_name from input data before Pydantic's
  extra='forbid' rejects it, preserving the init-only semantic.
- pyrit/models/__init__.py: kept both main's MEDIA_PATH_DATA_TYPES /
  messages-module rename and this branch's json_schema_definition
  re-exports.
- tests/unit/models/test_import_boundary.py: accepted main's empty
  KNOWN_TOP_LEVEL_VIOLATIONS (main now allows the full pyrit.common
  prefix from pyrit.models, retiring the per-module ratchet entries).
- tests/unit/models/test_seed_prompt.py: replaced dataclasses.fields
  introspection with SeedPrompt.model_fields for the
  response_json_schema_name regression guard.

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