# © 2020 James R. Barlow: github.com/jbarlow83 # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. import argparse import importlib import importlib.util import sys from functools import partial from pathlib import Path from typing import Callable, List, Tuple, Union import pluggy from ocrmypdf import pluginspec from ocrmypdf.cli import get_parser, plugins_only_parser class OcrmypdfPluginManager(pluggy.PluginManager): """pluggy.PluginManager that can fork. Capable of reconstructing itself in child workers. Arguments: setup_func: callback that initializes the plugin manager with all standard plugins """ def __init__( self, *args, setup_func: Callable[[pluggy.PluginManager], None], **kwargs ): self._init_args = args self._setup_func = setup_func self._init_kwargs = kwargs super().__init__(*args, **kwargs) setup_func(self) def __getstate__(self): state = dict( _init_args=self._init_args, _setup_func=self._setup_func, _init_kwargs=self._init_kwargs, ) return state def __setstate__(self, state): self.__init__( *state['_init_args'], setup_func=state['_setup_func'], **state['_init_kwargs'], ) def _setup_plugins( pm: pluggy.PluginManager, plugins: List[Union[str, Path]], builtins: bool = True ): pm.add_hookspecs(pluginspec) all_plugins: List[Union[str, Path]] = [] if builtins: all_plugins.extend( [ 'ocrmypdf.builtin_plugins.ghostscript', 'ocrmypdf.builtin_plugins.tesseract_ocr', ] ) all_plugins.extend(plugins) for name in all_plugins: if isinstance(name, Path) or name.endswith('.py'): # Import by filename module_name = Path(name).stem spec = importlib.util.spec_from_file_location(module_name, name) module = importlib.util.module_from_spec(spec) sys.modules[module_name] = module spec.loader.exec_module(module) else: # Import by dotted module name module = importlib.import_module(name) pm.register(module) def get_plugin_manager(plugins: List[str], builtins=True): pm = OcrmypdfPluginManager( project_name='ocrmypdf', setup_func=partial(_setup_plugins, plugins=plugins, builtins=builtins), ) return pm def get_parser_options_plugins( args, ) -> Tuple[argparse.ArgumentParser, argparse.Namespace, pluggy.PluginManager]: pre_options, _unused = plugins_only_parser.parse_known_args(args=args) plugin_manager = get_plugin_manager(pre_options.plugins) parser = get_parser() plugin_manager.hook.add_options(parser=parser) # pylint: disable=no-member options = parser.parse_args(args=args) return parser, options, plugin_manager