- Cover the new utilities helpers (unpad, crc32, checksumPid type preservation, pidFromSerial, safe_join) and drop the now-redundant per-module crc32 tests. - Rename test_unpad_removes_pkcs7_padding to reflect that unpad only trusts the trailing pad-length byte rather than validating PKCS#7. - Replace the KOBO_HASH_KEYS change-detector with a test that documents the intentional value pin and checks the ASCII-salt contract. - Note kgenpids' hybrid import in the test-loader docstring. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
64 lines
2.2 KiB
Python
64 lines
2.2 KiB
Python
"""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)
|