Configuration

SPLENT provides a layered configuration system designed for modular applications. Configuration can be defined and extended at three different levels:

  1. Product configuration
  2. Feature configuration
  3. Service initialization

Each level has a different responsibility.


Table of contents

  1. Product configuration
    1. Example structure
    2. Example
  2. Feature configuration
    1. Example structure
    2. Example implementation
  3. Service initialization
  4. Configuration hierarchy

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:

  1. SPLENT reads SPLENT_APP.
  2. The module <product>.config is imported.
  3. The configuration class is selected based on FLASK_ENV.
  4. All configuration values are injected into app.config.

Typical configuration classes are:

  • DevelopmentConfig
  • ProductionConfig
  • TestingConfig

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:

  1. Framework default configuration
  2. Product configuration (<product>/config.py)
  3. Feature configuration (<feature>/config.py)
  4. Service initialization (service.init_app())

This layered approach keeps SPLENT modular while allowing products, features, and services to configure the components they require.