"""Registries for filter pipeline stages and plugins.""" import importlib import logging from typing import Any, Dict, Iterable, Optional, Type logger = logging.getLogger(__name__) _STAGE_REGISTRY: Dict[str, Type[Any]] = {} _PLUGIN_REGISTRY: Dict[str, Type[Any]] = {} _DISCOVERED_MODULES = set() def register_stage(name: str): """Register a pipeline stage class under a config name.""" def decorator(stage_cls: Type[Any]): if name in _STAGE_REGISTRY and _STAGE_REGISTRY[name] is not stage_cls: logger.warning("Replacing registered filter stage '%s'", name) _STAGE_REGISTRY[name] = stage_cls return stage_cls return decorator def register_plugin(name: str): """Register a filter plugin class under a config name.""" def decorator(plugin_cls: Type[Any]): if name in _PLUGIN_REGISTRY and _PLUGIN_REGISTRY[name] is not plugin_cls: logger.warning("Replacing registered filter plugin '%s'", name) _PLUGIN_REGISTRY[name] = plugin_cls return plugin_cls return decorator def get_stage_class(name: str) -> Optional[Type[Any]]: """Return a registered stage class by name.""" return _STAGE_REGISTRY.get(name) def get_plugin_class(name: str) -> Optional[Type[Any]]: """Return a registered plugin class by name.""" return _PLUGIN_REGISTRY.get(name) def get_registered_stages() -> Dict[str, Type[Any]]: """Return a copy of registered stage classes.""" return dict(_STAGE_REGISTRY) def get_registered_plugins() -> Dict[str, Type[Any]]: """Return a copy of registered plugin classes.""" return dict(_PLUGIN_REGISTRY) def discover_modules(module_names: Iterable[str]): """Import modules for registration side effects once.""" for module_name in module_names: if not module_name or module_name in _DISCOVERED_MODULES: continue importlib.import_module(module_name) _DISCOVERED_MODULES.add(module_name)