Skip to content

Commit 9aa6288

Browse files
Address Copilot review feedback
- Use Path.suffix.lower() for case-insensitive .json detection in _save_response so Path('x.JSON') is treated as full-path mode. - Expand _save_response docstring to describe both modes and the 'output' filename special case. - Wrap AsyncLandingAIADE in async-with in test_save_to.py to close the underlying httpx client and avoid resource warnings.
1 parent 2f34814 commit 9aa6288

2 files changed

Lines changed: 30 additions & 28 deletions

File tree

src/landingai_ade/_client.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,14 +128,16 @@ def _save_response(
128128
) -> None:
129129
"""Save API response to a JSON file.
130130
131-
If save_to ends with '.json', it is treated as a full file path and the
132-
response is written there directly. Otherwise it is treated as a directory
133-
and the file is auto-named '{filename}_{method_name}_output.json'
134-
(or '{method_name}_output.json' when filename is 'output').
131+
If save_to has a '.json' suffix (case-insensitive), it is treated as a full
132+
file path and the response is written there directly. Otherwise it is
133+
treated as a directory and the file is auto-named
134+
'{filename}_{method_name}_output.json', except when filename is 'output'
135+
(i.e. no input filename could be derived) — in that case the redundant
136+
prefix is dropped and the file is named '{method_name}_output.json'.
135137
"""
136138
try:
137139
save_path = Path(save_to)
138-
if str(save_to).endswith(".json"):
140+
if save_path.suffix.lower() == ".json":
139141
save_path.parent.mkdir(parents=True, exist_ok=True)
140142
save_path.write_text(result.to_json())
141143
else:

tests/test_save_to.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -220,13 +220,13 @@ def mock_response(self) -> MagicMock:
220220
async def test_async_extract_save_to_directory(self, tmp_path: Path, mock_response: MagicMock) -> None:
221221
from unittest.mock import AsyncMock, patch
222222

223-
client = AsyncLandingAIADE(apikey="test-key", base_url="http://localhost")
224-
with patch.object(client, "post", new_callable=AsyncMock, return_value=mock_response):
225-
result = await client.extract(
226-
schema="{}",
227-
markdown=Path("/path/to/doc.pdf"),
228-
save_to=tmp_path,
229-
)
223+
async with AsyncLandingAIADE(apikey="test-key", base_url="http://localhost") as client:
224+
with patch.object(client, "post", new_callable=AsyncMock, return_value=mock_response):
225+
result = await client.extract(
226+
schema="{}",
227+
markdown=Path("/path/to/doc.pdf"),
228+
save_to=tmp_path,
229+
)
230230

231231
assert (tmp_path / "doc_extract_output.json").exists()
232232
assert result is mock_response
@@ -236,43 +236,43 @@ async def test_async_extract_save_to_json_path(self, tmp_path: Path, mock_respon
236236
from unittest.mock import AsyncMock, patch
237237

238238
output_file = tmp_path / "custom.json"
239-
client = AsyncLandingAIADE(apikey="test-key", base_url="http://localhost")
240-
with patch.object(client, "post", new_callable=AsyncMock, return_value=mock_response):
241-
await client.extract(schema="{}", markdown=Path("/doc.pdf"), save_to=output_file)
239+
async with AsyncLandingAIADE(apikey="test-key", base_url="http://localhost") as client:
240+
with patch.object(client, "post", new_callable=AsyncMock, return_value=mock_response):
241+
await client.extract(schema="{}", markdown=Path("/doc.pdf"), save_to=output_file)
242242

243243
assert output_file.exists()
244244

245245
@pytest.mark.asyncio
246246
async def test_async_parse_save_to(self, tmp_path: Path, mock_response: MagicMock) -> None:
247247
from unittest.mock import AsyncMock, patch
248248

249-
client = AsyncLandingAIADE(apikey="test-key", base_url="http://localhost")
250-
with patch.object(client, "post", new_callable=AsyncMock, return_value=mock_response):
251-
await client.parse(document=Path("/path/to/doc.pdf"), save_to=tmp_path)
249+
async with AsyncLandingAIADE(apikey="test-key", base_url="http://localhost") as client:
250+
with patch.object(client, "post", new_callable=AsyncMock, return_value=mock_response):
251+
await client.parse(document=Path("/path/to/doc.pdf"), save_to=tmp_path)
252252

253253
assert (tmp_path / "doc_parse_output.json").exists()
254254

255255
@pytest.mark.asyncio
256256
async def test_async_split_save_to(self, tmp_path: Path, mock_response: MagicMock) -> None:
257257
from unittest.mock import AsyncMock, patch
258258

259-
client = AsyncLandingAIADE(apikey="test-key", base_url="http://localhost")
260-
with patch.object(client, "post", new_callable=AsyncMock, return_value=mock_response):
261-
await client.split(
262-
split_class=[{"name": "type1"}],
263-
markdown=Path("/path/to/doc.md"),
264-
save_to=tmp_path,
265-
)
259+
async with AsyncLandingAIADE(apikey="test-key", base_url="http://localhost") as client:
260+
with patch.object(client, "post", new_callable=AsyncMock, return_value=mock_response):
261+
await client.split(
262+
split_class=[{"name": "type1"}],
263+
markdown=Path("/path/to/doc.md"),
264+
save_to=tmp_path,
265+
)
266266

267267
assert (tmp_path / "doc_split_output.json").exists()
268268

269269
@pytest.mark.asyncio
270270
async def test_async_no_save_when_save_to_none(self, tmp_path: Path, mock_response: MagicMock) -> None:
271271
from unittest.mock import AsyncMock, patch
272272

273-
client = AsyncLandingAIADE(apikey="test-key", base_url="http://localhost")
274-
with patch.object(client, "post", new_callable=AsyncMock, return_value=mock_response):
275-
result = await client.extract(schema="{}")
273+
async with AsyncLandingAIADE(apikey="test-key", base_url="http://localhost") as client:
274+
with patch.object(client, "post", new_callable=AsyncMock, return_value=mock_response):
275+
result = await client.extract(schema="{}")
276276

277277
assert result is mock_response
278278
assert not list(tmp_path.iterdir())

0 commit comments

Comments
 (0)