cli: push up imports
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -164,7 +164,6 @@ class OCROptions(BaseModel):
|
||||
default_factory=dict, exclude=True, alias='_extra_attrs'
|
||||
)
|
||||
|
||||
|
||||
@field_validator('languages')
|
||||
@classmethod
|
||||
def validate_languages(cls, v):
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user