59 lines
1.6 KiB
Python
59 lines
1.6 KiB
Python
# Copyright (c) 2026 PowerOn AG
|
|
# All rights reserved.
|
|
"""
|
|
Feature discovery utility (Layer L0 - shared).
|
|
Dynamically discovers and loads feature main modules from the features directory.
|
|
Zero internal dependencies — only os, glob, importlib, logging.
|
|
"""
|
|
|
|
import os
|
|
import glob
|
|
import importlib
|
|
import logging
|
|
from typing import Dict, Any
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
FEATURES_DIR = os.path.join(
|
|
os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "features"
|
|
)
|
|
|
|
_cachedMainModules = None
|
|
|
|
|
|
def loadFeatureMainModules() -> Dict[str, Any]:
|
|
"""
|
|
Dynamically load main modules from all discovered feature containers.
|
|
Results are cached after the first call.
|
|
"""
|
|
global _cachedMainModules
|
|
if _cachedMainModules is not None:
|
|
return _cachedMainModules
|
|
|
|
mainModules = {}
|
|
pattern = os.path.join(FEATURES_DIR, "*", "main*.py")
|
|
|
|
for filepath in glob.glob(pattern):
|
|
filename = os.path.basename(filepath)
|
|
if filename == "__init__.py":
|
|
continue
|
|
|
|
featureDir = os.path.basename(os.path.dirname(filepath))
|
|
if featureDir.startswith("_"):
|
|
continue
|
|
|
|
if featureDir in mainModules:
|
|
continue
|
|
|
|
mainFile = filename[:-3]
|
|
|
|
try:
|
|
modulePath = f"modules.features.{featureDir}.{mainFile}"
|
|
module = importlib.import_module(modulePath)
|
|
mainModules[featureDir] = module
|
|
logger.debug(f"Loaded main module: {featureDir}")
|
|
except Exception as e:
|
|
logger.error(f"Failed to load main module from {featureDir}: {e}")
|
|
|
|
_cachedMainModules = mainModules
|
|
return mainModules
|