Usage

Defining a class

There are four ways of defining an environment variable class. The recommended way is to use the environment_variables function as a wrapper:

from environment_variables import environment_variables

@environment_variables
class Environment:
    MY_VARIABLE: str

but these can also be defined by choosing the metaclass EnvVarsMeta:

from environment_variables import EnvVarsMeta

class Environment(metaclass=EnvVarsMeta)
    MY_VARIABLE: str

as a subclass of the EnvVars class:

from environment_variables import EnvVars

class Environment(EnvVars):
    MY_VARIABLE: str

or by using the environment_variables function as a regular function:

from environment_variables import environment_variables

class Environment:
    MY_VARIABLE: str

environment = environment_variables(Environment)

Type annotations

Using type annotations, you can define what type you want your environment variable to be cast to. Casting to str, int, float and bool are trivial, but you can also define simple classes whose init functions only need one positional argument. In this case, the loaded value will be passed directly as a string to the init method as the first positional argument.

import pathlib
from environment_variables import environment_variables

@environment_variables
class Environment:
    MY_STRING: str
    MY_INTEGER: int
    MY_FLOAT: float
    MY_BOOL: bool
    MY_PATH: pathlib.Path

In the above example, if an environment variable is defined as MY_PATH=/path/to/resource, then the attribute Environment.MY_PATH will be whatever pathlib.Path('/path/to/resource') evaluates to. To annotate classes that require more than one argument, see Variable fields.

Defaults

Default values for variables can be set by assigning a value to an attribute:

from environment_variables import environment_variables

@environment_variables
class Environment:
    MY_STRING: str = 'default string'
    MY_INTEGER: int = 123

If the environment variable is not defined on the system, the default value will be returned instead. If a default value is provided, the type annotation is not even necessary, since the type of the variable will be inferred from the type of the default. If you define your class like

from environment_variables import environment_variables

@environment_variables
class Environment:
    MY_INTEGER = 123
    MY_BOOL = False

then MY_INTEGER will be an integer and MY_BOOL a boolean, regardless of the corresponding environment variables are set or not. A Python developer should not have to worry about types if it is not necessary.

Variable fields

In some cases, a type annotation is not enough to define how an attribute should behave. In that case, you can use the variable function to define how you want your attribute to be created.

from environment_variables import environment_variables, variable

@environment_variables
class Environment:
    MY_ATTRIBUTE = variable(
        MyClass,
        default='default',
        args=('some argument',),
        kwargs={'key': 'value'}
    )

This method sets MY_ATTRIBUTE to an instance of MyClass, with the first argument passed to the MyClass init method being either the value of the environment variable MY_ATTRIBUTE if it is set, or default if the variable is not set. The arguments args and kwargs are used as further arguments to the init method.

If needed, i.e. if the environment variable is not the first argument to the constructor, a factory method can be provided:

from environment_variables import environment_variables, variable

@environment_variables
class Environment:
    MY_ATTRIBUTE = variable(
        MyClass,
        default='default'
        default_factory: create_my_class
    )

This function should take the value of the environment variable or the value of default as its only argument and return an instance of MyClass and can initialize it in whatever way is desired.