Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support to override os.environ to allow for better envfile-chaining and other advanced use #352

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

johnbergvall
Copy link

@johnbergvall johnbergvall commented Aug 13, 2021

There are some closed tickets regarding loading multiple env-files, like #73 #246 #257, most issues which can be implemented using dotenv_values as described in comments and README

There are still some cases that I keep running in to that would be solved by this pull request, mostly regarding preparing environments/doing health checks for docker deployment and docker-compose-files, to be used as env-parameter to subprocess-calls for tools without envfile-support or serialized to some YAML-file to be used by other tools.

One example is when auto-deploying feature-branches to test environments which is composed by some server-wide settings /etc/env.server, one .env.[productname] for base product settings and one .env.[deployment] which contain some optional final overrides for that specific featurebranch/customer/user provided settings, all coming from different sources.

Right now you have to normalize newlines and create a StringIO(server_settings + deployment_settings + product_settings + deployment_settings) to have interpolation working correctly, and also clear the os.environ in the local process during the dotenv_values-call to avoid conflicting options in the running enviroment. If there are some values that are generated in the program you also have to serialize them before use.

By allowing to replace os.environ with a custom dict you can use dotenv_values with a clean environment for safe use both with or without threads, provide fallback/override values from python and chain multiple .env-files and still have functioning interpolation between multiple env-files. It's also possible to compare the resulting values without mocking os.environ in unit tests.

Example usage as added to README:

import os
import subprocess
from dotenv import dotenv_values

deploy_env = {
  'FALLBACK_DOMAIN': 'example.org',
  'VERSION': '1.5',
}
env = dotenv_values('.env.deployment01', base_env={
    # override=False to ignore local file overrides in interpolations
    **dotenv_values('.env.base', override=False, base_env=deploy_env),
    **deploy_env,
})
subprocess.call(
  ['/usr/bin/docker', 'stack', 'deploy', '-c', 'docker-compose.yml', 'myproject'],
  env={**deploy_env, **env},
)

I started working on an implementation for chained loading in the cli and the helper methods, but felt that it was too out of scope for this project and that these additions alone would open up for project specific implementations without monkeypatching.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant