Configuration
SPLENT provides a layered configuration system designed for modular applications. Configuration can be defined and extended at three different levels:
- Product configuration
- Feature configuration
- Service initialization
Each level has a different responsibility.
Table of contents
Product configuration
Every SPLENT product can define its own configuration in:
<product>/config.py
At application startup, the framework loads this configuration through the ConfigManager.
The active product is determined by the environment variable:
SPLENT_APP
The loading process works as follows:
- SPLENT reads
SPLENT_APP. - The module
<product>.configis imported. - The configuration class is selected based on
FLASK_ENV. - All configuration values are injected into
app.config.
Typical configuration classes are:
DevelopmentConfigProductionConfigTestingConfig
Example structure
sample_splent_app/
config.py
Example
class DevelopmentConfig(BaseConfig):
DEBUG = True
TEMPLATES_AUTO_RELOAD = True
def __init__(self):
super().__init__()
self.SQLALCHEMY_DATABASE_URI = (
f"mysql+pymysql://{os.getenv('MARIADB_USER', 'default_user')}:"
f"{os.getenv('MARIADB_PASSWORD', 'default_password')}@"
f"{os.getenv('MARIADB_HOSTNAME', 'localhost')}:3306/"
f"{os.getenv('MARIADB_DATABASE', 'default_test_db')}"
)
During startup, the ConfigManager loads the appropriate configuration class based on the FLASK_ENV environment variable and injects the values into app.config.
If a product does not provide a config.py, SPLENT falls back to the default configuration defined in the framework.
Feature configuration
In addition to the product configuration, features can optionally inject additional configuration into the application.
This is done by defining a config.py file inside the feature module.
Example structure
features/
splent_feature_redis/
config.py
Example implementation
import os
import redis
def inject_config(app):
redis_url = os.getenv("REDIS_URL", "redis://redis:6379")
app.config.update({
"SESSION_TYPE": "redis",
"SESSION_PERMANENT": False,
"REDIS_URL": redis_url,
"SESSION_REDIS": redis.from_url(redis_url)
})
The function inject_config(app) receives the Flask application instance and can modify app.config.
Service initialization
Services may also initialize their own dependencies using the application configuration.
This is typically done through an init_app() method.
Unlike config.py, which only defines configuration values, services use init_app() to consume configuration and initialize runtime components such as clients, connections, or extensions.
Example of services.py in splent_feature_mail:
class MailService(BaseService):
def __init__(self):
super().__init__(MailRepository())
self.mail = None
self.sender = None
def init_app(self, app):
app.config["MAIL_SERVER"] = os.getenv(
"MAIL_SERVER", "smtp.example.com"
)
app.config["MAIL_PORT"] = int(os.getenv("MAIL_PORT", "587"))
app.config["MAIL_USE_TLS"] = (
os.getenv("MAIL_USE_TLS", "True") == "True"
)
app.config["MAIL_USE_SSL"] = (
os.getenv("MAIL_USE_SSL", "False") == "True"
)
app.config["MAIL_USERNAME"] = os.getenv(
"MAIL_USERNAME", "your-email@your-domain.com"
)
app.config["MAIL_PASSWORD"] = os.getenv("MAIL_PASSWORD", "your_password")
app.config["MAIL_DEFAULT_SENDER"] = os.getenv("MAIL_USERNAME")
self.mail = Mail(app)
self.sender = app.config["MAIL_USERNAME"]
In this case the service:
- Reads environment variables
- Updates the Flask configuration
- Initializes the mail client (
flask_mail.Mail) - Stores references needed during execution
Configuration hierarchy
Configuration is applied in the following order:
- Framework default configuration
- Product configuration (
<product>/config.py) - Feature configuration (
<feature>/config.py) - Service initialization (
service.init_app())
This layered approach keeps SPLENT modular while allowing products, features, and services to configure the components they require.