Skip to content

Commit 2ab5abc

Browse files
OCR PDF: Add missing languages body parameter
Assisted-by: Codex
1 parent cbc0ff8 commit 2ab5abc

6 files changed

Lines changed: 75 additions & 10 deletions

File tree

src/pdfrest/client.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@
114114
GifColorModel,
115115
GraphicSmoothing,
116116
JpegColorModel,
117+
OcrLanguage,
117118
PdfAType,
118119
PdfInfoQuery,
119120
PdfMergeInput,
@@ -2264,6 +2265,7 @@ def ocr_pdf(
22642265
self,
22652266
file: PdfRestFile | Sequence[PdfRestFile],
22662267
*,
2268+
languages: OcrLanguage | Sequence[OcrLanguage] = "English",
22672269
pages: PdfPageSelection | None = None,
22682270
output: str | None = None,
22692271
extra_query: Query | None = None,
@@ -2273,7 +2275,7 @@ def ocr_pdf(
22732275
) -> PdfRestFileBasedResponse:
22742276
"""Perform OCR on a PDF to make text searchable and extractable."""
22752277

2276-
payload: dict[str, Any] = {"files": file}
2278+
payload: dict[str, Any] = {"files": file, "languages": languages}
22772279
if pages is not None:
22782280
payload["pages"] = pages
22792281
if output is not None:
@@ -3263,6 +3265,7 @@ async def ocr_pdf(
32633265
self,
32643266
file: PdfRestFile | Sequence[PdfRestFile],
32653267
*,
3268+
languages: OcrLanguage | Sequence[OcrLanguage] = "English",
32663269
pages: PdfPageSelection | None = None,
32673270
output: str | None = None,
32683271
extra_query: Query | None = None,
@@ -3272,7 +3275,7 @@ async def ocr_pdf(
32723275
) -> PdfRestFileBasedResponse:
32733276
"""Perform OCR on a PDF to make text searchable and extractable."""
32743277

3275-
payload: dict[str, Any] = {"files": file}
3278+
payload: dict[str, Any] = {"files": file, "languages": languages}
32763279
if pages is not None:
32773280
payload["pages"] = pages
32783281
if output is not None:

src/pdfrest/models/_internal.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from pdfrest.types.public import PdfRedactionPreset
2323

2424
from ..types import (
25+
OcrLanguage,
2526
PdfAType,
2627
PdfInfoQuery,
2728
PdfXType,
@@ -329,6 +330,18 @@ class OcrPdfPayload(BaseModel):
329330
),
330331
PlainSerializer(_serialize_as_first_file_id),
331332
]
333+
languages: Annotated[
334+
list[OcrLanguage],
335+
Field(
336+
serialization_alias="languages",
337+
validation_alias=AliasChoices("languages", "language"),
338+
min_length=1,
339+
default_factory=lambda: ["English"],
340+
),
341+
BeforeValidator(_ensure_list),
342+
BeforeValidator(_split_comma_list),
343+
PlainSerializer(_serialize_as_comma_separated_string),
344+
]
332345
pages: Annotated[
333346
list[AscendingPageRange] | None,
334347
Field(serialization_alias="pages", min_length=1, default=None),

src/pdfrest/types/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Public import surface for shared pdfrest types."""
22

33
from .public import (
4+
ALL_OCR_LANGUAGES,
45
ALL_PDF_INFO_QUERIES,
56
BmpColorModel,
67
CompressionLevel,
@@ -9,6 +10,7 @@
910
GifColorModel,
1011
GraphicSmoothing,
1112
JpegColorModel,
13+
OcrLanguage,
1214
PdfAType,
1315
PdfInfoQuery,
1416
PdfMergeInput,
@@ -28,6 +30,7 @@
2830
)
2931

3032
__all__ = [
33+
"ALL_OCR_LANGUAGES",
3134
"ALL_PDF_INFO_QUERIES",
3235
"BmpColorModel",
3336
"CompressionLevel",
@@ -36,6 +39,7 @@
3639
"GifColorModel",
3740
"GraphicSmoothing",
3841
"JpegColorModel",
42+
"OcrLanguage",
3943
"PdfAType",
4044
"PdfInfoQuery",
4145
"PdfMergeInput",

src/pdfrest/types/public.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
PdfRestFile = Any
1414

1515
__all__ = (
16+
"ALL_OCR_LANGUAGES",
1617
"ALL_PDF_INFO_QUERIES",
1718
"BmpColorModel",
1819
"CompressionLevel",
@@ -21,6 +22,7 @@
2122
"GifColorModel",
2223
"GraphicSmoothing",
2324
"JpegColorModel",
25+
"OcrLanguage",
2426
"PdfAType",
2527
"PdfInfoQuery",
2628
"PdfMergeInput",
@@ -140,3 +142,21 @@ class PdfMergeSource(TypedDict, total=False):
140142
SummaryOutputType = Literal["json", "file"]
141143

142144
TranslateOutputFormat = Literal["plaintext", "markdown"]
145+
146+
OcrLanguage = Literal[
147+
"ChineseSimplified",
148+
"ChineseTraditional",
149+
"Dutch",
150+
"English",
151+
"French",
152+
"German",
153+
"Italian",
154+
"Japanese",
155+
"Korean",
156+
"Portuguese",
157+
"Spanish",
158+
]
159+
160+
ALL_OCR_LANGUAGES: tuple[OcrLanguage, ...] = cast(
161+
tuple[OcrLanguage, ...], get_args(OcrLanguage)
162+
)

tests/live/test_live_ocr_pdf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def test_live_ocr_pdf_success(
1818
base_url=pdfrest_live_base_url,
1919
) as client:
2020
uploaded = client.files.create_from_paths([resource])[0]
21-
response = client.ocr_pdf(uploaded)
21+
response = client.ocr_pdf(uploaded, languages=["English", "German"])
2222

2323
assert isinstance(response, PdfRestFileBasedResponse)
2424
assert response.output_files

tests/test_ocr_pdf.py

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,36 @@ def test_ocr_payload_invalid_page_range() -> None:
3838
OcrPdfPayload.model_validate({"files": [file_repr], "pages": ["5-2"]})
3939

4040

41+
def test_ocr_payload_languages() -> None:
42+
file_repr = make_pdf_file(PdfRestFileID.generate(1))
43+
payload = OcrPdfPayload.model_validate(
44+
{"files": [file_repr], "languages": ["English", "German"]}
45+
)
46+
assert payload.languages == ["English", "German"]
47+
assert (
48+
payload.model_dump(
49+
mode="json", by_alias=True, exclude_none=True, exclude_unset=True
50+
)["languages"]
51+
== "English,German"
52+
)
53+
54+
55+
def test_ocr_payload_invalid_language() -> None:
56+
file_repr = make_pdf_file(PdfRestFileID.generate(1))
57+
with pytest.raises(ValidationError, match="ChineseSimplified"):
58+
OcrPdfPayload.model_validate({"files": [file_repr], "languages": ["Klingon"]})
59+
60+
4161
def test_ocr_pdf_success(monkeypatch: pytest.MonkeyPatch) -> None:
4262
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
4363
input_file = make_pdf_file(PdfRestFileID.generate(1))
4464
payload_dump = OcrPdfPayload.model_validate(
45-
{"files": [input_file], "pages": ["1-3"], "output": "ocr"}
65+
{
66+
"files": [input_file],
67+
"pages": ["1-3"],
68+
"output": "ocr",
69+
"languages": ["English"],
70+
}
4671
).model_dump(mode="json", by_alias=True, exclude_none=True, exclude_unset=True)
4772
output_id = str(PdfRestFileID.generate())
4873

@@ -91,9 +116,9 @@ def test_ocr_pdf_request_customization(
91116
) -> None:
92117
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
93118
input_file = make_pdf_file(PdfRestFileID.generate(1))
94-
payload_dump = OcrPdfPayload.model_validate({"files": [input_file]}).model_dump(
95-
mode="json", by_alias=True, exclude_none=True, exclude_unset=True
96-
)
119+
payload_dump = OcrPdfPayload.model_validate(
120+
{"files": [input_file], "languages": ["English"]}
121+
).model_dump(mode="json", by_alias=True, exclude_none=True, exclude_unset=True)
97122
output_id = str(PdfRestFileID.generate())
98123
captured_timeout: dict[str, float | dict[str, float] | None] = {}
99124

@@ -152,9 +177,9 @@ async def test_async_ocr_pdf_success(
152177
) -> None:
153178
monkeypatch.delenv("PDFREST_API_KEY", raising=False)
154179
input_file = make_pdf_file(PdfRestFileID.generate(2))
155-
payload_dump = OcrPdfPayload.model_validate({"files": [input_file]}).model_dump(
156-
mode="json", by_alias=True, exclude_none=True, exclude_unset=True
157-
)
180+
payload_dump = OcrPdfPayload.model_validate(
181+
{"files": [input_file], "languages": ["English"]}
182+
).model_dump(mode="json", by_alias=True, exclude_none=True, exclude_unset=True)
158183
output_id = str(PdfRestFileID.generate())
159184

160185
seen: dict[str, int] = {"post": 0, "get": 0}

0 commit comments

Comments
 (0)