Rename OCROptions to OcrOptions for consistency

Technically OCROptions is more Pythonic but we have several pre-existing classes named OcrWhatever. Go with the local flow.
This commit is contained in:
James R. Barlow
2026-01-12 23:37:54 -08:00
parent 36dea181e6
commit 740f67091c
26 changed files with 197 additions and 190 deletions
+2 -2
View File
@@ -107,14 +107,14 @@ def test_hocr_result_pickle():
def test_nested_plugin_option_access():
"""Test that plugin options can be accessed via nested namespaces."""
from ocrmypdf._options import OCROptions
from ocrmypdf._options import OcrOptions
from ocrmypdf.api import setup_plugin_infrastructure
# Set up plugin infrastructure to register plugin models
setup_plugin_infrastructure()
# Create options with tesseract settings
options = OCROptions(
options = OcrOptions(
input_file='test.pdf',
output_file='output.pdf',
tesseract_timeout=120.0,
+16 -16
View File
@@ -1,4 +1,4 @@
"""Test JSON serialization of OCROptions for multiprocessing compatibility."""
"""Test JSON serialization of OcrOptions for multiprocessing compatibility."""
import multiprocessing
from io import BytesIO
@@ -6,28 +6,28 @@ from pathlib import Path
import pytest
from ocrmypdf._options import OCROptions
from ocrmypdf._options import OcrOptions
from ocrmypdf.builtin_plugins.tesseract_ocr import TesseractOptions
@pytest.fixture(autouse=True)
def register_plugin_models():
"""Register plugin models for tests."""
OCROptions.register_plugin_models({'tesseract': TesseractOptions})
OcrOptions.register_plugin_models({'tesseract': TesseractOptions})
yield
# Clean up after test (optional, but good practice)
def worker_function(options_json: str) -> str:
"""Worker function that deserializes OCROptions from JSON and returns a result."""
"""Worker function that deserializes OcrOptions from JSON and returns a result."""
# Register plugin models in worker process
from ocrmypdf._options import OCROptions
from ocrmypdf._options import OcrOptions
from ocrmypdf.builtin_plugins.tesseract_ocr import TesseractOptions
OCROptions.register_plugin_models({'tesseract': TesseractOptions})
OcrOptions.register_plugin_models({'tesseract': TesseractOptions})
# Reconstruct OCROptions from JSON in worker process
options = OCROptions.model_validate_json_safe(options_json)
# Reconstruct OcrOptions from JSON in worker process
options = OcrOptions.model_validate_json_safe(options_json)
# Verify we can access various option types
# Count only user-added extra_attrs (exclude plugin cache keys starting with '_')
@@ -51,9 +51,9 @@ def worker_function(options_json: str) -> str:
def test_json_serialization_multiprocessing():
"""Test that OCROptions can be JSON serialized and used in multiprocessing."""
# Create OCROptions with various field types
options = OCROptions(
"""Test that OcrOptions can be JSON serialized and used in multiprocessing."""
# Create OcrOptions with various field types
options = OcrOptions(
input_file=Path('/test/input.pdf'),
output_file=Path('/test/output.pdf'),
languages=['eng', 'deu'],
@@ -72,7 +72,7 @@ def test_json_serialization_multiprocessing():
options_json = options.model_dump_json_safe()
# Test that we can deserialize in the main process
reconstructed = OCROptions.model_validate_json_safe(options_json)
reconstructed = OcrOptions.model_validate_json_safe(options_json)
assert reconstructed.input_file == options.input_file
assert reconstructed.output_file == options.output_file
assert reconstructed.languages == options.languages
@@ -112,7 +112,7 @@ def test_json_serialization_with_streams():
input_stream = BytesIO(b'fake pdf data')
output_stream = BytesIO()
options = OCROptions(
options = OcrOptions(
input_file=input_stream,
output_file=output_stream,
languages=['eng'],
@@ -123,7 +123,7 @@ def test_json_serialization_with_streams():
options_json = options.model_dump_json_safe()
# Deserialize (streams will be placeholder strings)
reconstructed = OCROptions.model_validate_json_safe(options_json)
reconstructed = OcrOptions.model_validate_json_safe(options_json)
# Streams should be converted to placeholder strings
assert reconstructed.input_file == 'stream'
@@ -134,7 +134,7 @@ def test_json_serialization_with_streams():
def test_json_serialization_with_none_values():
"""Test JSON serialization handles None values correctly."""
options = OCROptions(
options = OcrOptions(
input_file=Path('/test/input.pdf'),
output_file=Path('/test/output.pdf'),
languages=['eng'],
@@ -145,7 +145,7 @@ def test_json_serialization_with_none_values():
options_json = options.model_dump_json_safe()
# Deserialize
reconstructed = OCROptions.model_validate_json_safe(options_json)
reconstructed = OcrOptions.model_validate_json_safe(options_json)
# Verify None values are preserved (check actual defaults from model)
assert reconstructed.tesseract_timeout == 0.0 # Default value, not None
+7 -7
View File
@@ -74,14 +74,14 @@ class TestOcrEngineCliOption:
class TestOcrEngineOptionsModel:
"""Test OCROptions has ocr_engine field."""
"""Test OcrOptions has ocr_engine field."""
def test_ocr_options_has_ocr_engine_field(self):
"""OCROptions should have ocr_engine field."""
from ocrmypdf._options import OCROptions
"""OcrOptions should have ocr_engine field."""
from ocrmypdf._options import OcrOptions
# Check field exists in model
assert 'ocr_engine' in OCROptions.model_fields
assert 'ocr_engine' in OcrOptions.model_fields
class TestOcrEnginePluginSelection:
@@ -91,8 +91,8 @@ class TestOcrEnginePluginSelection:
"""TesseractOcrEngine should be returned when ocr_engine='auto'."""
from unittest.mock import MagicMock
from ocrmypdf.builtin_plugins.tesseract_ocr import TesseractOcrEngine
from ocrmypdf.builtin_plugins import tesseract_ocr
from ocrmypdf.builtin_plugins.tesseract_ocr import TesseractOcrEngine
options = MagicMock()
options.ocr_engine = 'auto'
@@ -104,8 +104,8 @@ class TestOcrEnginePluginSelection:
"""TesseractOcrEngine should be returned when ocr_engine='tesseract'."""
from unittest.mock import MagicMock
from ocrmypdf.builtin_plugins.tesseract_ocr import TesseractOcrEngine
from ocrmypdf.builtin_plugins import tesseract_ocr
from ocrmypdf.builtin_plugins.tesseract_ocr import TesseractOcrEngine
options = MagicMock()
options.ocr_engine = 'tesseract'
@@ -117,8 +117,8 @@ class TestOcrEnginePluginSelection:
"""NullOcrEngine should be returned when ocr_engine='none'."""
from unittest.mock import MagicMock
from ocrmypdf.builtin_plugins.null_ocr import NullOcrEngine
from ocrmypdf.builtin_plugins import null_ocr
from ocrmypdf.builtin_plugins.null_ocr import NullOcrEngine
options = MagicMock()
options.ocr_engine = 'none'
+16 -17
View File
@@ -12,7 +12,7 @@ import pikepdf
import pytest
from PIL import Image
from ocrmypdf._options import OCROptions
from ocrmypdf._options import OcrOptions
from ocrmypdf._plugin_manager import get_plugin_manager
from ocrmypdf.helpers import IMG2PDF_KWARGS, Resolution
@@ -67,7 +67,7 @@ class TestRasterizerOption:
def test_rasterizer_invalid(self):
"""Test that an invalid rasterizer value is rejected."""
with pytest.raises(ValueError, match="rasterizer must be one of"):
OCROptions(
OcrOptions(
input_file='test.pdf', output_file='out.pdf', rasterizer='invalid'
)
@@ -127,7 +127,7 @@ class TestRasterizerHookDirect:
pm = get_plugin_manager([])
# Create options requesting pypdfium
options = OCROptions(
options = OcrOptions(
input_file=resources / 'graph.pdf',
output_file=tmp_path / 'out.pdf',
rasterizer='pypdfium',
@@ -162,7 +162,7 @@ class TestRasterizerHookDirect:
pm = get_plugin_manager([])
# Create options requesting ghostscript
options = OCROptions(
options = OcrOptions(
input_file=resources / 'graph.pdf',
output_file=tmp_path / 'out.pdf',
rasterizer='ghostscript',
@@ -190,7 +190,7 @@ class TestRasterizerHookDirect:
"""Test that auto mode uses pypdfium when available."""
pm = get_plugin_manager([])
options = OCROptions(
options = OcrOptions(
input_file=resources / 'graph.pdf',
output_file=tmp_path / 'out.pdf',
rasterizer='auto',
@@ -363,7 +363,7 @@ class TestRasterizerWithNonStandardBoxes:
"""Compare output dimensions between rasterizers for nonstandard boxes."""
pm = get_plugin_manager([])
options_gs = OCROptions(
options_gs = OcrOptions(
input_file=pdf_with_nonstandard_boxes,
output_file=tmp_path / 'out_gs.pdf',
rasterizer='ghostscript',
@@ -388,7 +388,7 @@ class TestRasterizerWithNonStandardBoxes:
gs_size = im_gs.size
if PYPDFIUM_AVAILABLE:
options_pdfium = OCROptions(
options_pdfium = OcrOptions(
input_file=pdf_with_nonstandard_boxes,
output_file=tmp_path / 'out_pdfium.pdf',
rasterizer='pypdfium',
@@ -445,7 +445,7 @@ class TestRasterizerWithRotationAndBoxes:
"""Test Ghostscript produces correct dimensions with rotation."""
pm = get_plugin_manager([])
options = OCROptions(
options = OcrOptions(
input_file=pdf_with_nonstandard_boxes,
output_file=tmp_path / 'out.pdf',
rasterizer='ghostscript',
@@ -481,13 +481,11 @@ class TestRasterizerWithRotationAndBoxes:
)
@pytest.mark.skipif(not PYPDFIUM_AVAILABLE, reason="pypdfium2 not installed")
def test_pypdfium_rotation_dimensions(
self, pdf_with_nonstandard_boxes, tmp_path
):
def test_pypdfium_rotation_dimensions(self, pdf_with_nonstandard_boxes, tmp_path):
"""Test pypdfium produces correct dimensions with rotation."""
pm = get_plugin_manager([])
options = OCROptions(
options = OcrOptions(
input_file=pdf_with_nonstandard_boxes,
output_file=tmp_path / 'out.pdf',
rasterizer='pypdfium',
@@ -535,7 +533,7 @@ class TestRasterizerWithRotationAndBoxes:
for rotation in [0, 90, 180, 270]:
# Rasterize with Ghostscript
gs_options = OCROptions(
gs_options = OcrOptions(
input_file=pdf_with_nonstandard_boxes,
output_file=tmp_path / 'out.pdf',
rasterizer='ghostscript',
@@ -556,7 +554,7 @@ class TestRasterizerWithRotationAndBoxes:
)
# Rasterize with pypdfium
pdfium_options = OCROptions(
pdfium_options = OcrOptions(
input_file=pdf_with_nonstandard_boxes,
output_file=tmp_path / 'out.pdf',
rasterizer='pypdfium',
@@ -577,9 +575,10 @@ class TestRasterizerWithRotationAndBoxes:
)
# Verify both produce the same MediaBox dimensions
with Image.open(gs_img_path) as gs_img, Image.open(
pdfium_img_path
) as pdfium_img:
with (
Image.open(gs_img_path) as gs_img,
Image.open(pdfium_img_path) as pdfium_img,
):
expected = self._get_expected_size(rotation)
assert abs(gs_img.size[0] - expected[0]) <= 2, (
+2 -2
View File
@@ -329,11 +329,11 @@ def test_rotate_and_crop(
def test_rasterize_rotates(resources, tmp_path):
from ocrmypdf._options import OCROptions
from ocrmypdf._options import OcrOptions
pm = get_plugin_manager([])
options = OCROptions(
options = OcrOptions(
input_file=resources / 'graph.pdf',
output_file=tmp_path / 'out.pdf',
rasterizer='ghostscript', # Use Ghostscript for consistent dimensions
+4 -4
View File
@@ -13,7 +13,7 @@ import pytest
from ocrmypdf import _validation as vd
from ocrmypdf._concurrent import NullProgressBar, SerialExecutor
from ocrmypdf._exec.tesseract import TesseractVersion
from ocrmypdf._options import OCROptions
from ocrmypdf._options import OcrOptions
from ocrmypdf.api import create_options, setup_plugin_infrastructure
from ocrmypdf.cli import get_parser
from ocrmypdf.exceptions import BadArgsError, MissingDependencyError
@@ -42,8 +42,8 @@ def make_opts(*args, **kwargs):
def make_ocr_opts(input_file='a.pdf', output_file='b.pdf', **kwargs):
"""Create OCROptions directly for testing Pydantic validation."""
return OCROptions(input_file=input_file, output_file=output_file, **kwargs)
"""Create OcrOptions directly for testing Pydantic validation."""
return OcrOptions(input_file=input_file, output_file=output_file, **kwargs)
def test_old_tesseract_error():
@@ -95,7 +95,7 @@ def test_optimizing(caplog):
def test_pillow_options():
# Test that max_image_mpixels=0 is valid (validation now in OCROptions)
# Test that max_image_mpixels=0 is valid (validation now in OcrOptions)
opts = make_ocr_opts(max_image_mpixels=0)
assert opts.max_image_mpixels == 0