Source code for structum_lab.plugins.dynaconf.core.manager

# src/structum_lab.plugins.dynaconf/manager.py
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: 2025 PythonWoods

"""Gestore di Configurazione Centrale per Structum.

Fornisce un punto di accesso centralizzato e singleton per tutte le configurazioni.
Supporta la registrazione dinamica dei builder per estendibilità.
"""

from typing import Dict, Type, Any, Union
from functools import lru_cache
import logging

from structum_lab.plugins.dynaconf.core.director import ConfigDirector
from structum_lab.plugins.dynaconf.core.exceptions import ConfigurationError
from structum_lab.plugins.dynaconf.core.builders import AbstractConfigBuilder

log = logging.getLogger(__name__)


[docs] class ConfigManager: """Gestisce il caricamento, il caching e l'accesso alle configurazioni."""
[docs] def __init__(self) -> None: # Registro dinamico: nome -> Classe Builder o Istanza Builder self._builders: Dict[ str, Union[Type[AbstractConfigBuilder], AbstractConfigBuilder] ] = {}
[docs] def register_builder( self, name: str, builder: Union[Type[AbstractConfigBuilder], AbstractConfigBuilder], ) -> None: """Registra un nuovo builder di configurazione.""" if name in self._builders: log.warning(f"Overwriting builder for configuration '{name}'") self._builders[name] = builder builder_name = ( builder.__name__ if isinstance(builder, type) else builder.__class__.__name__ ) log.debug(f"Registered builder: {name} -> {builder_name}")
[docs] def load_all(self) -> None: """Carica forzatamente tutte le configurazioni registrate.""" log.info("Forcing load of all registered configurations...") # Puliamo la cache prima di ricaricare self.refresh() for config_name in self._builders: try: self.get_config(config_name) except Exception as e: log.error(f"Failed to load configuration '{config_name}': {e}") log.info("All configurations loaded.")
[docs] @lru_cache(maxsize=None) def get_config(self, config_name: str) -> Any: """Recupera una configurazione specifica con caching lazy.""" if config_name not in self._builders: log.error(f"Unsupported configuration name requested: '{config_name}'") raise ConfigurationError( f"Configuration '{config_name}' is not registered." ) # Ottieni builder (classe o istanza) builder_or_cls = self._builders[config_name] # Se è una classe, istanziala. Se è un'istanza, usala direttamente. if isinstance(builder_or_cls, type): builder_instance = builder_or_cls() else: builder_instance = builder_or_cls # Orchestra la costruzione usando il Director log.debug(f"Building configuration '{config_name}'...") config = ConfigDirector.construct(builder_instance) return config
[docs] def refresh(self) -> None: """Invalida la cache interna.""" self.get_config.cache_clear() log.info("Configuration cache cleared.")