| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| import pytest |
|
|
| from paddleocr._api_client._core import ( |
| default_payload, |
| job_id_for_task, |
| resolve_document_model, |
| resolve_document_options, |
| resolve_ocr_model, |
| validate_input_source, |
| ) |
| from paddleocr._api_client.errors import InvalidRequestError |
| from paddleocr._api_client.models import ( |
| Model, |
| OCROptions, |
| PaddleOCRVLOptions, |
| PPStructureV3Options, |
| ) |
| from paddleocr._utils.naming import snake_to_camel |
| from paddleocr._api_client._poller import parse_doc_parsing_result, parse_ocr_result |
| from paddleocr._api_client.results import Job |
|
|
|
|
| def test_ppstructurev3_options_to_payload_uses_official_camel_case_keys(): |
| assert snake_to_camel("top_p") == "topP" |
| assert snake_to_camel("use_e2e_wired_table_rec_model") == "useE2eWiredTableRecModel" |
|
|
| options = PPStructureV3Options( |
| use_e2e_wired_table_rec_model=True, |
| format_block_content=True, |
| markdown_ignore_labels=["image"], |
| text_det_limit_side_len=1280, |
| extra_options={"futureOption": "enabled"}, |
| ) |
| assert options.to_payload() == { |
| "useE2eWiredTableRecModel": True, |
| "formatBlockContent": True, |
| "markdownIgnoreLabels": ["image"], |
| "textDetLimitSideLen": 1280, |
| "futureOption": "enabled", |
| } |
|
|
|
|
| def test_paddleocr_vl_options_include_service_parameters_and_extra_options(): |
| options = PaddleOCRVLOptions( |
| use_ocr_for_image_block=True, |
| format_block_content=True, |
| markdown_ignore_labels=["image"], |
| vlm_extra_args={"temperature": 0.1}, |
| return_markdown_images=False, |
| output_formats=["docx"], |
| extra_options={"futureOption": "enabled"}, |
| ) |
|
|
| assert options.to_payload() == { |
| "useOcrForImageBlock": True, |
| "formatBlockContent": True, |
| "markdownIgnoreLabels": ["image"], |
| "vlmExtraArgs": {"temperature": 0.1}, |
| "returnMarkdownImages": False, |
| "outputFormats": ["docx"], |
| "futureOption": "enabled", |
| } |
|
|
|
|
| def test_result_parsers_preserve_raw_fields_and_data_info(): |
| ocr_line = { |
| "result": { |
| "dataInfo": {"numPages": 1}, |
| "ocrResults": [ |
| { |
| "prunedResult": {"rec_texts": ["hello"]}, |
| "ocrImage": "ocr.png", |
| "docPreprocessingImage": "pre.png", |
| "inputImage": "input.png", |
| } |
| ], |
| } |
| } |
| ocr_result = parse_ocr_result("job-ocr", [ocr_line]) |
| assert ocr_result.data_info == {"numPages": 1} |
| assert ocr_result.pages[0].doc_preprocessing_image_url == "pre.png" |
| assert ocr_result.pages[0].input_image_url == "input.png" |
| assert ocr_result.pages[0].raw["ocrImage"] == "ocr.png" |
|
|
| doc_page = { |
| "prunedResult": {"blocks": [{"label": "text", "content": "hello"}]}, |
| "markdown": { |
| "text": "hello", |
| "images": {"figure.png": "figure-url"}, |
| "isStart": True, |
| }, |
| "outputImages": {"page.png": "page-url"}, |
| "inputImage": "input.png", |
| "exports": {"docx": "docx-url"}, |
| } |
| doc_line = { |
| "result": { |
| "dataInfo": {"numPages": 1}, |
| "layoutParsingResults": [doc_page], |
| } |
| } |
| doc_result = parse_doc_parsing_result("job-doc", [doc_line]) |
| assert doc_result.data_info == {"numPages": 1} |
| assert doc_result.pages[0].pruned_result == doc_page["prunedResult"] |
| assert doc_result.pages[0].markdown == doc_page["markdown"] |
| assert doc_result.pages[0].exports == {"docx": "docx-url"} |
| assert doc_result.pages[0].raw == doc_page |
|
|
|
|
| def test_core_resolves_models_and_default_payloads(): |
| assert resolve_ocr_model("PP-OCRv5") is Model.PP_OCRV5 |
| assert resolve_ocr_model("PP-OCRv5-latin") is Model.PP_OCRV5_LATIN |
| assert resolve_ocr_model("PP-OCRv6") is Model.PP_OCRV6 |
| assert resolve_document_model("PaddleOCR-VL-1.6") is Model.PADDLE_OCR_VL_16 |
|
|
| assert default_payload(Model.PP_OCRV5) == OCROptions().to_payload() |
| assert default_payload(Model.PP_OCRV5_LATIN) == OCROptions().to_payload() |
| assert default_payload(Model.PP_OCRV6) == OCROptions().to_payload() |
| assert default_payload(Model.PADDLE_OCR_VL_16) == PaddleOCRVLOptions().to_payload() |
|
|
| with pytest.raises(InvalidRequestError): |
| resolve_ocr_model("PP-StructureV3") |
|
|
| with pytest.raises(InvalidRequestError): |
| resolve_document_model("unknown-model") |
|
|
|
|
| def test_core_selects_document_options_by_model(): |
| assert isinstance( |
| resolve_document_options(Model.PP_STRUCTURE_V3, None), |
| PPStructureV3Options, |
| ) |
| assert isinstance( |
| resolve_document_options(Model.PADDLE_OCR_VL_16, None), |
| PaddleOCRVLOptions, |
| ) |
|
|
| with pytest.raises(InvalidRequestError): |
| resolve_document_options(Model.PP_STRUCTURE_V3, PaddleOCRVLOptions()) |
|
|
| with pytest.raises(InvalidRequestError): |
| resolve_document_options(Model.PADDLE_OCR_VL_16, PPStructureV3Options()) |
|
|
|
|
| def test_core_validates_input_source_and_job_task(): |
| validate_input_source("https://example.test/file.pdf", None) |
| validate_input_source(None, "/tmp/file.pdf") |
|
|
| with pytest.raises(InvalidRequestError): |
| validate_input_source(None, None) |
|
|
| with pytest.raises(InvalidRequestError): |
| validate_input_source("https://example.test/file.pdf", "/tmp/file.pdf") |
|
|
| job = Job(job_id="job-1", model=Model.PP_OCRV5.value, task="ocr") |
| assert job_id_for_task(job, "ocr") == "job-1" |
| assert job_id_for_task("job-2", "ocr") == "job-2" |
|
|
| with pytest.raises(InvalidRequestError): |
| job_id_for_task(job, "document_parsing") |
|
|