"""Test helpers for importing the calibre plugin modules outside of calibre. The DeDRM and Obok plugins normally run inside calibre's bundled Python and use intra-package (``from .x import y``) imports. To unit-test the pure logic we: * put the plugin source directories on ``sys.path`` (for absolute imports such as ``import kgenpids`` / ``import alfcrypto``); * provide a minimal ``calibre`` stub for the few modules that import it; * register a synthetic ``dedrm`` package whose ``__path__`` points at the DeDRM_plugin directory, so modules that use relative imports resolve without executing the real (calibre-dependent) ``__init__.py``. Modules with no relative imports (alfcrypto, argv_utils, obok) are loaded top-level; modules with ``from .`` imports are loaded as ``dedrm.X``. kgenpids is a hybrid: it is imported absolutely by other worker modules, so it falls back to an absolute ``from utilities import ...`` and is still loaded top-level here. """ import importlib import os import sys import types ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) DEDRM = os.path.join(ROOT, "DeDRM_plugin") OBOK = os.path.join(ROOT, "Obok_plugin", "obok") def _ensure_on_path(path): if path not in sys.path: sys.path.insert(0, path) def _setup(): _ensure_on_path(DEDRM) _ensure_on_path(OBOK) # Minimal calibre stub (only the bits the plugin modules touch at import). if "calibre" not in sys.modules: sys.modules["calibre"] = types.ModuleType("calibre") constants = types.ModuleType("calibre.constants") constants.iswindows = sys.platform.startswith("win") sys.modules["calibre.constants"] = constants # Synthetic package so `from .x import y` works without the real __init__.py. if "dedrm" not in sys.modules: pkg = types.ModuleType("dedrm") pkg.__path__ = [DEDRM] pkg.__package__ = "dedrm" sys.modules["dedrm"] = pkg _setup() def load(module_name, package=None): """Import and return a plugin module. Pass ``package="dedrm"`` for modules that use relative imports. """ if package: return importlib.import_module("{0}.{1}".format(package, module_name)) return importlib.import_module(module_name)