dynaconf

repository·master·Indexed 26 days ago

https://github.com/dynaconf/dynaconf

A dynamic configuration management library for Python inspired by the 12-factor app methodology. It supports multiple file formats, environment variable overrides, layered environments, and secret management via files or external services like Hashicorp Vault. Features include dot notation access, custom loaders, post-hooks for conditional loading, and tools for inspecting settings loading history.

Tokens
33.6K
Snippets
97
Records
212
Agent score
87%

What's inside dynaconf

  1. Overview of Dynaconf Features

    master

    Dynaconf is a configuration management library for Python inspired by the 12-factor app methodology. Key features include:

    • Settings management: Handles default values, validation, parsing, and templating.
    • Sensitive information protection: Built-in mechanisms to protect passwords and tokens.
    • Multiple file formats: Supports toml, yaml, json, ini, and py, with support for custom loaders.
    • Environment variable support: Allows overriding settings via environment variables (including .env file support).
    • Multi-environment support: A layered system for managing different profiles such as [default, development, testing, production].
    • External storage integration: Built-in support for Hashicorp Vault and Redis.
    • Framework extensions: Official extensions for Django and Flask.
    • CLI tool: Provides commands for init, list, write, validate, and export.
  2. Configure Dynaconf for Pytest using FORCE_ENV_FOR_DYNACONF

    master

    When using pytest, it is recommended to use the FORCE_ENV_FOR_DYNACONF environment variable (or configuration option) instead of ENV_FOR_DYNACONF because it has higher precedence. This ensures your test environment settings are strictly applied.

    You can use a pytest fixture with autouse=True to force the global settings object into the testing environment for the entire session.

    import pytest
    from dynaconf import settings
    
    @pytest.fixture(scope="session", autouse=True)
    def set_test_settings():
        settings.configure(FORCE_ENV_FOR_DYNACONF="testing")
  3. Define settings using environment variables

    master

    Dynaconf prioritizes environment variables. By default, it looks for variables prefixed with DYNACONF_. You can customize this prefix using the envvar_prefix argument in the Dynaconf constructor.

    Key features:

    • Automatic Type Casting: Variables like DYNACONF_NUMBER=123 are automatically cast to int. Booleans (e.g., true) and lists (e.g., "['a', 'b']") are also supported.
    • Nested Settings: Use double underscores (__) to denote nesting. For example, DYNACONF_NESTED__LEVEL__KEY=1 creates {'nested': {'level': {'key': 1}}}.
    • Framework Prefixes: If using extensions, DJANGO_ and FLASK_ prefixes are automatically recognized.
    • Custom Prefixes: If you initialize with Dynaconf(envvar_prefix="custom"), use CUSTOM_NAME=value.
  4. Insert values into specific list positions with @insert

    master

    The @insert token allows you to insert a value at a specific index in a list.

    Syntax: KEY = '@insert [index] value'

    Details:

    • If the index is omitted, the value is inserted at index 0.
    • Supports signed indexes (e.g., -1 to insert at the end of the list).
    • For inserting dictionaries into a list of dictionaries, use TOML format or the @json token.
  5. Integrate Dynaconf with Django using the Django Extension

    master

    The Django Extension gives Dynaconf full control over django.conf.settings. By using DjangoDynaconf, every time you import django.conf.settings anywhere in your project, you are interacting with a Dynaconf instance. This grants you access to all advanced Dynaconf features.

    Setup: Append the DjangoDynaconf initialization to the very bottom of your settings.py file.

    # ... standard Django settings (DEBUG, etc.) ...
    
    # AT THE VERY BOTTOM of settings.py
    import dynaconf
    
    validators = [
        dynaconf.Validator("INSTALLED_APPS", cont="mynew.app"),
        dynaconf.Validator("DEBUG", ne=True, env="production"),
    ]
    
    settings = dynaconf.DjangoDynaconf(
        __name__,
        settings_files=["/etc/myapp/settings.toml"],
        validators=validators,
    )
  6. Use layered environments in settings files

    master

    To use layered environments (e.g., [default], [development], [production]), you must set environments=True when instantiating Dynaconf.

    Without this flag, Dynaconf treats sections as normal first-level keys.

    To switch between environments, set the ENV_FOR_DYNACONF environment variable. For Flask/Django extensions, use FLASK_ENV or DJANGO_ENV respectively. You can also pass env="environment_name" directly to the Dynaconf constructor.

    # config.py
    settings = Dynaconf(environments=True)
    # settings.toml
    [default]
    name = ""
    [development]
    name = "developer"
    [production]
    name = "admin"
    # Switch to development
    export ENV_FOR_DYNACONF=development
    # settings.name will be "developer"
  7. Load settings from files

    master

    You can specify which files Dynaconf should load using the settings_files argument in the Dynaconf constructor or via environment variables.

    Dynaconf searches for files starting from the directory of your entry point python file, moving up through parent directories (including /config subdirectories).

    Key behaviors:

    • root_path: If defined, Dynaconf starts searching from this path (relative to cwd).
    • Absolute paths: Supported and loaded directly.
    • Local overrides: For every file in settings_files, Dynaconf automatically looks for a .local version (e.g., settings.toml triggers a search for settings.local.toml).
    • Globs: Pattern matching (e.g., *.yaml) is supported.
    # Using explicit file list
    settings = Dynaconf(settings_files=["settings.toml", "*.yaml"])
    
    # Using root_path
    settings = Dynaconf(
        root_path="my/project/root",
        settings_files=["settings.toml", "*.yaml"]
    )
    # Using environment variables
    export ROOT_PATH_FOR_DYNACONF='my/project/root'
    export SETTINGS_FILES_FOR_DYNACONF='["settings.toml", "*.yaml"]'
  8. Validate settings on instantiation

    master

    When you pass a list of validators to the Dynaconf constructor, they are not run immediately. They are triggered lazily when you first attempt to access a setting, call settings.validators, or call settings.as_dict(). Only the first ValidationError encountered will be raised.

    from dynaconf import Dynaconf, Validator
    
    settings = Dynaconf(
        settings_file=["settings.toml"],
        environments=True,
        validators=[
            Validator("AGE", lte=30, gte=10),
            Validator("NAME", eq="John"),
        ],
    )
    
    # Accessing settings triggers validation
    print(settings.age)
  9. Initialize the FlaskDynaconf extension

    master

    Dynaconf provides a drop-in replacement for Flask's app.config. You can initialize the FlaskDynaconf extension by passing your Flask app instance to it. This turns app.config into a dynaconf instance.

    from flask import Flask
    from dynaconf import FlaskDynaconf
    
    app = Flask(__name__)
    FlaskDynaconf(app)
  10. Manage settings files and environments in Flask

    master

    Place settings.toml and .secrets.toml in your project root (where you run flask run). Define environments using TOML sections like [default], [development], and [production].

    Use the FLASK_ENV environment variable to switch between environments:

    • FLASK_ENV=development
    • FLASK_ENV=production

    Note: If using the dynaconf CLI, the FLASK_APP environment variable must be defined.

  11. Initialize Dynaconf with custom variables and formats

    master

    When running dynaconf init, you can specify the file format, the project path, and pre-populate settings and secrets.

    Options:

    • -f, --format [ini|toml|yaml|json|py|env]: Set the file format.
    • -p, --path TEXT: Specify the project root directory (defaults to current directory).
    • -v, --vars TEXT: Key-value pairs to write to settings.toml (e.g., NAME=foo).
    • -s, --secrets TEXT: Key-value pairs to write to .secrets.toml (e.g., TOKEN=1234).
    • --django TEXT: Django-specific initialization.
  12. Validate only the current environment

    master

    By default, settings.validators.validate() runs all validators for all environments defined in them. If you want to skip validators that belong to environments other than the one currently active, use the only_current_env parameter or the validate_only_current_env configuration.

    This is useful when certain settings (like production API keys) are only required in specific environments and you don't want validation to fail during local development.

    from dynaconf import Dynaconf, Validator
    
    settings = Dynaconf(
        settings_files=['setting.toml', '.secrets.toml'],
        environments=True,
        # If current_env is 'development', validators for 'production' are skipped
        validate_only_current_env=True,
        validators=[
            Validator('VERSION', 'NAME', 'SERVERS', env=['development', 'production'], must_exist=True),
            Validator("SERVERS", env='development', cont='localhost'),
            Validator('API_KEY', env='production', must_exist=True),
        ]
    )