Skip to main content

Dynamic Config Class Creation using Environment Variables

Project description

LAZY_ENV_CONFIGURATOR


Github Builds codecov Language Counts Version License

A utility library for Dynamic Config class generation. Now no more repeated boilerplate code...

Before lazy_env_configurator, config classes used to be created as below.

    class BaseConfig:
        APP = os.environ.get("APP")
        APP_ENV = os.environ.get("APP_ENV")

        # authentication related configuration
        # DB Credentials
        DB_USERNAME = os.environ.get("DB_USERNAME")
        DB_PASSWORD = os.environ.get("DB_PASSWORD")
        DB_HOST = os.environ.get("DB_HOST")
        DB_PORT = os.environ.get("DB_PORT")
        DB_NAME = os.environ.get("DB_NAME")
        DB_DRIVER = os.environ.get("DB_DRIVER")

This use to require a lot of boiler plate and redundant code With lazy_env_configurator this can be reduced to below:

from lazy_env_configurator import BaseEnv, BaseConfig as Config_
class BaseConfig(BaseEnv):
    class Config(Config_):
        envs = ('APP',
        'APP_ENV',
        'DB_USERNAME',
        'DB_PASSWORD',
        'DB_PASSWORD',
        'DB_HOST',
        # defaults
        ('DB_PORT',3306),
        'DB_NAME',
        'DB_DRIVER'
        )

Benefits of using lazy_env_configurator over Normal classes


  • Low memory footprint.
  • Lazily evaluates environment variable and only loads them when used.
  • Once loaded, env variables are cached.
  • Get defaults populated, in case of missing env variables.
  • env attributes can be overridden easily.
  • classes expose instance attribute preventing need to initialization and making it behave singleton.
  • Loads .env files by default so you only need to focus on essentials.
  • Self Contained Objects if you do not want to sanatise global env variables. contained attribute.

Components


  • BaseConfig: Main Config class for library. This changes behavior of the container class.

    • envs: List or Tuple of env variable to be populated as attributes in container class. Elements of iterable can be a string or tuple with first element as attribute name and second as default, second element Defaults to None. Eg:
    class Config(Config_):
          envs = ('APP',
          'APP_ENV',
          'DB_USERNAME',
          'DB_PASSWORD',
          'DB_PASSWORD',
          'DB_HOST',
          # defaults
          ('DB_PORT',3306),
          'DB_NAME',
          'DB_DRIVER'
          )
    
    • dot_env_path: Path to .env file. This can be a string or pathlib.Path object. defaults to None. Eg:
    class Config(Config_):
          dot_env_path = Path(__file__).parent/'.env'
    
    • contained: This variable is responsible for behaviour of the container. If this is set to False, all the env variables read from .env file would be populated to os.environ and available globally. If this is set to True, environment variables would only be contained in the container itself. This would help to create configuration containers with different env settings. It contained is set to true and no .env file is present, it raises EnvWarning and fallback to Environment variables. Eg:
    class Config(BaseConfig):
          envs = ("FOO", "APP")
          dot_env_path = Path(__file__).parent / ".env.contained"
          contained = True
    
  • BaseEnv: This class will be used as a Base Class for all the containers. It uses EnvMeta as metaclass to populate env variables as attributes on Container Class. Eg:

    from lazy_env_configurator import BaseEnv, BaseConfig as Config_
    class BaseConfig(BaseEnv):
        class Config(Config_):
            envs = ('APP',
            'APP_ENV',
            'DB_USERNAME',
            'DB_PASSWORD',
            'DB_PASSWORD',
            'DB_HOST',
            # defaults
            ('DB_PORT',3306),
            'DB_NAME',
            'DB_DRIVER'
            )
    

    Note: Config class is optional. If not provided, it will not load any env variables. Config class won't be available as an attribute on the child class.

  • EnvMeta: Metaclass for populating env variables as class attributes to the child class. if the child class has a Config class, it will be used to populate the env variables.

    by default, the env variables are populated on first access and cached for subsequent access. This can be overriden by setting the value on the instance.

    if the env variable is not set, it uses the default value provided.

    This class also initializes the instance of the child class and make it available as instance attribute on the child class. So it can be accessed as ChildClass.instance.

    Example:
    
    class ABC(BaseEnv):
      def generate_uri(self):
          return f'{self.DB_HOST}:{self.DB_PORT}'
      class Config(BaseConfig):
          envs = ('dev', ('test', 'test_value'),
                  'prd', 'DB_HOST', 'DB_PORT')
          dot_env_path = Path(__file__).parent / '.env.test'
    
      >>> # access env variables
      >>> ABC.instance.dev
      >>> ABC.instance.test
      >>> ABC.instance.prd
    

How to use


Let us refer below example:

from lazy_env_configurator import BaseEnv, BaseConfig as Config_
class BaseConfig(BaseEnv):
    class Config(Config_):
        envs = ('APP',
        'APP_ENV',
        'DB_USERNAME',
        'DB_PASSWORD',
        'DB_PASSWORD',
        'DB_HOST',
        # defaults
        ('DB_PORT',3306),
        'DB_NAME',
        'DB_DRIVER'
        )

We can now use BaseConfig class create as below.

>>> BaseConfig.instance.APP

Every class, subclassed from BaseEnv would expose .instance attribute which will be instance of the subclass. This instance can be used to access all the attributes on the class.

For simplicity, metaclass pre-initialises created class, so to make it behave as singleton.

How this works ?


lazy_env_configurator uses descriptors under the hood to dynamically populate env variables as attributes, thus making them available on demand, Lazily.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lazy_env_configurator-0.2.0.tar.gz (9.4 kB view details)

Uploaded Source

Built Distribution

lazy_env_configurator-0.2.0-py3-none-any.whl (11.2 kB view details)

Uploaded Python 3

File details

Details for the file lazy_env_configurator-0.2.0.tar.gz.

File metadata

  • Download URL: lazy_env_configurator-0.2.0.tar.gz
  • Upload date:
  • Size: 9.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.4.1 CPython/3.11.1 Darwin/22.3.0

File hashes

Hashes for lazy_env_configurator-0.2.0.tar.gz
Algorithm Hash digest
SHA256 56e2f42bbdcc71352e01f6762064d5e7d89beb7fe28ccf44719d8db6046e40c0
MD5 f6cc35de23b3d443df3f193c4bcff883
BLAKE2b-256 d8d053185da290acfe756a3d0bab83edda12371faf06fcb00f8203bd50c2427a

See more details on using hashes here.

File details

Details for the file lazy_env_configurator-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for lazy_env_configurator-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ed13b25845d76046867929884cb4846b6428c35ee45df1a65c4d5bdd3b0fa477
MD5 1a022debeabbb46c8c874aa4579a5586
BLAKE2b-256 72b8fecabd44e532bc270e5adb5a4df62efd0338e9c9950fcf21344fdec306ac

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page