feat: add legacy field mapping to plugin registry
Co-authored-by: aider (openrouter/anthropic/claude-sonnet-4) <aider@aider.chat>
This commit is contained in:
@@ -161,6 +161,8 @@ class OCROptions(BaseModel):
|
||||
tesseract_non_ocr_timeout: float | None = None
|
||||
tesseract_downsample_above: int = 32767
|
||||
tesseract_downsample_large_images: bool | None = None
|
||||
user_words: str | None = None
|
||||
user_patterns: str | None = None
|
||||
|
||||
# Legacy ghostscript options (for backward compatibility)
|
||||
pdfa_image_compression: str | None = None
|
||||
|
||||
@@ -76,3 +76,81 @@ class PluginOptionRegistry:
|
||||
def clear_cache(self) -> None:
|
||||
"""Clear the extended model cache."""
|
||||
self._extended_model_cache = None
|
||||
|
||||
def map_legacy_options(self, options: dict) -> dict:
|
||||
"""Map legacy flat options to nested plugin options.
|
||||
|
||||
This method helps with backward compatibility by mapping flat option
|
||||
names (like 'tesseract_timeout') to nested plugin option structures.
|
||||
|
||||
Args:
|
||||
options: Dictionary of flat options
|
||||
|
||||
Returns:
|
||||
Dictionary with both legacy flat options and nested plugin options
|
||||
"""
|
||||
result = options.copy()
|
||||
|
||||
# Map tesseract options
|
||||
if 'tesseract' in self._option_models:
|
||||
tesseract_options = {}
|
||||
tesseract_fields = self._option_models['tesseract'].model_fields.keys()
|
||||
|
||||
for field in tesseract_fields:
|
||||
legacy_key = f'tesseract_{field}'
|
||||
if legacy_key in options:
|
||||
tesseract_options[field] = options[legacy_key]
|
||||
|
||||
if tesseract_options:
|
||||
result['tesseract'] = tesseract_options
|
||||
|
||||
# Map optimize options
|
||||
if 'optimize' in self._option_models:
|
||||
optimize_options = {}
|
||||
optimize_fields = self._option_models['optimize'].model_fields.keys()
|
||||
|
||||
for field in optimize_fields:
|
||||
if field in options:
|
||||
optimize_options[field] = options[field]
|
||||
# Handle special case for optimize level
|
||||
elif field == 'level' and 'optimize' in options:
|
||||
optimize_options[field] = options['optimize']
|
||||
|
||||
if optimize_options:
|
||||
result['optimize'] = optimize_options
|
||||
|
||||
# Map ghostscript options
|
||||
if 'ghostscript' in self._option_models:
|
||||
ghostscript_options = {}
|
||||
ghostscript_fields = self._option_models['ghostscript'].model_fields.keys()
|
||||
|
||||
for field in ghostscript_fields:
|
||||
if field in options:
|
||||
ghostscript_options[field] = options[field]
|
||||
|
||||
if ghostscript_options:
|
||||
result['ghostscript'] = ghostscript_options
|
||||
|
||||
return result
|
||||
|
||||
def validate_plugin_options(self, options: dict) -> dict:
|
||||
"""Validate plugin options using their registered models.
|
||||
|
||||
Args:
|
||||
options: Dictionary containing plugin options
|
||||
|
||||
Returns:
|
||||
Dictionary with validated plugin options
|
||||
|
||||
Raises:
|
||||
ValidationError: If any plugin options are invalid
|
||||
"""
|
||||
validated = {}
|
||||
|
||||
for namespace, model_class in self._option_models.items():
|
||||
if namespace in options:
|
||||
# Validate using the plugin's model
|
||||
plugin_options = model_class(**options[namespace])
|
||||
validated[namespace] = plugin_options.model_dump()
|
||||
|
||||
return validated
|
||||
|
||||
@@ -58,6 +58,12 @@ class TesseractOptions(BaseModel):
|
||||
description="Downsample images larger than this pixel size",
|
||||
),
|
||||
] = 32767
|
||||
user_words: Annotated[
|
||||
str | None, Field(description="Path to Tesseract user words file")
|
||||
] = None
|
||||
user_patterns: Annotated[
|
||||
str | None, Field(description="Path to Tesseract user patterns file")
|
||||
] = None
|
||||
|
||||
@classmethod
|
||||
def add_arguments_to_parser(cls, parser, namespace: str = 'tesseract'):
|
||||
@@ -182,6 +188,22 @@ class TesseractOptions(BaseModel):
|
||||
),
|
||||
)
|
||||
|
||||
tess.add_argument(
|
||||
'--user-words',
|
||||
metavar='FILE',
|
||||
dest='user_words',
|
||||
help="Specify the location of the Tesseract user words file. This is a "
|
||||
"list of words Tesseract should consider while performing OCR in "
|
||||
"addition to its standard language dictionaries. This can improve "
|
||||
"OCR quality especially for specialized and technical documents.",
|
||||
)
|
||||
tess.add_argument(
|
||||
'--user-patterns',
|
||||
metavar='FILE',
|
||||
dest='user_patterns',
|
||||
help="Specify the location of the Tesseract user patterns file.",
|
||||
)
|
||||
|
||||
|
||||
@hookimpl
|
||||
def register_options():
|
||||
@@ -191,25 +213,9 @@ def register_options():
|
||||
|
||||
@hookimpl
|
||||
def add_options(parser):
|
||||
# Use the model's CLI generation method
|
||||
# Use the model's CLI generation method - it now handles all Tesseract options
|
||||
TesseractOptions.add_arguments_to_parser(parser)
|
||||
|
||||
# Add user words and patterns (these are not part of TesseractOptions model yet)
|
||||
tess = parser.add_argument_group("Tesseract", "Advanced control of Tesseract OCR")
|
||||
tess.add_argument(
|
||||
'--user-words',
|
||||
metavar='FILE',
|
||||
help="Specify the location of the Tesseract user words file. This is a "
|
||||
"list of words Tesseract should consider while performing OCR in "
|
||||
"addition to its standard language dictionaries. This can improve "
|
||||
"OCR quality especially for specialized and technical documents.",
|
||||
)
|
||||
tess.add_argument(
|
||||
'--user-patterns',
|
||||
metavar='FILE',
|
||||
help="Specify the location of the Tesseract user patterns file.",
|
||||
)
|
||||
|
||||
|
||||
@hookimpl
|
||||
def check_options(options):
|
||||
|
||||
Reference in New Issue
Block a user