Advanced Usage

EYConf provides several advanced features to customize its behavior and integrate seamlessly into your projects.

Change Configuration File Path

To change the path of the configuration file, you can set the EYCONF_CONFIG_FILE environment variable to the desired path before creating the EYConf instance:

export EYCONF_CONFIG_FILE="/path/to/your/config.yaml"

Alternatively, you can pass override the get_file() method in a subclass of EYConf. We recommend this approach if you want to have more control over the configuration file location, this also allows you to add helper methods specific to your application configuration.

from eyconf import EYConf
class CustomConfig(EYConf):
    @staticmethod
    def get_file() -> Path:
        return Path("/path/to/your/config.yaml").expanduser().resolve()
config = CustomConfig(ConfigSchema)

Why can I not just provide a path to the constructor?

Without YAML File / Memory Only Validation

Sometimes you might want to create a configuration without creating or loading a YAML file. This is possible be using the EYConfBase base class. We still expect you to provide a schema using dataclasses.

from eyconf import EYConfBase


@dataclass
class Transport:
    """Email transport configuration"""
    host: str = 'imap.example.com'
    port: int = 993
    username: str = 'user'
    password: str = 'password'
    use_ssl: bool = False

@dataclass
class ConfigSchema:
    """My configuration schema

    Docstrings are used as comments in the generated yaml file!
    """
    transport: Transport

# Loaded from memory only
config = {
    "transport": {
        "host": "custom.example.com",
        "port": 993,
        "username": "custom_user",
        "password": "custom_password",
        "use_ssl": True,
    },
}
config = EYConfBase(data=config, schema=ConfigSchema)

Dict style access

While we do not recommend using dict style access to configuration values, as you lose type safety and autocompletion, it is still possible to access configuration values using dict style access if you really need or want to.

To do so you can either use our utility decorator @dict_access or create a __getitem__ method in your dataclass to convert your dataclass schema into a dictionary-like object:

from eyconf.utils import dict_access

@dict_access
@dataclass
class ConfigSchema:
    fortytwo: int = 42

This now allows you to access configuration values using dict style access:

from eyconf import EYConf
from eyconf.utils import DictAccess
config = EYConf(ConfigSchema)

assert isinstance(config.data, DictAccess)
print(config.data["fortytwo"])  # Outputs: 42

Warning

If you are using nested dataclasses in your configuration schema, make sure to apply the @dict_access decorator to all nested dataclasses as well. Otherwise, dict style access will not work for the nested dataclasses.

Typer integration

The eyconf.cli module provides a convenient way to create a command-line interface (CLI) for managing configuration files using the typer library. This can be particularly useful when you want to provide users with the ability to interact and modify configuration files via the terminal.

You need to install the cli additions to use this feature. You can install it using pip:

pip install eyconf[cli]

Integrating the CLI into Your Project

To integrate the CLI into your project, follow these steps:

from eyconf.cli import create_config_cli
from eyconf import EYConf
from your_project.config import ConfigSchema  # Adjust the import to your actual config schema
from your_project import app  # Adjust the import to your actual Typer app

# Your main typer app
app = typer.Typer()
sub_app = create_config_cli(EYConf, schema)
app.add_typer(sub_app, name="config")

The CLI Commands

The CLI provides several commands to manage your configuration:

 config Usage: config [OPTIONS] COMMAND [ARGS]... Manage configuration file ╭─ Options ────────────────────────────────────────────────────────────────────╮ --edit-eEdit the configuration. --helpShow this message and exit. ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Commands ───────────────────────────────────────────────────────────────────╮ ls Show the current configuration.                                         ╰──────────────────────────────────────────────────────────────────────────────╯
 config Usage: config [OPTIONS] COMMAND [ARGS]... Manage configuration file ╭─ Options ────────────────────────────────────────────────────────────────────╮ --edit-eEdit the configuration. --helpShow this message and exit. ╰──────────────────────────────────────────────────────────────────────────────╯ ╭─ Commands ───────────────────────────────────────────────────────────────────╮ ls Show the current configuration.                                         ╰──────────────────────────────────────────────────────────────────────────────╯

Annotated Docstrings

You can use Annotated from the typing module to add docstrings to individual fields in your dataclasses. These docstrings will be included as comments in the generated YAML configuration file.

from dataclasses import dataclass
from typing import Annotated

@dataclass
class Config:
    """This is a config docstring."""
    host: Annotated[str, "The host of the server"] = "localhost"
    port: Annotated[int, "The port of the server"] = 8080
    use_ssl: Annotated[bool, "Whether to use SSL", "default: false"] = False

When you generate the YAML file using EYConf, the docstrings will appear as comments:

# This is a config docstring.

# The host of the server
host: localhost
# The port of the server
port: 8080
# Whether to use SSL
# default: false
use_ssl: false