Skip to content

Commit d6806ef

Browse files
Add PDF restriction methods
Assisted-by: Codex
1 parent f6bb554 commit d6806ef

4 files changed

Lines changed: 335 additions & 0 deletions

File tree

src/pdfrest/client.py

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,12 +92,14 @@
9292
PdfRedactionApplyPayload,
9393
PdfRedactionPreviewPayload,
9494
PdfRestRawFileResponse,
95+
PdfRestrictPayload,
9596
PdfSplitPayload,
9697
PdfToExcelPayload,
9798
PdfToPdfaPayload,
9899
PdfToPdfxPayload,
99100
PdfToPowerpointPayload,
100101
PdfToWordPayload,
102+
PdfUnrestrictPayload,
101103
PdfXfaToAcroformsPayload,
102104
PngPdfRestPayload,
103105
SummarizePdfTextPayload,
@@ -120,6 +122,7 @@
120122
PdfMergeInput,
121123
PdfPageSelection,
122124
PdfRedactionInstruction,
125+
PdfRestriction,
123126
PdfRGBColor,
124127
PdfXType,
125128
PngColorModel,
@@ -2684,6 +2687,113 @@ def flatten_pdf_forms(
26842687
timeout=timeout,
26852688
)
26862689

2690+
def add_permissions_password(
2691+
self,
2692+
file: PdfRestFile | Sequence[PdfRestFile],
2693+
*,
2694+
new_permissions_password: str,
2695+
restrictions: Sequence[PdfRestriction] | None = None,
2696+
current_open_password: str | None = None,
2697+
output: str | None = None,
2698+
extra_query: Query | None = None,
2699+
extra_headers: AnyMapping | None = None,
2700+
extra_body: Body | None = None,
2701+
timeout: TimeoutTypes | None = None,
2702+
) -> PdfRestFileBasedResponse:
2703+
"""Add a permissions password and optional restrictions to a PDF."""
2704+
2705+
payload: dict[str, Any] = {
2706+
"files": file,
2707+
"new_permissions_password": new_permissions_password,
2708+
}
2709+
if restrictions is not None:
2710+
payload["restrictions"] = restrictions
2711+
if current_open_password is not None:
2712+
payload["current_open_password"] = current_open_password
2713+
if output is not None:
2714+
payload["output"] = output
2715+
2716+
return self._post_file_operation(
2717+
endpoint="/restricted-pdf",
2718+
payload=payload,
2719+
payload_model=PdfRestrictPayload,
2720+
extra_query=extra_query,
2721+
extra_headers=extra_headers,
2722+
extra_body=extra_body,
2723+
timeout=timeout,
2724+
)
2725+
2726+
def change_permissions_password(
2727+
self,
2728+
file: PdfRestFile | Sequence[PdfRestFile],
2729+
*,
2730+
current_permissions_password: str,
2731+
new_permissions_password: str,
2732+
restrictions: Sequence[PdfRestriction] | None = None,
2733+
current_open_password: str | None = None,
2734+
output: str | None = None,
2735+
extra_query: Query | None = None,
2736+
extra_headers: AnyMapping | None = None,
2737+
extra_body: Body | None = None,
2738+
timeout: TimeoutTypes | None = None,
2739+
) -> PdfRestFileBasedResponse:
2740+
"""Rotate the permissions password and optionally update restrictions."""
2741+
2742+
payload: dict[str, Any] = {
2743+
"files": file,
2744+
"current_permissions_password": current_permissions_password,
2745+
"new_permissions_password": new_permissions_password,
2746+
}
2747+
if restrictions is not None:
2748+
payload["restrictions"] = restrictions
2749+
if current_open_password is not None:
2750+
payload["current_open_password"] = current_open_password
2751+
if output is not None:
2752+
payload["output"] = output
2753+
2754+
return self._post_file_operation(
2755+
endpoint="/restricted-pdf",
2756+
payload=payload,
2757+
payload_model=PdfRestrictPayload,
2758+
extra_query=extra_query,
2759+
extra_headers=extra_headers,
2760+
extra_body=extra_body,
2761+
timeout=timeout,
2762+
)
2763+
2764+
def remove_permissions_password(
2765+
self,
2766+
file: PdfRestFile | Sequence[PdfRestFile],
2767+
*,
2768+
current_permissions_password: str,
2769+
current_open_password: str | None = None,
2770+
output: str | None = None,
2771+
extra_query: Query | None = None,
2772+
extra_headers: AnyMapping | None = None,
2773+
extra_body: Body | None = None,
2774+
timeout: TimeoutTypes | None = None,
2775+
) -> PdfRestFileBasedResponse:
2776+
"""Remove permissions restrictions from a PDF."""
2777+
2778+
payload: dict[str, Any] = {
2779+
"files": file,
2780+
"current_permissions_password": current_permissions_password,
2781+
}
2782+
if current_open_password is not None:
2783+
payload["current_open_password"] = current_open_password
2784+
if output is not None:
2785+
payload["output"] = output
2786+
2787+
return self._post_file_operation(
2788+
endpoint="/unrestricted-pdf",
2789+
payload=payload,
2790+
payload_model=PdfUnrestrictPayload,
2791+
extra_query=extra_query,
2792+
extra_headers=extra_headers,
2793+
extra_body=extra_body,
2794+
timeout=timeout,
2795+
)
2796+
26872797
def compress_pdf(
26882798
self,
26892799
file: PdfRestFile | Sequence[PdfRestFile],
@@ -3721,6 +3831,113 @@ async def flatten_pdf_forms(
37213831
timeout=timeout,
37223832
)
37233833

3834+
async def add_permissions_password(
3835+
self,
3836+
file: PdfRestFile | Sequence[PdfRestFile],
3837+
*,
3838+
new_permissions_password: str,
3839+
restrictions: Sequence[PdfRestriction] | None = None,
3840+
current_open_password: str | None = None,
3841+
output: str | None = None,
3842+
extra_query: Query | None = None,
3843+
extra_headers: AnyMapping | None = None,
3844+
extra_body: Body | None = None,
3845+
timeout: TimeoutTypes | None = None,
3846+
) -> PdfRestFileBasedResponse:
3847+
"""Asynchronously add a permissions password and optional restrictions to a PDF."""
3848+
3849+
payload: dict[str, Any] = {
3850+
"files": file,
3851+
"new_permissions_password": new_permissions_password,
3852+
}
3853+
if restrictions is not None:
3854+
payload["restrictions"] = restrictions
3855+
if current_open_password is not None:
3856+
payload["current_open_password"] = current_open_password
3857+
if output is not None:
3858+
payload["output"] = output
3859+
3860+
return await self._post_file_operation(
3861+
endpoint="/restricted-pdf",
3862+
payload=payload,
3863+
payload_model=PdfRestrictPayload,
3864+
extra_query=extra_query,
3865+
extra_headers=extra_headers,
3866+
extra_body=extra_body,
3867+
timeout=timeout,
3868+
)
3869+
3870+
async def change_permissions_password(
3871+
self,
3872+
file: PdfRestFile | Sequence[PdfRestFile],
3873+
*,
3874+
current_permissions_password: str,
3875+
new_permissions_password: str,
3876+
restrictions: Sequence[PdfRestriction] | None = None,
3877+
current_open_password: str | None = None,
3878+
output: str | None = None,
3879+
extra_query: Query | None = None,
3880+
extra_headers: AnyMapping | None = None,
3881+
extra_body: Body | None = None,
3882+
timeout: TimeoutTypes | None = None,
3883+
) -> PdfRestFileBasedResponse:
3884+
"""Asynchronously rotate the permissions password and optionally update restrictions."""
3885+
3886+
payload: dict[str, Any] = {
3887+
"files": file,
3888+
"current_permissions_password": current_permissions_password,
3889+
"new_permissions_password": new_permissions_password,
3890+
}
3891+
if restrictions is not None:
3892+
payload["restrictions"] = restrictions
3893+
if current_open_password is not None:
3894+
payload["current_open_password"] = current_open_password
3895+
if output is not None:
3896+
payload["output"] = output
3897+
3898+
return await self._post_file_operation(
3899+
endpoint="/restricted-pdf",
3900+
payload=payload,
3901+
payload_model=PdfRestrictPayload,
3902+
extra_query=extra_query,
3903+
extra_headers=extra_headers,
3904+
extra_body=extra_body,
3905+
timeout=timeout,
3906+
)
3907+
3908+
async def remove_permissions_password(
3909+
self,
3910+
file: PdfRestFile | Sequence[PdfRestFile],
3911+
*,
3912+
current_permissions_password: str,
3913+
current_open_password: str | None = None,
3914+
output: str | None = None,
3915+
extra_query: Query | None = None,
3916+
extra_headers: AnyMapping | None = None,
3917+
extra_body: Body | None = None,
3918+
timeout: TimeoutTypes | None = None,
3919+
) -> PdfRestFileBasedResponse:
3920+
"""Asynchronously remove permissions restrictions from a PDF."""
3921+
3922+
payload: dict[str, Any] = {
3923+
"files": file,
3924+
"current_permissions_password": current_permissions_password,
3925+
}
3926+
if current_open_password is not None:
3927+
payload["current_open_password"] = current_open_password
3928+
if output is not None:
3929+
payload["output"] = output
3930+
3931+
return await self._post_file_operation(
3932+
endpoint="/unrestricted-pdf",
3933+
payload=payload,
3934+
payload_model=PdfUnrestrictPayload,
3935+
extra_query=extra_query,
3936+
extra_headers=extra_headers,
3937+
extra_body=extra_body,
3938+
timeout=timeout,
3939+
)
3940+
37243941
async def compress_pdf(
37253942
self,
37263943
file: PdfRestFile | Sequence[PdfRestFile],

src/pdfrest/models/_internal.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
OcrLanguage,
2727
PdfAType,
2828
PdfInfoQuery,
29+
PdfRestriction,
2930
PdfXType,
3031
SummaryFormat,
3132
SummaryOutputFormat,
@@ -1142,6 +1143,102 @@ class PdfFlattenAnnotationsPayload(BaseModel):
11421143
] = None
11431144

11441145

1146+
class PdfRestrictPayload(BaseModel):
1147+
"""Adapt caller options into a pdfRest-ready restrict-PDF request payload."""
1148+
1149+
files: Annotated[
1150+
list[PdfRestFile],
1151+
Field(
1152+
min_length=1,
1153+
max_length=1,
1154+
validation_alias=AliasChoices("file", "files"),
1155+
serialization_alias="id",
1156+
),
1157+
BeforeValidator(_ensure_list),
1158+
AfterValidator(
1159+
_allowed_mime_types("application/pdf", error_msg="Must be a PDF file")
1160+
),
1161+
PlainSerializer(_serialize_as_first_file_id),
1162+
]
1163+
new_permissions_password: Annotated[
1164+
str,
1165+
Field(
1166+
serialization_alias="new_permissions_password",
1167+
min_length=6,
1168+
max_length=128,
1169+
),
1170+
]
1171+
restrictions: Annotated[
1172+
list[PdfRestriction] | None,
1173+
Field(serialization_alias="restrictions", min_length=1, default=None),
1174+
BeforeValidator(_ensure_list),
1175+
] = None
1176+
current_permissions_password: Annotated[
1177+
str | None,
1178+
Field(
1179+
serialization_alias="current_permissions_password",
1180+
min_length=1,
1181+
max_length=128,
1182+
default=None,
1183+
),
1184+
] = None
1185+
current_open_password: Annotated[
1186+
str | None,
1187+
Field(
1188+
serialization_alias="current_open_password",
1189+
min_length=1,
1190+
max_length=128,
1191+
default=None,
1192+
),
1193+
] = None
1194+
output: Annotated[
1195+
str | None,
1196+
Field(serialization_alias="output", min_length=1, default=None),
1197+
AfterValidator(_validate_output_prefix),
1198+
] = None
1199+
1200+
1201+
class PdfUnrestrictPayload(BaseModel):
1202+
"""Adapt caller options into a pdfRest-ready unrestrict-PDF request payload."""
1203+
1204+
files: Annotated[
1205+
list[PdfRestFile],
1206+
Field(
1207+
min_length=1,
1208+
max_length=1,
1209+
validation_alias=AliasChoices("file", "files"),
1210+
serialization_alias="id",
1211+
),
1212+
BeforeValidator(_ensure_list),
1213+
AfterValidator(
1214+
_allowed_mime_types("application/pdf", error_msg="Must be a PDF file")
1215+
),
1216+
PlainSerializer(_serialize_as_first_file_id),
1217+
]
1218+
current_permissions_password: Annotated[
1219+
str,
1220+
Field(
1221+
serialization_alias="current_permissions_password",
1222+
min_length=1,
1223+
max_length=128,
1224+
),
1225+
]
1226+
current_open_password: Annotated[
1227+
str | None,
1228+
Field(
1229+
serialization_alias="current_open_password",
1230+
min_length=1,
1231+
max_length=128,
1232+
default=None,
1233+
),
1234+
] = None
1235+
output: Annotated[
1236+
str | None,
1237+
Field(serialization_alias="output", min_length=1, default=None),
1238+
AfterValidator(_validate_output_prefix),
1239+
] = None
1240+
1241+
11451242
class BmpPdfRestPayload(BasePdfRestGraphicPayload[Literal["rgb", "gray"]]):
11461243
"""Adapt caller options into a pdfRest-ready BMP request payload."""
11471244

src/pdfrest/types/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .public import (
44
ALL_OCR_LANGUAGES,
55
ALL_PDF_INFO_QUERIES,
6+
ALL_PDF_RESTRICTIONS,
67
BmpColorModel,
78
CompressionLevel,
89
ExtractTextGranularity,
@@ -19,6 +20,7 @@
1920
PdfRedactionInstruction,
2021
PdfRedactionPreset,
2122
PdfRedactionType,
23+
PdfRestriction,
2224
PdfRGBColor,
2325
PdfXType,
2426
PngColorModel,
@@ -32,6 +34,7 @@
3234
__all__ = [
3335
"ALL_OCR_LANGUAGES",
3436
"ALL_PDF_INFO_QUERIES",
37+
"ALL_PDF_RESTRICTIONS",
3538
"BmpColorModel",
3639
"CompressionLevel",
3740
"ExtractTextGranularity",
@@ -49,6 +52,7 @@
4952
"PdfRedactionInstruction",
5053
"PdfRedactionPreset",
5154
"PdfRedactionType",
55+
"PdfRestriction",
5256
"PdfXType",
5357
"PngColorModel",
5458
"SummaryFormat",

0 commit comments

Comments
 (0)