Fix Python API ignoring language parameter (fixes #1640)
The API's 'language' param was silently dropped because OcrOptions uses 'languages' (plural). Map language->languages in create_options() and _pdf_to_hocr(), coercing bare strings to lists and splitting '+' separated codes to match CLI behavior.
This commit is contained in:
@@ -283,6 +283,34 @@ def _check_no_conflicting_ocr_params(
|
||||
)
|
||||
|
||||
|
||||
def _remap_language_to_languages(options_kwargs: dict) -> None:
|
||||
"""Map the public API 'language' parameter to OcrOptions 'languages' field.
|
||||
|
||||
The public API uses 'language' (matching CLI --language) but OcrOptions
|
||||
uses 'languages' (plural). This also coerces a bare string to a list
|
||||
and splits '+'-separated language codes (e.g. 'eng+deu' -> ['eng', 'deu'])
|
||||
to match the CLI behavior.
|
||||
"""
|
||||
if 'language' in options_kwargs and 'languages' not in options_kwargs:
|
||||
lang = options_kwargs.pop('language')
|
||||
if lang is None:
|
||||
return
|
||||
if isinstance(lang, str):
|
||||
lang = lang.split('+')
|
||||
else:
|
||||
# Flatten any '+'-separated entries in the list
|
||||
expanded: list[str] = []
|
||||
for item in lang:
|
||||
if isinstance(item, str) and '+' in item:
|
||||
expanded.extend(item.split('+'))
|
||||
else:
|
||||
expanded.append(item)
|
||||
lang = expanded
|
||||
options_kwargs['languages'] = lang
|
||||
elif 'language' in options_kwargs:
|
||||
del options_kwargs['language']
|
||||
|
||||
|
||||
def create_options(
|
||||
*, input_file: PathOrIO, output_file: PathOrIO, parser: ArgumentParser, **kwargs
|
||||
) -> OcrOptions:
|
||||
@@ -304,6 +332,9 @@ def create_options(
|
||||
# Prepare kwargs for direct OcrOptions construction
|
||||
options_kwargs = kwargs.copy()
|
||||
|
||||
# Map API parameter 'language' to OcrOptions field 'languages'
|
||||
_remap_language_to_languages(options_kwargs)
|
||||
|
||||
# Set input and output files
|
||||
options_kwargs['input_file'] = input_file
|
||||
options_kwargs['output_file'] = output_file
|
||||
@@ -762,6 +793,9 @@ def _pdf_to_hocr( # noqa: D417
|
||||
):
|
||||
options_kwargs[param_name] = param_value
|
||||
|
||||
# Map API parameter 'language' to OcrOptions field 'languages'
|
||||
_remap_language_to_languages(options_kwargs)
|
||||
|
||||
# Handle plugins
|
||||
if plugins:
|
||||
options_kwargs['plugins'] = plugins
|
||||
|
||||
@@ -22,6 +22,64 @@ def test_language_list():
|
||||
ocrmypdf.ocr('doesnotexist.pdf', '_.pdf', language=['eng', 'deu'])
|
||||
|
||||
|
||||
def test_language_parameter_mapped_to_languages():
|
||||
"""Test that the API 'language' parameter is mapped to OcrOptions 'languages'.
|
||||
|
||||
Regression test for GitHub issue #1640: the Python API ignored the language
|
||||
parameter, always defaulting to 'eng'.
|
||||
"""
|
||||
from ocrmypdf._options import OcrOptions
|
||||
from ocrmypdf.api import create_options, setup_plugin_infrastructure
|
||||
from ocrmypdf.cli import get_parser
|
||||
|
||||
setup_plugin_infrastructure()
|
||||
parser = get_parser()
|
||||
|
||||
options = create_options(
|
||||
input_file='test.pdf',
|
||||
output_file='output.pdf',
|
||||
parser=parser,
|
||||
language=['tam'],
|
||||
)
|
||||
assert options.languages == ['tam']
|
||||
|
||||
# Test with a list of multiple languages
|
||||
options = create_options(
|
||||
input_file='test.pdf',
|
||||
output_file='output.pdf',
|
||||
parser=parser,
|
||||
language=['fra', 'deu'],
|
||||
)
|
||||
assert options.languages == ['fra', 'deu']
|
||||
|
||||
# Test with a bare string (single language)
|
||||
options = create_options(
|
||||
input_file='test.pdf',
|
||||
output_file='output.pdf',
|
||||
parser=parser,
|
||||
language='tam',
|
||||
)
|
||||
assert options.languages == ['tam']
|
||||
|
||||
# Test '+'-separated string is split like CLI --language
|
||||
options = create_options(
|
||||
input_file='test.pdf',
|
||||
output_file='output.pdf',
|
||||
parser=parser,
|
||||
language='eng+spa',
|
||||
)
|
||||
assert options.languages == ['eng', 'spa']
|
||||
|
||||
# Test '+'-separated entry within a list is also split
|
||||
options = create_options(
|
||||
input_file='test.pdf',
|
||||
output_file='output.pdf',
|
||||
parser=parser,
|
||||
language=['eng+spa'],
|
||||
)
|
||||
assert options.languages == ['eng', 'spa']
|
||||
|
||||
|
||||
def test_stream_api(resources: Path):
|
||||
in_ = (resources / 'graph.pdf').open('rb')
|
||||
out = BytesIO()
|
||||
|
||||
Reference in New Issue
Block a user