Skip to content

Commit b4ffe7e

Browse files
blank-pdf: Encapsulate custom page dimensions
Assisted-by: Codex
1 parent ffde7f9 commit b4ffe7e

5 files changed

Lines changed: 82 additions & 32 deletions

File tree

src/pdfrest/models/_internal.py

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,19 +1404,20 @@ def _normalize_custom_page_size(cls, data: Any) -> Any:
14041404

14051405
normalized_data: dict[str, Any] = dict(cast(Mapping[str, Any], data))
14061406
page_size = normalized_data.get("page_size")
1407-
if isinstance(page_size, Sequence) and not isinstance(
1408-
page_size, (str, bytes, bytearray)
1409-
):
1410-
custom_dimensions = list(page_size)
1411-
if len(custom_dimensions) != 2:
1407+
if isinstance(page_size, Mapping):
1408+
custom_page_size = cast(Mapping[str, Any], page_size)
1409+
if (
1410+
"custom_height" not in custom_page_size
1411+
or "custom_width" not in custom_page_size
1412+
):
14121413
msg = (
1413-
"Custom page sizes must contain exactly two values: "
1414-
"custom_height and custom_width."
1414+
"Custom page sizes must include both custom_height and "
1415+
"custom_width."
14151416
)
14161417
raise ValueError(msg)
14171418
normalized_data["page_size"] = "custom"
1418-
normalized_data["custom_height"] = custom_dimensions[0]
1419-
normalized_data["custom_width"] = custom_dimensions[1]
1419+
normalized_data["custom_height"] = custom_page_size["custom_height"]
1420+
normalized_data["custom_width"] = custom_page_size["custom_width"]
14201421

14211422
if (
14221423
normalized_data.get("page_size") is not None

src/pdfrest/types/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
PdfAddTextObject,
1616
PdfAType,
1717
PdfCmykColor,
18+
PdfCustomPageSize,
1819
PdfInfoQuery,
1920
PdfMergeInput,
2021
PdfMergeSource,
@@ -50,6 +51,7 @@
5051
"PdfAType",
5152
"PdfAddTextObject",
5253
"PdfCmykColor",
54+
"PdfCustomPageSize",
5355
"PdfInfoQuery",
5456
"PdfMergeInput",
5557
"PdfMergeSource",

src/pdfrest/types/public.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"PdfAType",
2828
"PdfAddTextObject",
2929
"PdfCmykColor",
30+
"PdfCustomPageSize",
3031
"PdfInfoQuery",
3132
"PdfMergeInput",
3233
"PdfMergeSource",
@@ -128,6 +129,11 @@ class PdfAddTextObject(TypedDict, total=False):
128129
is_right_to_left: bool
129130

130131

132+
class PdfCustomPageSize(TypedDict):
133+
custom_height: Required[float]
134+
custom_width: Required[float]
135+
136+
131137
PdfPageSelection = str | int | Sequence[str | int]
132138

133139

@@ -199,7 +205,5 @@ class PdfMergeSource(TypedDict, total=False):
199205
ALL_PDF_RESTRICTIONS: tuple[PdfRestriction, ...] = cast(
200206
tuple[PdfRestriction, ...], get_args(PdfRestriction)
201207
)
202-
PdfPageSize = (
203-
Literal["letter", "legal", "ledger", "A3", "A4", "A5"] | tuple[float, float]
204-
)
208+
PdfPageSize = Literal["letter", "legal", "ledger", "A3", "A4", "A5"] | PdfCustomPageSize
205209
PdfPageOrientation = Literal["portrait", "landscape"]

tests/live/test_live_blank_pdf.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import pytest
44

55
from pdfrest import AsyncPdfRestClient, PdfRestApiError, PdfRestClient
6+
from pdfrest.types import PdfCustomPageSize
67

78
BLANK_PDF_LITERAL_CASES = [
89
pytest.param(
@@ -42,7 +43,7 @@
4243
id="a5-landscape",
4344
),
4445
pytest.param(
45-
(792.0, 612.0),
46+
{"custom_height": 792.0, "custom_width": 612.0},
4647
None,
4748
"blank-custom",
4849
id="custom-dimensions",
@@ -57,11 +58,11 @@
5758
def test_live_blank_pdf_success(
5859
pdfrest_api_key: str,
5960
pdfrest_live_base_url: str,
60-
page_size: str | tuple[float, float],
61+
page_size: str | PdfCustomPageSize,
6162
page_orientation: str | None,
6263
output_name: str,
6364
) -> None:
64-
kwargs: dict[str, str | int | float | tuple[float, float]] = {
65+
kwargs: dict[str, str | int | float | PdfCustomPageSize] = {
6566
"page_size": page_size,
6667
"page_count": 1,
6768
"output": output_name,
@@ -91,11 +92,11 @@ def test_live_blank_pdf_success(
9192
async def test_live_async_blank_pdf_success(
9293
pdfrest_api_key: str,
9394
pdfrest_live_base_url: str,
94-
page_size: str | tuple[float, float],
95+
page_size: str | PdfCustomPageSize,
9596
page_orientation: str | None,
9697
output_name: str,
9798
) -> None:
98-
kwargs: dict[str, str | int | float | tuple[float, float]] = {
99+
kwargs: dict[str, str | int | float | PdfCustomPageSize] = {
99100
"page_size": page_size,
100101
"page_count": 2,
101102
"output": output_name,

tests/test_blank_pdf.py

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import json
4+
from typing import cast
45

56
import httpx
67
import pytest
@@ -9,6 +10,7 @@
910
from pdfrest import AsyncPdfRestClient, PdfRestClient
1011
from pdfrest.models import PdfRestFileBasedResponse, PdfRestFileID
1112
from pdfrest.models._internal import PdfBlankPayload
13+
from pdfrest.types import PdfCustomPageSize
1214

1315
from .graphics_test_helpers import ASYNC_API_KEY, VALID_API_KEY, build_file_info_payload
1416

@@ -384,15 +386,31 @@ async def test_async_blank_pdf_page_count_boundaries_validation(
384386
@pytest.mark.parametrize(
385387
("page_size", "match"),
386388
[
387-
pytest.param((0.0, 10.0), "greater than 0", id="height-zero"),
388-
pytest.param((-1.0, 10.0), "greater than 0", id="height-negative"),
389-
pytest.param((10.0, 0.0), "greater than 0", id="width-zero"),
390-
pytest.param((10.0, -1.0), "greater than 0", id="width-negative"),
389+
pytest.param(
390+
{"custom_height": 0.0, "custom_width": 10.0},
391+
"greater than 0",
392+
id="height-zero",
393+
),
394+
pytest.param(
395+
{"custom_height": -1.0, "custom_width": 10.0},
396+
"greater than 0",
397+
id="height-negative",
398+
),
399+
pytest.param(
400+
{"custom_height": 10.0, "custom_width": 0.0},
401+
"greater than 0",
402+
id="width-zero",
403+
),
404+
pytest.param(
405+
{"custom_height": 10.0, "custom_width": -1.0},
406+
"greater than 0",
407+
id="width-negative",
408+
),
391409
],
392410
)
393411
def test_blank_pdf_custom_dimensions_validation(
394412
monkeypatch: pytest.MonkeyPatch,
395-
page_size: tuple[float, float],
413+
page_size: PdfCustomPageSize,
396414
match: str,
397415
) -> None:
398416
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
@@ -412,15 +430,31 @@ def test_blank_pdf_custom_dimensions_validation(
412430
@pytest.mark.parametrize(
413431
("page_size", "match"),
414432
[
415-
pytest.param((0.0, 10.0), "greater than 0", id="height-zero"),
416-
pytest.param((-1.0, 10.0), "greater than 0", id="height-negative"),
417-
pytest.param((10.0, 0.0), "greater than 0", id="width-zero"),
418-
pytest.param((10.0, -1.0), "greater than 0", id="width-negative"),
433+
pytest.param(
434+
{"custom_height": 0.0, "custom_width": 10.0},
435+
"greater than 0",
436+
id="height-zero",
437+
),
438+
pytest.param(
439+
{"custom_height": -1.0, "custom_width": 10.0},
440+
"greater than 0",
441+
id="height-negative",
442+
),
443+
pytest.param(
444+
{"custom_height": 10.0, "custom_width": 0.0},
445+
"greater than 0",
446+
id="width-zero",
447+
),
448+
pytest.param(
449+
{"custom_height": 10.0, "custom_width": -1.0},
450+
"greater than 0",
451+
id="width-negative",
452+
),
419453
],
420454
)
421455
async def test_async_blank_pdf_custom_dimensions_validation(
422456
monkeypatch: pytest.MonkeyPatch,
423-
page_size: tuple[float, float],
457+
page_size: PdfCustomPageSize,
424458
match: str,
425459
) -> None:
426460
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
@@ -537,7 +571,7 @@ def handler(request: httpx.Request) -> httpx.Response:
537571
transport = httpx.MockTransport(handler)
538572
with PdfRestClient(api_key=VALID_API_KEY, transport=transport) as client:
539573
response = client.blank_pdf(
540-
page_size=(792, 612),
574+
page_size={"custom_height": 792, "custom_width": 612},
541575
page_count=3,
542576
output="custom",
543577
extra_query={"trace": "true"},
@@ -658,7 +692,7 @@ def handler(request: httpx.Request) -> httpx.Response:
658692
transport = httpx.MockTransport(handler)
659693
async with AsyncPdfRestClient(api_key=ASYNC_API_KEY, transport=transport) as client:
660694
response = await client.blank_pdf(
661-
page_size=(100, 50),
695+
page_size={"custom_height": 100, "custom_width": 50},
662696
page_count=1,
663697
extra_query={"trace": "async"},
664698
extra_headers={"X-Debug": "async"},
@@ -684,16 +718,24 @@ def test_blank_pdf_validation(monkeypatch: pytest.MonkeyPatch) -> None:
684718

685719
with (
686720
PdfRestClient(api_key=VALID_API_KEY, transport=transport) as client,
687-
pytest.raises(ValueError, match="Custom page sizes must contain exactly two"),
721+
pytest.raises(
722+
ValueError, match="must include both custom_height and custom_width"
723+
),
688724
):
689-
client.blank_pdf(page_size=(50,), page_count=1)
725+
client.blank_pdf(
726+
page_size=cast(
727+
PdfCustomPageSize,
728+
cast(object, {"custom_height": 50}),
729+
),
730+
page_count=1,
731+
)
690732

691733
with (
692734
PdfRestClient(api_key=VALID_API_KEY, transport=transport) as client,
693735
pytest.raises(ValueError, match="page_orientation must be omitted"),
694736
):
695737
client.blank_pdf(
696-
page_size=(10, 10),
738+
page_size={"custom_height": 10, "custom_width": 10},
697739
page_count=1,
698740
page_orientation="portrait",
699741
)

0 commit comments

Comments
 (0)