feat: add plugin auto-discovery via importlib
This commit is contained in:
parent
7e769872a7
commit
f34c805b84
85
src/proxy_pool/plugins/discovery.py
Normal file
85
src/proxy_pool/plugins/discovery.py
Normal 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__,
|
||||
)
|
||||
Loading…
x
Reference in New Issue
Block a user