feat: add plugin auto-discovery via importlib

This commit is contained in:
agatha 2026-03-14 15:14:11 -04:00
parent 7e769872a7
commit f34c805b84

View File

@ -0,0 +1,85 @@
from __future__ import annotations
import importlib
import logging
from pathlib import Path
from proxy_pool.config import Settings
from proxy_pool.plugins.protocols import Notifier, ProxyChecker, SourceParser
from proxy_pool.plugins.registry import PluginRegistry
logger = logging.getLogger(__name__)
def discover_plugins(
package: str,
registry: PluginRegistry,
settings: Settings,
) -> None:
try:
mod = importlib.import_module(package)
except ImportError:
logger.warning("Plugin package '%s' not found, skipping", package)
return
if hasattr(mod, "__path__"):
logger.warning(
"Plugin package '%s' has no __path__ attribute, skipping", package
)
return
package_path = Path(mod.__path__[0])
for path in sorted(package_path.rglob("*.py")):
if path.name.startswith("_"):
continue
relative = path.relative_to(package_path)
module_parts = relative.with_suffix("").parts
module_name = f"{package}.{'.'.join(module_parts)}"
try:
plugin_module = importlib.import_module(module_name)
except Exception:
logger.exception("Failed to import plugin module '%s'", module_name)
continue
if not hasattr(plugin_module, "create_plugin"):
continue
try:
plugin = plugin_module.create_plugin(settings)
except Exception:
logger.exception(
"Failed to create plugin from '%s'",
module_name,
)
continue
if plugin is None:
logger.debug(
"Plugin '%s' returned None (disabled by config)",
module_name,
)
continue
_register_plugin(registry, plugin, module_name)
def _register_plugin(
registry: PluginRegistry,
plugin: object,
module_name: str,
) -> None:
if isinstance(plugin, SourceParser):
registry.register_parser(plugin)
elif isinstance(plugin, ProxyChecker):
registry.register_checker(plugin)
elif isinstance(plugin, Notifier):
registry.register_notifier(plugin)
else:
logger.warning(
"Plugin from '%s' has unknown type: %s",
module_name,
type(plugin).__name__,
)