environment.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. from __future__ import absolute_import
  2. from __future__ import unicode_literals
  3. import codecs
  4. import logging
  5. import os
  6. import six
  7. from ..const import IS_WINDOWS_PLATFORM
  8. from .errors import ConfigurationError
  9. log = logging.getLogger(__name__)
  10. def split_env(env):
  11. if isinstance(env, six.binary_type):
  12. env = env.decode('utf-8', 'replace')
  13. if '=' in env:
  14. return env.split('=', 1)
  15. else:
  16. return env, None
  17. def env_vars_from_file(filename):
  18. """
  19. Read in a line delimited file of environment variables.
  20. """
  21. if not os.path.exists(filename):
  22. raise ConfigurationError("Couldn't find env file: %s" % filename)
  23. env = {}
  24. for line in codecs.open(filename, 'r', 'utf-8'):
  25. line = line.strip()
  26. if line and not line.startswith('#'):
  27. k, v = split_env(line)
  28. env[k] = v
  29. return env
  30. class Environment(dict):
  31. def __init__(self, *args, **kwargs):
  32. super(Environment, self).__init__(*args, **kwargs)
  33. self.missing_keys = []
  34. @classmethod
  35. def from_env_file(cls, base_dir):
  36. def _initialize():
  37. result = cls()
  38. if base_dir is None:
  39. return result
  40. env_file_path = os.path.join(base_dir, '.env')
  41. try:
  42. return cls(env_vars_from_file(env_file_path))
  43. except ConfigurationError:
  44. pass
  45. return result
  46. instance = _initialize()
  47. instance.update(os.environ)
  48. return instance
  49. def __getitem__(self, key):
  50. try:
  51. return super(Environment, self).__getitem__(key)
  52. except KeyError:
  53. if IS_WINDOWS_PLATFORM:
  54. try:
  55. return super(Environment, self).__getitem__(key.upper())
  56. except KeyError:
  57. pass
  58. if key not in self.missing_keys:
  59. log.warn(
  60. "The {} variable is not set. Defaulting to a blank string."
  61. .format(key)
  62. )
  63. self.missing_keys.append(key)
  64. return ""
  65. def __contains__(self, key):
  66. result = super(Environment, self).__contains__(key)
  67. if IS_WINDOWS_PLATFORM:
  68. return (
  69. result or super(Environment, self).__contains__(key.upper())
  70. )
  71. return result
  72. def get(self, key, *args, **kwargs):
  73. if IS_WINDOWS_PLATFORM:
  74. return super(Environment, self).get(
  75. key,
  76. super(Environment, self).get(key.upper(), *args, **kwargs)
  77. )
  78. return super(Environment, self).get(key, *args, **kwargs)