Skip to content

Commit 36bfb16

Browse files
client, models: Simplify credential payload handling for PDF signing
- Refactored the credentials logic in `client.py` to remove redundant validation and mapping code. - Added a `_normalize_credentials` model validator in `_internal.py` to handle credential normalization and enforce valid inputs. - Updated test cases in `test_sign_pdf.py` to align with the new credentials structure, consolidating `pfx` and `certificate` data under a unified `credentials` field. Assisted-by: Codex
1 parent 503c84c commit 36bfb16

3 files changed

Lines changed: 34 additions & 8 deletions

File tree

src/pdfrest/client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3091,8 +3091,8 @@ def sign_pdf(
30913091
payload: dict[str, Any] = {
30923092
"files": file,
30933093
"signature_configuration": signature_configuration,
3094+
"credentials": credentials,
30943095
}
3095-
payload.update(credentials)
30963096

30973097
if logo is not None:
30983098
payload["logo"] = logo
@@ -4507,8 +4507,8 @@ async def sign_pdf(
45074507
payload: dict[str, Any] = {
45084508
"files": file,
45094509
"signature_configuration": signature_configuration,
4510+
"credentials": credentials,
45104511
}
4511-
payload.update(credentials)
45124512

45134513
if logo is not None:
45144514
payload["logo"] = logo

src/pdfrest/models/_internal.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
from __future__ import annotations
22

33
import re
4-
from collections.abc import Callable, Sequence
4+
from collections.abc import Callable, Mapping, Sequence
55
from pathlib import PurePath
6-
from typing import Annotated, Any, Generic, Literal, TypeVar
6+
from typing import Annotated, Any, Generic, Literal, TypeVar, cast
77

88
from langcodes import tag_is_valid
99
from pydantic import (
@@ -1157,6 +1157,31 @@ class PdfSignPayload(BaseModel):
11571157
AfterValidator(_validate_output_prefix),
11581158
] = None
11591159

1160+
@model_validator(mode="before")
1161+
@classmethod
1162+
def _normalize_credentials(cls, data: Any) -> Any:
1163+
if not isinstance(data, Mapping):
1164+
return data
1165+
1166+
payload = cast(Mapping[object, Any], data)
1167+
credentials = payload.get("credentials")
1168+
if credentials is None:
1169+
return {str(key): value for key, value in payload.items()}
1170+
if not isinstance(credentials, Mapping):
1171+
msg = (
1172+
"credentials must be a mapping with either pfx/passphrase or "
1173+
"certificate/private_key."
1174+
)
1175+
raise TypeError(msg)
1176+
1177+
normalized: dict[str, Any] = {str(key): value for key, value in payload.items()}
1178+
credential_map = cast(Mapping[object, Any], credentials)
1179+
for raw_key, value in credential_map.items():
1180+
key = str(raw_key)
1181+
if key not in normalized:
1182+
normalized[key] = value
1183+
return normalized
1184+
11601185
@model_validator(mode="after")
11611186
def _validate_credentials(self) -> PdfSignPayload:
11621187
has_pfx = self.pfx_credential is not None or self.pfx_passphrase is not None

tests/test_sign_pdf.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ def test_sign_pdf_with_pfx_credentials(monkeypatch: pytest.MonkeyPatch) -> None:
7373
{
7474
"files": [input_file],
7575
"signature_configuration": signature_configuration,
76-
"pfx_credential": [pfx_file],
77-
"pfx_passphrase": [passphrase_file],
76+
"credentials": {"pfx": pfx_file, "passphrase": passphrase_file},
7877
"output": "signed-pdf",
7978
}
8079
).model_dump(mode="json", by_alias=True, exclude_none=True, exclude_unset=True)
@@ -140,8 +139,10 @@ def test_sign_pdf_with_certificate_credentials_and_logo(
140139
{
141140
"files": [input_file],
142141
"signature_configuration": signature_configuration,
143-
"certificate": [certificate_file],
144-
"private_key": [private_key_file],
142+
"credentials": {
143+
"certificate": certificate_file,
144+
"private_key": private_key_file,
145+
},
145146
"logo": [logo_file],
146147
}
147148
).model_dump(mode="json", by_alias=True, exclude_none=True, exclude_unset=True)

0 commit comments

Comments
 (0)