Skip to content

Commit 765677a

Browse files
biefanCopilotromanlutz
authored
MAINT: Remove deprecated message init in JSON schema normalizer (#2091)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Roman Lutz <romanlutz13@gmail.com>
1 parent c8418c9 commit 765677a

14 files changed

Lines changed: 84 additions & 78 deletions

doc/code/memory/5_advanced_memory.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@
263263
)
264264

265265
# Wrap each piece in a Message so we can pass it to score_async
266-
assistant_messages = [Message([piece]) for piece in assistant_pieces]
266+
assistant_messages = [Message(message_pieces=[piece]) for piece in assistant_pieces]
267267

268268
# Score every response with both scorers — scores are automatically persisted in memory
269269
for msg in assistant_messages:

doc/code/memory/6_azure_sql_memory.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@
7373
),
7474
]
7575

76-
memory.add_message_to_memory(request=Message([message_list[0]]))
77-
memory.add_message_to_memory(request=Message([message_list[1]]))
78-
memory.add_message_to_memory(request=Message([message_list[2]]))
76+
memory.add_message_to_memory(request=Message(message_pieces=[message_list[0]]))
77+
memory.add_message_to_memory(request=Message(message_pieces=[message_list[1]]))
78+
memory.add_message_to_memory(request=Message(message_pieces=[message_list[2]]))
7979

8080
entries = memory.get_conversation_messages(conversation_id=conversation_id)
8181

doc/code/targets/4_openai_video_target.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@
148148
original_value="Make it a watercolor painting style",
149149
prompt_metadata={"video_id": video_id},
150150
)
151-
remix_result = await video_target.send_prompt_async(message=Message([remix_piece])) # type: ignore
151+
remix_result = await video_target.send_prompt_async(message=Message(message_pieces=[remix_piece])) # type: ignore
152152
print(f"Remixed video: {remix_result[0].message_pieces[0].converted_value}")
153153

154154
# %% [markdown]
@@ -190,5 +190,5 @@
190190
converted_value_data_type="image_path",
191191
conversation_id=conversation_id,
192192
)
193-
result = await i2v_target.send_prompt_async(message=Message([text_piece, image_piece])) # type: ignore
193+
result = await i2v_target.send_prompt_async(message=Message(message_pieces=[text_piece, image_piece])) # type: ignore
194194
print(f"Text+Image-to-video result: {result[0].message_pieces[0].converted_value}")

doc/code/targets/6_1_target_capabilities.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,7 @@
304304
def _ok_response():
305305
return [
306306
Message(
307-
[
307+
message_pieces=[
308308
MessagePiece(
309309
role="assistant",
310310
original_value="ok",

pyrit/message_normalizer/json_schema_normalizer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ def _adapt_message(self, *, message: Message) -> Message:
126126
if not changed:
127127
return message
128128

129-
return Message(new_pieces)
129+
return Message(message_pieces=new_pieces)
130130

131131
def _adapt_piece(self, *, piece: MessagePiece) -> MessagePiece:
132132
"""

tests/integration/targets/test_entra_auth_targets.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ async def test_video_target_remix_entra_auth(sqlite_instance):
332332
original_value="A bird flying over a lake",
333333
converted_value="A bird flying over a lake",
334334
)
335-
result = await target.send_prompt_async(message=Message([text_piece]))
335+
result = await target.send_prompt_async(message=Message(message_pieces=[text_piece]))
336336
response_piece = result[0].message_pieces[0]
337337
assert response_piece.response_error == "none"
338338
video_id = response_piece.prompt_metadata.get("video_id")
@@ -345,7 +345,7 @@ async def test_video_target_remix_entra_auth(sqlite_instance):
345345
converted_value="Add a sunset",
346346
prompt_metadata={"video_id": video_id},
347347
)
348-
remix_result = await target.send_prompt_async(message=Message([remix_piece]))
348+
remix_result = await target.send_prompt_async(message=Message(message_pieces=[remix_piece]))
349349
assert remix_result[0].message_pieces[0].response_error == "none"
350350

351351

tests/integration/targets/test_targets_and_secrets.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ async def test_video_remix_chain(sqlite_instance):
571571
original_value="A cat sitting on a windowsill",
572572
converted_value="A cat sitting on a windowsill",
573573
)
574-
result = await target.send_prompt_async(message=Message([text_piece]))
574+
result = await target.send_prompt_async(message=Message(message_pieces=[text_piece]))
575575
assert len(result) == 1
576576
response_piece = result[0].message_pieces[0]
577577
assert response_piece.response_error == "none"
@@ -586,7 +586,7 @@ async def test_video_remix_chain(sqlite_instance):
586586
converted_value="Make it a watercolor painting style",
587587
prompt_metadata={"video_id": video_id},
588588
)
589-
remix_result = await target.send_prompt_async(message=Message([remix_piece]))
589+
remix_result = await target.send_prompt_async(message=Message(message_pieces=[remix_piece]))
590590
assert len(remix_result) == 1
591591
remix_response = remix_result[0].message_pieces[0]
592592
assert remix_response.response_error == "none"
@@ -636,7 +636,7 @@ async def test_video_image_to_video(sqlite_instance):
636636
converted_value_data_type="image_path",
637637
conversation_id=conversation_id,
638638
)
639-
result = await target.send_prompt_async(message=Message([text_piece, image_piece]))
639+
result = await target.send_prompt_async(message=Message(message_pieces=[text_piece, image_piece]))
640640
assert len(result) == 1
641641
response_piece = result[0].message_pieces[0]
642642
assert response_piece.response_error == "none", f"Image-to-video failed: {response_piece.converted_value}"

tests/unit/message_normalizer/test_json_schema_normalizer.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class TestJsonSchemaNormalizer:
4646
async def test_text_piece_gets_schema_appended_to_converted_value(self, normalizer: JsonSchemaNormalizer) -> None:
4747
schema = {"type": "object", "properties": {"answer": {"type": "string"}}}
4848
piece = _text_piece(value="Answer the question.", metadata={JSON_SCHEMA_METADATA_KEY: schema})
49-
message = Message([piece])
49+
message = Message(message_pieces=[piece])
5050

5151
result = await normalizer.normalize_async([message])
5252
out_piece = result[0].message_pieces[0]
@@ -66,7 +66,7 @@ async def test_text_piece_preserves_other_metadata(self, normalizer: JsonSchemaN
6666
"other": 7,
6767
},
6868
)
69-
result = await normalizer.normalize_async([Message([piece])])
69+
result = await normalizer.normalize_async([Message(message_pieces=[piece])])
7070
new_metadata = result[0].message_pieces[0].prompt_metadata
7171
assert JSON_SCHEMA_METADATA_KEY not in new_metadata
7272
assert new_metadata == {"response_format": "json", "other": 7}
@@ -76,7 +76,7 @@ async def test_non_text_piece_only_strips_key(self, normalizer: JsonSchemaNormal
7676
piece = _image_piece(value="fake.jpg", metadata={JSON_SCHEMA_METADATA_KEY: schema, "extra": "stay"})
7777
original_converted_value = piece.converted_value
7878

79-
result = await normalizer.normalize_async([Message([piece])])
79+
result = await normalizer.normalize_async([Message(message_pieces=[piece])])
8080
out_piece = result[0].message_pieces[0]
8181

8282
assert JSON_SCHEMA_METADATA_KEY not in out_piece.prompt_metadata
@@ -87,7 +87,7 @@ async def test_non_text_piece_only_strips_key(self, normalizer: JsonSchemaNormal
8787

8888
async def test_no_schema_is_noop(self, normalizer: JsonSchemaNormalizer) -> None:
8989
piece = _text_piece(value="just say hi", metadata={"unrelated": True})
90-
message = Message([piece])
90+
message = Message(message_pieces=[piece])
9191

9292
result = await normalizer.normalize_async([message])
9393

@@ -98,7 +98,7 @@ async def test_input_pieces_not_mutated(self, normalizer: JsonSchemaNormalizer)
9898
schema = {"type": "object"}
9999
piece = _text_piece(value="hi", metadata={JSON_SCHEMA_METADATA_KEY: schema})
100100

101-
await normalizer.normalize_async([Message([piece])])
101+
await normalizer.normalize_async([Message(message_pieces=[piece])])
102102

103103
# The original piece still carries the schema and its unchanged text.
104104
assert piece.prompt_metadata == {JSON_SCHEMA_METADATA_KEY: schema}
@@ -117,7 +117,7 @@ async def test_mixed_pieces_in_message_each_handled(self, normalizer: JsonSchema
117117
)
118118
no_schema_piece = _text_piece(value="z", metadata={"foo": "bar"}, conversation_id=conversation_id)
119119

120-
result = await normalizer.normalize_async([Message([text_piece, image_piece, no_schema_piece])])
120+
result = await normalizer.normalize_async([Message(message_pieces=[text_piece, image_piece, no_schema_piece])])
121121
out_pieces = result[0].message_pieces
122122

123123
assert JSON_SCHEMA_METADATA_KEY not in out_pieces[0].prompt_metadata
@@ -133,8 +133,8 @@ async def test_mixed_pieces_in_message_each_handled(self, normalizer: JsonSchema
133133

134134
async def test_multiple_messages(self, normalizer: JsonSchemaNormalizer) -> None:
135135
schema = {"type": "object"}
136-
msg_with_schema = Message([_text_piece(value="a", metadata={JSON_SCHEMA_METADATA_KEY: schema})])
137-
msg_without_schema = Message([_text_piece(value="b", metadata={})])
136+
msg_with_schema = Message(message_pieces=[_text_piece(value="a", metadata={JSON_SCHEMA_METADATA_KEY: schema})])
137+
msg_without_schema = Message(message_pieces=[_text_piece(value="b", metadata={})])
138138

139139
result = await normalizer.normalize_async([msg_with_schema, msg_without_schema])
140140
assert "### Response format" in result[0].message_pieces[0].converted_value
@@ -155,7 +155,7 @@ async def test_appended_text_lists_schema_keys(self, normalizer: JsonSchemaNorma
155155
}
156156
piece = _text_piece(value="prompt", metadata={JSON_SCHEMA_METADATA_KEY: schema})
157157

158-
result = await normalizer.normalize_async([Message([piece])])
158+
result = await normalizer.normalize_async([Message(message_pieces=[piece])])
159159
appended = result[0].message_pieces[0].converted_value
160160

161161
# Sanity-check that the rendered text actually surfaces schema field names.
@@ -170,7 +170,7 @@ async def test_custom_template_is_used(self) -> None:
170170
schema = {"type": "object"}
171171
piece = _text_piece(value="hi", metadata={JSON_SCHEMA_METADATA_KEY: schema})
172172

173-
result = await normalizer.normalize_async([Message([piece])])
173+
result = await normalizer.normalize_async([Message(message_pieces=[piece])])
174174
out_value = result[0].message_pieces[0].converted_value
175175

176176
assert "<<SCHEMA START>>" in out_value

tests/unit/models/test_message.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def test_get_pieces_by_type_returns_matching_pieces() -> None:
7373
converted_value_data_type="image_path",
7474
conversation_id=conversation_id,
7575
)
76-
msg = Message([text_piece, image_piece])
76+
msg = Message(message_pieces=[text_piece, image_piece])
7777

7878
result = msg.get_pieces_by_type(data_type="text")
7979
assert len(result) == 1
@@ -86,21 +86,21 @@ def test_get_pieces_by_type_returns_matching_pieces() -> None:
8686

8787
def test_get_pieces_by_type_returns_empty_for_no_match() -> None:
8888
piece = MessagePiece(role="user", original_value="hello", converted_value="hello")
89-
msg = Message([piece])
89+
msg = Message(message_pieces=[piece])
9090
assert msg.get_pieces_by_type(data_type="image_path") == []
9191

9292

9393
def test_get_piece_by_type_returns_first_match() -> None:
9494
conversation_id = "test-conv"
9595
text1 = MessagePiece(role="user", original_value="a", converted_value="a", conversation_id=conversation_id)
9696
text2 = MessagePiece(role="user", original_value="b", converted_value="b", conversation_id=conversation_id)
97-
msg = Message([text1, text2])
97+
msg = Message(message_pieces=[text1, text2])
9898
assert msg.get_piece_by_type(data_type="text") is text1
9999

100100

101101
def test_get_piece_by_type_returns_none_for_no_match() -> None:
102102
piece = MessagePiece(role="user", original_value="hello", converted_value="hello")
103-
msg = Message([piece])
103+
msg = Message(message_pieces=[piece])
104104
assert msg.get_piece_by_type(data_type="image_path") is None
105105

106106

tests/unit/prompt_target/target/test_image_target.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ async def test_send_prompt_async_generate(
8080
with patch.object(image_target._async_client.images, "generate", new_callable=AsyncMock) as mock_generate:
8181
mock_generate.return_value = mock_response
8282

83-
resp = await image_target.send_prompt_async(message=Message([request]))
83+
resp = await image_target.send_prompt_async(message=Message(message_pieces=[request]))
8484
assert len(resp) == 1
8585
assert resp
8686
path = resp[0].message_pieces[0].original_value
@@ -115,7 +115,7 @@ async def test_send_prompt_async_edit(
115115
with patch.object(image_target._async_client.images, "edit", new_callable=AsyncMock) as mock_edit:
116116
mock_edit.return_value = mock_response
117117

118-
resp = await image_target.send_prompt_async(message=Message([text_piece, image_piece]))
118+
resp = await image_target.send_prompt_async(message=Message(message_pieces=[text_piece, image_piece]))
119119
assert len(resp) == 1
120120
assert resp
121121
path = resp[0].message_pieces[0].original_value
@@ -151,7 +151,7 @@ async def test_send_prompt_async_edit_single_image_passes_tuple_not_list(
151151
with patch.object(image_target._async_client.images, "edit", new_callable=AsyncMock) as mock_edit:
152152
mock_edit.return_value = mock_response
153153

154-
resp = await image_target.send_prompt_async(message=Message([text_piece, image_piece]))
154+
resp = await image_target.send_prompt_async(message=Message(message_pieces=[text_piece, image_piece]))
155155
assert resp
156156

157157
call_kwargs = mock_edit.call_args[1]
@@ -189,7 +189,9 @@ async def test_send_prompt_async_edit_multiple_images(
189189
with patch.object(image_target._async_client.images, "edit", new_callable=AsyncMock) as mock_edit:
190190
mock_edit.return_value = mock_response
191191

192-
resp = await image_target.send_prompt_async(message=Message([image_piece, text_piece] + image_pieces))
192+
resp = await image_target.send_prompt_async(
193+
message=Message(message_pieces=[image_piece, text_piece] + image_pieces)
194+
)
193195
assert len(resp) == 1
194196
assert resp
195197
path = resp[0].message_pieces[0].original_value
@@ -226,7 +228,7 @@ async def test_send_prompt_async_invalid_image_path(
226228
)
227229

228230
with pytest.raises(FileNotFoundError):
229-
await image_target.send_prompt_async(message=Message([text_piece, image_piece]))
231+
await image_target.send_prompt_async(message=Message(message_pieces=[text_piece, image_piece]))
230232

231233

232234
async def test_send_prompt_async_empty_response(
@@ -248,7 +250,7 @@ async def test_send_prompt_async_empty_response(
248250
mock_generate.return_value = mock_response
249251

250252
with pytest.raises(EmptyResponseException):
251-
await image_target.send_prompt_async(message=Message([request]))
253+
await image_target.send_prompt_async(message=Message(message_pieces=[request]))
252254

253255

254256
async def test_send_prompt_async_rate_limit_exception(
@@ -264,7 +266,7 @@ async def test_send_prompt_async_rate_limit_exception(
264266
mock_generate.side_effect = RateLimitError("Rate Limit Reached", response=MagicMock(), body={})
265267

266268
with pytest.raises(RateLimitException):
267-
await image_target.send_prompt_async(message=Message([request]))
269+
await image_target.send_prompt_async(message=Message(message_pieces=[request]))
268270

269271

270272
async def test_send_prompt_async_bad_request_error(
@@ -290,7 +292,7 @@ async def test_send_prompt_async_bad_request_error(
290292

291293
# Non-content-filter BadRequestError should be re-raised (same as chat target behavior)
292294
with pytest.raises(Exception):
293-
await image_target.send_prompt_async(message=Message([request]))
295+
await image_target.send_prompt_async(message=Message(message_pieces=[request]))
294296

295297

296298
async def test_send_prompt_async_empty_response_adds_memory(
@@ -316,7 +318,7 @@ async def test_send_prompt_async_empty_response_adds_memory(
316318
image_target._memory = mock_memory
317319

318320
with pytest.raises(EmptyResponseException):
319-
await image_target.send_prompt_async(message=Message([request]))
321+
await image_target.send_prompt_async(message=Message(message_pieces=[request]))
320322

321323

322324
async def test_send_prompt_async_rate_limit_adds_memory(
@@ -338,7 +340,7 @@ async def test_send_prompt_async_rate_limit_adds_memory(
338340
image_target._memory = mock_memory
339341

340342
with pytest.raises(RateLimitException):
341-
await image_target.send_prompt_async(message=Message([request]))
343+
await image_target.send_prompt_async(message=Message(message_pieces=[request]))
342344

343345

344346
async def test_send_prompt_async_bad_request_content_filter(
@@ -364,7 +366,7 @@ async def test_send_prompt_async_bad_request_content_filter(
364366

365367
with patch.object(image_target._async_client.images, "generate", new_callable=AsyncMock) as mock_generate:
366368
mock_generate.side_effect = bad_request_error
367-
result = await image_target.send_prompt_async(message=Message([request]))
369+
result = await image_target.send_prompt_async(message=Message(message_pieces=[request]))
368370
assert len(result) == 1
369371
assert result[0].message_pieces[0].converted_value_data_type == "error"
370372
assert "content_filter" in result[0].message_pieces[0].converted_value
@@ -393,7 +395,7 @@ async def test_send_prompt_async_bad_request_content_policy_violation(
393395

394396
with patch.object(image_target._async_client.images, "generate", new_callable=AsyncMock) as mock_generate:
395397
mock_generate.side_effect = bad_request_error
396-
result = await image_target.send_prompt_async(message=Message([request]))
398+
result = await image_target.send_prompt_async(message=Message(message_pieces=[request]))
397399
assert len(result) == 1
398400
assert result[0].message_pieces[0].response_error == "blocked"
399401
assert result[0].message_pieces[0].converted_value_data_type == "error"
@@ -542,7 +544,7 @@ async def test_generate_request_passes_background(
542544
with patch.object(image_target._async_client.images, "generate", new_callable=AsyncMock) as mock_generate:
543545
mock_generate.return_value = mock_response
544546

545-
resp = await image_target.send_prompt_async(message=Message([request]))
547+
resp = await image_target.send_prompt_async(message=Message(message_pieces=[request]))
546548
assert resp
547549

548550
call_kwargs = mock_generate.call_args[1]
@@ -569,7 +571,7 @@ async def test_generate_request_omits_background_when_none(
569571
with patch.object(image_target._async_client.images, "generate", new_callable=AsyncMock) as mock_generate:
570572
mock_generate.return_value = mock_response
571573

572-
resp = await image_target.send_prompt_async(message=Message([request]))
574+
resp = await image_target.send_prompt_async(message=Message(message_pieces=[request]))
573575
assert resp
574576

575577
call_kwargs = mock_generate.call_args[1]

0 commit comments

Comments
 (0)