mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-10-04 14:25:08 +00:00
perf: import package re-exports on first use (#724)
src/common/__init__.py and src/plugin_system/__init__.py resolve their re-exports lazily (PEP 562 __getattr__, __all__ and __dir__ unchanged, TYPE_CHECKING imports for mypy), and sync_manager imports numpy only where send_frame uses it. The web process no longer loads numpy, freetype helpers and PluginManager just to import path_safety, store_manager or schema_manager (~67 MB to ~54 MB RSS on a Pi 4). from src.common import X and from src.plugin_system import X keep working, including submodule imports. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -3,15 +3,46 @@ LEDMatrix Plugin System
|
||||
|
||||
This module provides the core plugin infrastructure for the LEDMatrix project.
|
||||
It enables dynamic loading, management, and discovery of display plugins.
|
||||
|
||||
BasePlugin and PluginManager are imported on first use (PEP 562), not when
|
||||
the package is imported: the web interface imports several submodules
|
||||
(store_manager, schema_manager, ...) and never needs PluginManager, which
|
||||
pulls in the loader, executor and the shared helpers behind them.
|
||||
``from src.plugin_system import BasePlugin`` works as before and returns the
|
||||
same class.
|
||||
"""
|
||||
|
||||
import importlib
|
||||
from typing import TYPE_CHECKING, Any, Dict, List, Tuple
|
||||
|
||||
__version__ = "1.0.0"
|
||||
|
||||
from .base_plugin import BasePlugin
|
||||
from .plugin_manager import PluginManager
|
||||
if TYPE_CHECKING:
|
||||
from .base_plugin import BasePlugin
|
||||
from .plugin_manager import PluginManager
|
||||
|
||||
#: Exported name -> (module it lives in, attribute name there).
|
||||
_LAZY: Dict[str, Tuple[str, str]] = {
|
||||
'BasePlugin': ('src.plugin_system.base_plugin', 'BasePlugin'),
|
||||
'PluginManager': ('src.plugin_system.plugin_manager', 'PluginManager'),
|
||||
}
|
||||
|
||||
__all__ = [
|
||||
'BasePlugin',
|
||||
'PluginManager',
|
||||
]
|
||||
|
||||
|
||||
def __getattr__(name: str) -> Any:
|
||||
"""Import an exported name on first access (PEP 562); see src.common."""
|
||||
try:
|
||||
module_name, attr = _LAZY[name]
|
||||
except KeyError:
|
||||
raise AttributeError(f"module {__name__!r} has no attribute {name!r}") from None
|
||||
value = getattr(importlib.import_module(module_name), attr) # nosemgrep: python.lang.security.audit.non-literal-import.non-literal-import -- module_name comes from the fixed _LAZY table
|
||||
globals()[name] = value
|
||||
return value
|
||||
|
||||
|
||||
def __dir__() -> List[str]:
|
||||
return sorted(set(globals()) | set(__all__))
|
||||
|
||||
Reference in New Issue
Block a user