Skip to content

Commit d1dda55

Browse files
Add Rasterize PDF
Assisted-by: Codex
1 parent c16b0c3 commit d1dda55

4 files changed

Lines changed: 452 additions & 0 deletions

File tree

src/pdfrest/client.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
PdfRedactionPreviewPayload,
9090
PdfRestRawFileResponse,
9191
PdfFlattenTransparenciesPayload,
92+
PdfRasterizePayload,
9293
PdfSplitPayload,
9394
PdfToExcelPayload,
9495
PdfToPdfxPayload,
@@ -2606,6 +2607,32 @@ def linearize_pdf(
26062607
timeout=timeout,
26072608
)
26082609

2610+
def rasterize_pdf(
2611+
self,
2612+
file: PdfRestFile | Sequence[PdfRestFile],
2613+
*,
2614+
output: str | None = None,
2615+
extra_query: Query | None = None,
2616+
extra_headers: AnyMapping | None = None,
2617+
extra_body: Body | None = None,
2618+
timeout: TimeoutTypes | None = None,
2619+
) -> PdfRestFileBasedResponse:
2620+
"""Rasterize a PDF into a flattened bitmap-based PDF."""
2621+
2622+
payload: dict[str, Any] = {"files": file}
2623+
if output is not None:
2624+
payload["output"] = output
2625+
2626+
return self._post_file_operation(
2627+
endpoint="/rasterized-pdf",
2628+
payload=payload,
2629+
payload_model=PdfRasterizePayload,
2630+
extra_query=extra_query,
2631+
extra_headers=extra_headers,
2632+
extra_body=extra_body,
2633+
timeout=timeout,
2634+
)
2635+
26092636
def convert_to_pdfx(
26102637
self,
26112638
file: PdfRestFile | Sequence[PdfRestFile],
@@ -3506,6 +3533,32 @@ async def linearize_pdf(
35063533
timeout=timeout,
35073534
)
35083535

3536+
async def rasterize_pdf(
3537+
self,
3538+
file: PdfRestFile | Sequence[PdfRestFile],
3539+
*,
3540+
output: str | None = None,
3541+
extra_query: Query | None = None,
3542+
extra_headers: AnyMapping | None = None,
3543+
extra_body: Body | None = None,
3544+
timeout: TimeoutTypes | None = None,
3545+
) -> PdfRestFileBasedResponse:
3546+
"""Asynchronously rasterize a PDF into a flattened bitmap-based PDF."""
3547+
3548+
payload: dict[str, Any] = {"files": file}
3549+
if output is not None:
3550+
payload["output"] = output
3551+
3552+
return await self._post_file_operation(
3553+
endpoint="/rasterized-pdf",
3554+
payload=payload,
3555+
payload_model=PdfRasterizePayload,
3556+
extra_query=extra_query,
3557+
extra_headers=extra_headers,
3558+
extra_body=extra_body,
3559+
timeout=timeout,
3560+
)
3561+
35093562
async def convert_to_pdfx(
35103563
self,
35113564
file: PdfRestFile | Sequence[PdfRestFile],

src/pdfrest/models/_internal.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -889,6 +889,30 @@ class PdfLinearizePayload(BaseModel):
889889
] = None
890890

891891

892+
class PdfRasterizePayload(BaseModel):
893+
"""Adapt caller options into a pdfRest-ready rasterize PDF request payload."""
894+
895+
files: Annotated[
896+
list[PdfRestFile],
897+
Field(
898+
min_length=1,
899+
max_length=1,
900+
validation_alias=AliasChoices("file", "files"),
901+
serialization_alias="id",
902+
),
903+
BeforeValidator(_ensure_list),
904+
AfterValidator(
905+
_allowed_mime_types("application/pdf", error_msg="Must be a PDF file")
906+
),
907+
PlainSerializer(_serialize_as_first_file_id),
908+
]
909+
output: Annotated[
910+
str | None,
911+
Field(serialization_alias="output", min_length=1, default=None),
912+
AfterValidator(_validate_output_prefix),
913+
] = None
914+
915+
892916
class PdfFlattenTransparenciesPayload(BaseModel):
893917
"""Adapt caller options into a pdfRest-ready flatten-transparencies request payload."""
894918

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
from __future__ import annotations
2+
3+
import pytest
4+
5+
from pdfrest import AsyncPdfRestClient, PdfRestApiError, PdfRestClient
6+
from pdfrest.models import PdfRestFile
7+
8+
from ..resources import get_test_resource_path
9+
10+
11+
@pytest.fixture(scope="module")
12+
def uploaded_pdf_for_rasterize(
13+
pdfrest_api_key: str,
14+
pdfrest_live_base_url: str,
15+
) -> PdfRestFile:
16+
resource = get_test_resource_path("report.pdf")
17+
with PdfRestClient(
18+
api_key=pdfrest_api_key,
19+
base_url=pdfrest_live_base_url,
20+
) as client:
21+
return client.files.create_from_paths([resource])[0]
22+
23+
24+
@pytest.mark.parametrize(
25+
"output_name",
26+
[
27+
pytest.param(None, id="default-output"),
28+
pytest.param("rasterized-live", id="custom-output"),
29+
],
30+
)
31+
def test_live_rasterize_pdf_success(
32+
pdfrest_api_key: str,
33+
pdfrest_live_base_url: str,
34+
uploaded_pdf_for_rasterize: PdfRestFile,
35+
output_name: str | None,
36+
) -> None:
37+
kwargs: dict[str, str] = {}
38+
if output_name is not None:
39+
kwargs["output"] = output_name
40+
41+
with PdfRestClient(
42+
api_key=pdfrest_api_key,
43+
base_url=pdfrest_live_base_url,
44+
) as client:
45+
response = client.rasterize_pdf(uploaded_pdf_for_rasterize, **kwargs)
46+
47+
assert response.output_files
48+
output_file = response.output_file
49+
assert output_file.type == "application/pdf"
50+
assert str(response.input_id) == str(uploaded_pdf_for_rasterize.id)
51+
if output_name is not None:
52+
assert output_file.name.startswith(output_name)
53+
else:
54+
assert output_file.name.endswith(".pdf")
55+
56+
57+
@pytest.mark.asyncio
58+
async def test_live_async_rasterize_pdf_success(
59+
pdfrest_api_key: str,
60+
pdfrest_live_base_url: str,
61+
uploaded_pdf_for_rasterize: PdfRestFile,
62+
) -> None:
63+
async with AsyncPdfRestClient(
64+
api_key=pdfrest_api_key,
65+
base_url=pdfrest_live_base_url,
66+
) as client:
67+
response = await client.rasterize_pdf(
68+
uploaded_pdf_for_rasterize, output="async"
69+
)
70+
71+
assert response.output_files
72+
output_file = response.output_file
73+
assert output_file.name.startswith("async")
74+
assert output_file.type == "application/pdf"
75+
assert str(response.input_id) == str(uploaded_pdf_for_rasterize.id)
76+
77+
78+
def test_live_rasterize_pdf_invalid_file_id(
79+
pdfrest_api_key: str,
80+
pdfrest_live_base_url: str,
81+
uploaded_pdf_for_rasterize: PdfRestFile,
82+
) -> None:
83+
with (
84+
PdfRestClient(
85+
api_key=pdfrest_api_key,
86+
base_url=pdfrest_live_base_url,
87+
) as client,
88+
pytest.raises(PdfRestApiError),
89+
):
90+
client.rasterize_pdf(
91+
uploaded_pdf_for_rasterize,
92+
extra_body={"id": "00000000-0000-0000-0000-000000000000"},
93+
)
94+
95+
96+
@pytest.mark.asyncio
97+
async def test_live_async_rasterize_pdf_invalid_file_id(
98+
pdfrest_api_key: str,
99+
pdfrest_live_base_url: str,
100+
uploaded_pdf_for_rasterize: PdfRestFile,
101+
) -> None:
102+
async with AsyncPdfRestClient(
103+
api_key=pdfrest_api_key,
104+
base_url=pdfrest_live_base_url,
105+
) as client:
106+
with pytest.raises(PdfRestApiError):
107+
await client.rasterize_pdf(
108+
uploaded_pdf_for_rasterize,
109+
extra_body={"id": "ffffffff-ffff-ffff-ffff-ffffffffffff"},
110+
)

0 commit comments

Comments
 (0)