71 lines
2.2 KiB
Python
71 lines
2.2 KiB
Python
"""Regression tests for directory-plugin module loading."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
import sys
|
|
|
|
from plugins.plugin_loader import load_plugin_module
|
|
|
|
|
|
def test_failed_sibling_is_removed_before_init_handles_missing_import(tmp_path):
|
|
"""A failed eager sibling import must remain catchable as ModuleNotFoundError."""
|
|
plugin_dir = tmp_path / "plugin"
|
|
plugin_dir.mkdir()
|
|
(plugin_dir / "broken.py").write_text(
|
|
"from .missing_dependency import value\n",
|
|
encoding="utf-8",
|
|
)
|
|
(plugin_dir / "__init__.py").write_text(
|
|
"try:\n"
|
|
" from .broken import value\n"
|
|
"except ModuleNotFoundError:\n"
|
|
" fallback_used = True\n",
|
|
encoding="utf-8",
|
|
)
|
|
module_name = "test_plugin_loader_package.failed_sibling"
|
|
|
|
try:
|
|
module = load_plugin_module(
|
|
module_name,
|
|
plugin_dir,
|
|
parents=(),
|
|
logger=logging.getLogger(__name__),
|
|
)
|
|
|
|
assert module is not None
|
|
assert module.fallback_used is True
|
|
assert f"{module_name}.broken" not in sys.modules
|
|
finally:
|
|
for name in tuple(sys.modules):
|
|
if name == module_name or name.startswith(f"{module_name}."):
|
|
sys.modules.pop(name, None)
|
|
|
|
|
|
def test_successful_sibling_remains_available_on_loaded_module(tmp_path):
|
|
"""Cleaning failed siblings must not alter the eager success path."""
|
|
plugin_dir = tmp_path / "plugin"
|
|
plugin_dir.mkdir()
|
|
(plugin_dir / "helper.py").write_text("value = 42\n", encoding="utf-8")
|
|
(plugin_dir / "__init__.py").write_text(
|
|
"from .helper import value\n",
|
|
encoding="utf-8",
|
|
)
|
|
module_name = "test_plugin_loader_package.successful_sibling"
|
|
|
|
try:
|
|
module = load_plugin_module(
|
|
module_name,
|
|
plugin_dir,
|
|
parents=(),
|
|
logger=logging.getLogger(__name__),
|
|
)
|
|
|
|
assert module is not None
|
|
assert module.value == 42
|
|
assert module.helper.value == 42
|
|
finally:
|
|
for name in tuple(sys.modules):
|
|
if name == module_name or name.startswith(f"{module_name}."):
|
|
sys.modules.pop(name, None)
|