|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
3 | 3 | import re |
4 | | -from collections.abc import Callable, Sequence |
| 4 | +from collections.abc import Callable, Mapping, Sequence |
5 | 5 | from pathlib import PurePath |
6 | | -from typing import Annotated, Any, Generic, Literal, TypeVar |
| 6 | +from typing import Annotated, Any, Generic, Literal, TypeVar, cast |
7 | 7 |
|
8 | 8 | from langcodes import tag_is_valid |
9 | 9 | from pydantic import ( |
|
26 | 26 | OcrLanguage, |
27 | 27 | PdfAType, |
28 | 28 | PdfInfoQuery, |
| 29 | + PdfPageOrientation, |
| 30 | + PdfPageSize, |
29 | 31 | PdfRestriction, |
30 | 32 | PdfXType, |
31 | 33 | SummaryFormat, |
@@ -1365,6 +1367,89 @@ class PdfAddAttachmentPayload(BaseModel): |
1365 | 1367 | ] = None |
1366 | 1368 |
|
1367 | 1369 |
|
| 1370 | +class PdfBlankPayload(BaseModel): |
| 1371 | + """Adapt caller options into a pdfRest-ready blank PDF request payload.""" |
| 1372 | + |
| 1373 | + page_size: Annotated[ |
| 1374 | + PdfPageSize | Literal["custom"], |
| 1375 | + Field(serialization_alias="page_size"), |
| 1376 | + ] |
| 1377 | + page_count: Annotated[ |
| 1378 | + int, |
| 1379 | + Field(serialization_alias="page_count", ge=1, le=1000), |
| 1380 | + ] |
| 1381 | + page_orientation: Annotated[ |
| 1382 | + PdfPageOrientation | None, |
| 1383 | + Field(serialization_alias="page_orientation", default=None), |
| 1384 | + ] = None |
| 1385 | + custom_height: Annotated[ |
| 1386 | + float | None, |
| 1387 | + Field(serialization_alias="custom_height", gt=0, default=None), |
| 1388 | + ] = None |
| 1389 | + custom_width: Annotated[ |
| 1390 | + float | None, |
| 1391 | + Field(serialization_alias="custom_width", gt=0, default=None), |
| 1392 | + ] = None |
| 1393 | + output: Annotated[ |
| 1394 | + str | None, |
| 1395 | + Field(serialization_alias="output", min_length=1, default=None), |
| 1396 | + AfterValidator(_validate_output_prefix), |
| 1397 | + ] = None |
| 1398 | + |
| 1399 | + @model_validator(mode="before") |
| 1400 | + @classmethod |
| 1401 | + def _normalize_custom_page_size(cls, data: Any) -> Any: |
| 1402 | + if not isinstance(data, Mapping): |
| 1403 | + return data |
| 1404 | + |
| 1405 | + normalized_data: dict[str, Any] = dict(cast(Mapping[str, Any], data)) |
| 1406 | + page_size = normalized_data.get("page_size") |
| 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 | + ): |
| 1413 | + msg = ( |
| 1414 | + "Custom page sizes must include both custom_height and " |
| 1415 | + "custom_width." |
| 1416 | + ) |
| 1417 | + raise ValueError(msg) |
| 1418 | + normalized_data["page_size"] = "custom" |
| 1419 | + normalized_data["custom_height"] = custom_page_size["custom_height"] |
| 1420 | + normalized_data["custom_width"] = custom_page_size["custom_width"] |
| 1421 | + |
| 1422 | + if ( |
| 1423 | + normalized_data.get("page_size") is not None |
| 1424 | + and normalized_data.get("page_size") != "custom" |
| 1425 | + and normalized_data.get("page_orientation") is None |
| 1426 | + ): |
| 1427 | + normalized_data["page_orientation"] = "portrait" |
| 1428 | + |
| 1429 | + return normalized_data |
| 1430 | + |
| 1431 | + @model_validator(mode="after") |
| 1432 | + def _validate_page_configuration(self) -> PdfBlankPayload: |
| 1433 | + is_custom = self.page_size == "custom" |
| 1434 | + has_custom_height = self.custom_height is not None |
| 1435 | + has_custom_width = self.custom_width is not None |
| 1436 | + if is_custom: |
| 1437 | + if not (has_custom_height and has_custom_width): |
| 1438 | + msg = "custom_height and custom_width are required when page_size is 'custom'." |
| 1439 | + raise ValueError(msg) |
| 1440 | + if self.page_orientation is not None: |
| 1441 | + msg = "page_orientation must be omitted when page_size is 'custom'." |
| 1442 | + raise ValueError(msg) |
| 1443 | + else: |
| 1444 | + if self.page_orientation is None: |
| 1445 | + msg = "page_orientation is required when page_size is not 'custom'." |
| 1446 | + raise ValueError(msg) |
| 1447 | + if has_custom_height or has_custom_width: |
| 1448 | + msg = "custom_height and custom_width can only be provided when page_size is 'custom'." |
| 1449 | + raise ValueError(msg) |
| 1450 | + return self |
| 1451 | + |
| 1452 | + |
1368 | 1453 | class PdfRestrictPayload(BaseModel): |
1369 | 1454 | """Adapt caller options into a pdfRest-ready restrict-PDF request payload.""" |
1370 | 1455 |
|
@@ -1603,7 +1688,11 @@ class PdfRestRawFileResponse(BaseModel): |
1603 | 1688 |
|
1604 | 1689 | input_id: Annotated[ |
1605 | 1690 | list[PdfRestFileID], |
1606 | | - Field(alias="inputId", description="The id of the input file"), |
| 1691 | + Field( |
| 1692 | + alias="inputId", |
| 1693 | + description="The id of the input file", |
| 1694 | + default_factory=list, |
| 1695 | + ), |
1607 | 1696 | BeforeValidator(_ensure_list), |
1608 | 1697 | ] |
1609 | 1698 | output_urls: Annotated[ |
|
0 commit comments