cli: push up imports

This commit is contained in:
James R. Barlow
2025-12-21 12:21:48 -08:00
parent 42891346d1
commit b7737446e4
7 changed files with 32 additions and 34 deletions
+1 -1
View File
@@ -16,8 +16,8 @@ from contextlib import suppress
from ocrmypdf import __version__
from ocrmypdf._pipelines.ocr import run_pipeline_cli
from ocrmypdf._validation import check_options
from ocrmypdf.cli import get_options_and_plugins
from ocrmypdf.api import Verbosity, configure_logging
from ocrmypdf.cli import get_options_and_plugins
from ocrmypdf.exceptions import (
BadArgsError,
ExitCode,
-1
View File
@@ -164,7 +164,6 @@ class OCROptions(BaseModel):
default_factory=dict, exclude=True, alias='_extra_attrs'
)
@field_validator('languages')
@classmethod
def validate_languages(cls, v):
-2
View File
@@ -5,7 +5,6 @@
from __future__ import annotations
import argparse
import importlib
import importlib.util
import pkgutil
@@ -17,7 +16,6 @@ import pluggy
import ocrmypdf.builtin_plugins
from ocrmypdf import pluginspec
from ocrmypdf.cli import get_parser
class OcrmypdfPluginManager(pluggy.PluginManager):
+15 -20
View File
@@ -7,16 +7,16 @@ from __future__ import annotations
import argparse
from collections.abc import Callable, Mapping
from typing import Any, TypeVar, TYPE_CHECKING
from typing import Any, TypeVar
from ocrmypdf._defaults import DEFAULT_LANGUAGE, DEFAULT_ROTATE_PAGES_THRESHOLD
import pluggy
from ocrmypdf._defaults import DEFAULT_ROTATE_PAGES_THRESHOLD
from ocrmypdf._defaults import PROGRAM_NAME as _PROGRAM_NAME
from ocrmypdf._options import OCROptions
from ocrmypdf._plugin_manager import get_plugin_manager
from ocrmypdf._version import __version__ as _VERSION
if TYPE_CHECKING:
import pluggy
from ocrmypdf._options import OCROptions
T = TypeVar('T', int, float)
@@ -100,7 +100,7 @@ class LanguageSetAction(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
"""Add a language to the set."""
dest = getattr(namespace, self.dest)
if '+' in values:
if isinstance(values, str) and '+' in values:
[dest.append(lang) for lang in values.split('+')]
else:
dest.append(values)
@@ -471,14 +471,12 @@ plugins_only_parser.add_argument(
)
def namespace_to_options(ns) -> 'OCROptions':
def namespace_to_options(ns) -> OCROptions:
"""Convert argparse.Namespace to OCROptions.
This function encapsulates CLI-specific knowledge of how command line
arguments map to our internal options model.
"""
from ocrmypdf._options import OCROptions
# Extract known fields
known_fields = {}
extra_attrs = {}
@@ -504,22 +502,19 @@ def namespace_to_options(ns) -> 'OCROptions':
def get_options_and_plugins(
args=None,
) -> tuple['OCROptions', 'pluggy.PluginManager']:
) -> tuple[OCROptions, pluggy.PluginManager]:
"""Parse command line arguments and return OCROptions and plugin manager.
This is the main entry point for CLI argument processing. It handles
plugin discovery, argument parsing, and conversion to our internal
options model.
Args:
args: Command line arguments. If None, uses sys.argv.
Returns:
Tuple of (OCROptions, PluginManager)
"""
import pluggy
from ocrmypdf._plugin_manager import get_plugin_manager
# First pass: get plugins so we can register their options
pre_options, _unused = plugins_only_parser.parse_known_args(args=args)
plugin_manager = get_plugin_manager(pre_options.plugins)
@@ -531,8 +526,8 @@ def get_options_and_plugins(
# Parse all arguments
namespace = parser.parse_args(args=args)
# Convert to OCROptions
options = namespace_to_options(namespace)
return options, plugin_manager
+5 -1
View File
@@ -25,6 +25,7 @@ def worker_function(options_json: str) -> str:
# Return as JSON string
import json
return json.dumps(result)
@@ -68,6 +69,7 @@ def test_json_serialization_multiprocessing():
# Verify results from worker processes
import json
for result_json in results:
result = json.loads(result_json)
assert result['input_file'] == '/test/input.pdf'
@@ -122,7 +124,9 @@ def test_json_serialization_with_none_values():
# Verify None values are preserved (check actual defaults from model)
assert reconstructed.tesseract_timeout == 0.0 # Default value, not None
assert reconstructed.fast_web_view == 1.0 # Default value, not None
assert reconstructed.color_conversion_strategy == "LeaveColorUnchanged" # Default value
assert (
reconstructed.color_conversion_strategy == "LeaveColorUnchanged"
) # Default value
assert reconstructed.pdfa_image_compression is None # This one is actually None
# Verify non-None values are preserved
+1 -1
View File
@@ -11,8 +11,8 @@ import pytest
from packaging.version import Version
from ocrmypdf._exec import unpaper
from ocrmypdf.cli import get_options_and_plugins
from ocrmypdf._validation import check_options
from ocrmypdf.cli import get_options_and_plugins
from ocrmypdf.exceptions import BadArgsError, ExitCode, MissingDependencyError
from .conftest import check_ocrmypdf, have_unpaper, run_ocrmypdf_api
+10 -8
View File
@@ -44,11 +44,7 @@ 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
)
return OCROptions(input_file=input_file, output_file=output_file, **kwargs)
def test_old_tesseract_error():
@@ -78,11 +74,17 @@ def test_lossless_redo():
def test_mutex_options():
with pytest.raises(ValueError, match="Choose only one of --force-ocr, --skip-text, --redo-ocr"):
with pytest.raises(
ValueError, match="Choose only one of --force-ocr, --skip-text, --redo-ocr"
):
make_ocr_opts(force_ocr=True, skip_text=True)
with pytest.raises(ValueError, match="Choose only one of --force-ocr, --skip-text, --redo-ocr"):
with pytest.raises(
ValueError, match="Choose only one of --force-ocr, --skip-text, --redo-ocr"
):
make_ocr_opts(redo_ocr=True, skip_text=True)
with pytest.raises(ValueError, match="Choose only one of --force-ocr, --skip-text, --redo-ocr"):
with pytest.raises(
ValueError, match="Choose only one of --force-ocr, --skip-text, --redo-ocr"
):
make_ocr_opts(redo_ocr=True, force_ocr=True)