File: //usr/lib/python3/dist-packages/compose/config/environment.py
import logging
import os
import re
import dotenv
from ..const import IS_WINDOWS_PLATFORM
from .errors import ConfigurationError
from .errors import EnvFileNotFound
log = logging.getLogger(__name__)
def split_env(env):
if isinstance(env, bytes):
env = env.decode('utf-8', 'replace')
key = value = None
if '=' in env:
key, value = env.split('=', 1)
else:
key = env
if re.search(r'\s', key):
raise ConfigurationError(
"environment variable name '{}' may not contain whitespace.".format(key)
)
return key, value
def env_vars_from_file(filename, interpolate=True):
"""
Read in a line delimited file of environment variables.
"""
if not os.path.exists(filename):
raise EnvFileNotFound("Couldn't find env file: {}".format(filename))
elif not os.path.isfile(filename):
raise EnvFileNotFound("{} is not a file.".format(filename))
env = dotenv.dotenv_values(dotenv_path=filename, encoding='utf-8-sig', interpolate=interpolate)
for k, v in env.items():
env[k] = v if interpolate else v.replace('$', '$$')
return env
class Environment(dict):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.missing_keys = []
self.silent = False
@classmethod
def from_env_file(cls, base_dir, env_file=None):
def _initialize():
result = cls()
if base_dir is None:
return result
if env_file:
env_file_path = os.path.join(os.getcwd(), env_file)
return cls(env_vars_from_file(env_file_path))
env_file_path = os.path.join(base_dir, '.env')
try:
return cls(env_vars_from_file(env_file_path))
except EnvFileNotFound:
pass
return result
instance = _initialize()
instance.update(os.environ)
return instance
@classmethod
def from_command_line(cls, parsed_env_opts):
result = cls()
for k, v in parsed_env_opts.items():
# Values from the command line take priority, unless they're unset
# in which case they take the value from the system's environment
if v is None and k in os.environ:
result[k] = os.environ[k]
else:
result[k] = v
return result
def __getitem__(self, key):
try:
return super().__getitem__(key)
except KeyError:
if IS_WINDOWS_PLATFORM:
try:
return super().__getitem__(key.upper())
except KeyError:
pass
if not self.silent and key not in self.missing_keys:
log.warning(
"The {} variable is not set. Defaulting to a blank string."
.format(key)
)
self.missing_keys.append(key)
return ""
def __contains__(self, key):
result = super().__contains__(key)
if IS_WINDOWS_PLATFORM:
return (
result or super().__contains__(key.upper())
)
return result
def get(self, key, *args, **kwargs):
if IS_WINDOWS_PLATFORM:
return super().get(
key,
super().get(key.upper(), *args, **kwargs)
)
return super().get(key, *args, **kwargs)
def get_boolean(self, key, default=False):
# Convert a value to a boolean using "common sense" rules.
# Unset, empty, "0" and "false" (i-case) yield False.
# All other values yield True.
value = self.get(key)
if not value:
return default
if value.lower() in ['0', 'false']:
return False
return True