Core Config Protocols

Structum Configuration Subsystem.

This module exposes the Public API for configuration management. It adheres to the Stable Facade Principle (DP-1): application code imports from here (structum.config) and is decoupled from the underlying provider (JSON, Dynaconf, Database, etc.).

All code should interact with configuration via the aliases provided here.

Example

from structum.config import get_config

cfg = get_config() cfg.set(“app.mode”, “production”)

structum.config.ConfigInterface

alias of ConfigProviderInterface

structum.config.get_config() ConfigProviderInterface

Returns the global configuration provider (Lazy Loading & Dynamic).

Architectural Role: Singleton Accessor.

If no provider handles been registered, it automatically instantiates the Fallback JSON Provider (Principle of Operational Continuity). This ensures the application works out-of-the-box without setup.

Returns:

The active configuration provider.

Return type:

ConfigInterface

structum.config.set_config_provider(provider: ConfigProviderInterface | type[ConfigProviderInterface]) None[source]

Registers a custom configuration provider.

Architectural Role: Dependency Injection Root.

This function is typically called by a plugin (e.g., structum-dynaconf) during the bootstrap phase. The registered provider globally replaces the default one, seamlessly upgrading the application capabilities.

Parameters:
provider: ConfigProviderInterface | type[ConfigProviderInterface]

Instance or Class of a provider conforming to ConfigInterface.

class structum.config.JSONConfigProvider[source]

Bases: object

Provider di configurazione basato su file JSON.

Caratteristiche: - Persistenza automatica su filesystem - Supporto a chiavi annidate tramite dot notation - Nessuna dipendenza esterna

__init__()[source]

Initialize the JSON configuration provider.

Creates the configuration directory if needed and loads existing configuration from the JSON file.

get(key: str, default: Any = None) Any[source]

Restituisce il valore associato a una chiave (dot notation supportata).

has(key: str) bool[source]

Verifica l’esistenza di una chiave di configurazione.

reload() None[source]

Ricarica la configurazione dal file JSON gestendo errori di corruzione.

save() None[source]

Scrive la configurazione corrente su file JSON.

set(key: str, value: Any) None[source]

Imposta una chiave di configurazione e salva immediatamente su disco.

Interfaces

Structum Configuration Interface.

This module defines the Formal Contract (Protocol) that all configuration providers must respect. The Structum core depends exclusively on this interface (Dependency Inversion), not on concrete implementations.

Architectural Role: - Decoupling: Application code knows ConfigProviderInterface, not Dynaconf. - Extensibility: Plugins (Dynaconf, Vault, Etcd) register themselves at bootstrap.

class structum.config.interface.ConfigProviderInterface(*args, **kwargs)[source]

Bases: Protocol

Protocol defining the interface for configuration providers.

This interface uses typing.Protocol to enable duck typing: explicit inheritance is not required. Any object implementing these methods with compatible signatures is considered a valid provider.

This approach maximizes flexibility and reduces coupling between core and plugins.

Implementations:

Example

Using a configuration provider:

from structum.config import get_config_provider

config = get_config_provider()

# Get value with fallback
db_host = config.get("database.host", default="localhost")

# Set value
config.set[Any]("database.port", 5432)

# Check existence
if config.has("database.password"):
    password = config.get("database.password")

# Persist changes
config.save()

Note

All providers should be thread-safe and support hierarchical key access using dot-notation (e.g., “database.pool.size”).

See also

get_config_provider(): Retrieve the global configuration provider set_config_provider(): Register a custom provider

get(key: str, default: Any = None) Any[source]

Retrieve a configuration value by key.

Supports dot-notation for nested configuration values (e.g., “database.pool.size” accesses nested dictionaries).

Parameters:
key : str

Configuration key to retrieve. Supports dot-notation for hierarchical access.

default : Any, optional

Fallback value if key doesn’t exist. Defaults to None.

Returns:

The configuration value, or default if key not found.

Return type:

Any

Raises:

KeyError – If key not found and default not provided (implementation-specific behavior).

Example

Retrieving nested configuration:

# Config: {"database": {"host": "localhost", "port": 5432}}
host = config.get("database.host")  # "localhost"
port = config.get("database.port")  # 5432

# With fallback
timeout = config.get("database.timeout", 30)  # 30

See also

set[Any](): Set a configuration value has(): Check if a key exists

set(key: str, value: Any) None[source]

Set a configuration value.

Persistence behavior depends on the concrete provider implementation. Changes may be in-memory only until save() is called.

Parameters:
key : str

Configuration key to set[Any]. Supports dot-notation to create nested structures.

value : Any

Value to associate with the key. Can be any JSON-serializable type.

Example

Setting configuration values:

# Simple value
config.set[Any]("app.debug", True)

# Nested structure (creates intermediate dicts)
config.set[Any]("database.pool.size", 10)

# Complex value
config.set[Any]("servers", ["srv1", "srv2", "srv3"])

Warning

Changes are not persisted to storage until save() is called (for file-based providers). In-memory providers lose changes on restart.

See also

get(): Retrieve a configuration value save(): Persist changes to storage

has(key: str) bool[source]

Check if a configuration key exists.

Parameters:
key : str

Configuration key to check. Supports dot-notation.

Returns:

True if the key exists, False otherwise.

Return type:

bool

Example

Checking key existence:

if config.has("database.password"):
    password = config.get("database.password")
else:
    raise ValueError("Database password not configured")

Note

A key can exist with a None value. Use get() to distinguish between missing keys and None values.

save() None[source]

Persist configuration changes to underlying storage.

For file-based providers, writes changes to disk. For remote providers, may trigger a commit or synchronization. For in-memory providers, this may be a no-op.

Raises:
  • IOError – If unable to write to storage (file permissions, disk full).

  • RuntimeError – If provider doesn’t support persistence.

Example

Saving configuration:

config.set[Any]("app.version", "2.0.0")
config.set[Any]("app.build", 123)
config.save()  # Persist both changes

Warning

Unsaved changes will be lost on process termination. Call save() periodically for critical configuration updates.

See also

reload(): Discard changes and reload from storage

reload() None[source]

Reload configuration from persistent storage.

Discards all unsaved in-memory changes and reloads the configuration from the underlying storage source.

Raises:

IOError – If unable to read from storage.

Example

Reloading configuration:

config.set[Any]("temp.value", 123)  # In-memory change
config.reload()  # Discards temp.value

# Now config reflects disk state
assert not config.has("temp.value")

Warning

All unsaved changes will be permanently lost. Consider calling save() before reload if needed.

See also

save(): Persist changes before reloading

__init__(*args, **kwargs)
structum.config.interface.get_config_provider() ConfigProviderInterface[source]

Returns the global configuration provider (Lazy Loading & Dynamic).

Architectural Role: Singleton Accessor.

If no provider handles been registered, it automatically instantiates the Fallback JSON Provider (Principle of Operational Continuity). This ensures the application works out-of-the-box without setup.

Returns:

The active configuration provider.

Return type:

ConfigInterface

structum.config.interface.set_config_provider(provider: ConfigProviderInterface | type[ConfigProviderInterface]) None[source]

Registers a custom configuration provider.

Architectural Role: Dependency Injection Root.

This function is typically called by a plugin (e.g., structum-dynaconf) during the bootstrap phase. The registered provider globally replaces the default one, seamlessly upgrading the application capabilities.

Parameters:
provider: ConfigProviderInterface | type[ConfigProviderInterface]

Instance or Class of a provider conforming to ConfigInterface.

Manager

Provider di configurazione JSON per Structum.

Questa implementazione rappresenta il fallback minimale basato esclusivamente sulla standard library Python. È pensata per garantire un funzionamento immediato del framework in assenza di plugin avanzati.

Per casi d’uso complessi (multi-source, validazione, override per ambiente) si raccomanda l’uso di provider esterni come Dynaconf.

class structum.config.manager.JSONConfigProvider[source]

Bases: object

Provider di configurazione basato su file JSON.

Caratteristiche: - Persistenza automatica su filesystem - Supporto a chiavi annidate tramite dot notation - Nessuna dipendenza esterna

__init__()[source]

Initialize the JSON configuration provider.

Creates the configuration directory if needed and loads existing configuration from the JSON file.

get(key: str, default: Any = None) Any[source]

Restituisce il valore associato a una chiave (dot notation supportata).

set(key: str, value: Any) None[source]

Imposta una chiave di configurazione e salva immediatamente su disco.

has(key: str) bool[source]

Verifica l’esistenza di una chiave di configurazione.

save() None[source]

Scrive la configurazione corrente su file JSON.

reload() None[source]

Ricarica la configurazione dal file JSON gestendo errori di corruzione.