Skip to content

Commit c9a7c87

Browse files
committed
fix(evaluation): preserve prompt newline bytes
1 parent 97394aa commit c9a7c87

2 files changed

Lines changed: 33 additions & 3 deletions

File tree

tests/evaluation/test_target_prompt.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,30 @@ async def test_read_all_with_paths(tmp_path: Path):
129129
assert await target.read_all() == {"a": "alpha", "b": "beta"}
130130

131131

132+
@pytest.mark.parametrize(
133+
"original_bytes",
134+
[
135+
"system prompt\nkeep exact bytes\n".encode("utf-8"),
136+
"system prompt\r\nkeep exact bytes\r\n".encode("utf-8"),
137+
"lf\ncrlf\r\nlone carriage return\rend".encode("utf-8"),
138+
],
139+
ids=["lf", "crlf", "mixed"],
140+
)
141+
@pytest.mark.asyncio
142+
async def test_path_read_write_round_trip_preserves_newline_bytes(
143+
tmp_path: Path,
144+
original_bytes: bytes,
145+
):
146+
prompt_path = tmp_path / "prompt.md"
147+
prompt_path.write_bytes(original_bytes)
148+
target = TargetPrompt().add_path("prompt", str(prompt_path))
149+
150+
snapshot = await target.read_all()
151+
await target.write_all(snapshot)
152+
153+
assert prompt_path.read_bytes() == original_bytes
154+
155+
132156
@pytest.mark.asyncio
133157
async def test_read_all_path_not_exist_raises_file_not_found(tmp_path: Path):
134158
target = TargetPrompt().add_path("missing", str(tmp_path / "ghost.md"))

trpc_agent_sdk/evaluation/_target_prompt.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ def _snapshot_path_contents(self) -> dict[str, Optional[str]]:
180180
for name, src in self._sources.items():
181181
if isinstance(src, _PathSource):
182182
try:
183-
snapshot[name] = Path(src.path).read_text(encoding="utf-8")
183+
snapshot[name] = self._read_path(src.path)
184184
except FileNotFoundError:
185185
snapshot[name] = None
186186
return snapshot
@@ -232,12 +232,18 @@ def _cleanup_tmp_files(self) -> None:
232232
@staticmethod
233233
def _atomic_write_path(path: str, content: str) -> None:
234234
tmp = path + ".tmp"
235-
Path(tmp).write_text(content, encoding="utf-8")
235+
with Path(tmp).open("w", encoding="utf-8", newline="") as prompt_file:
236+
prompt_file.write(content)
236237
os.replace(tmp, path)
237238

239+
@staticmethod
240+
def _read_path(path: str) -> str:
241+
with Path(path).open("r", encoding="utf-8", newline="") as prompt_file:
242+
return prompt_file.read()
243+
238244
async def _read_one(self, src: _Source) -> str:
239245
if isinstance(src, _PathSource):
240-
return Path(src.path).read_text(encoding="utf-8")
246+
return self._read_path(src.path)
241247
if isinstance(src, _CallbackSource):
242248
return await src.read_fn()
243249
raise TypeError(f"unknown source type: {type(src).__name__}")

0 commit comments

Comments
 (0)