interpolation.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. from __future__ import absolute_import
  2. from __future__ import unicode_literals
  3. import logging
  4. from string import Template
  5. import six
  6. from .errors import ConfigurationError
  7. log = logging.getLogger(__name__)
  8. def interpolate_environment_variables(config, section, environment):
  9. def process_item(name, config_dict):
  10. return dict(
  11. (key, interpolate_value(name, key, val, section, environment))
  12. for key, val in (config_dict or {}).items()
  13. )
  14. return dict(
  15. (name, process_item(name, config_dict or {}))
  16. for name, config_dict in config.items()
  17. )
  18. def interpolate_value(name, config_key, value, section, mapping):
  19. try:
  20. return recursive_interpolate(value, mapping)
  21. except InvalidInterpolation as e:
  22. raise ConfigurationError(
  23. 'Invalid interpolation format for "{config_key}" option '
  24. 'in {section} "{name}": "{string}"'.format(
  25. config_key=config_key,
  26. name=name,
  27. section=section,
  28. string=e.string))
  29. def recursive_interpolate(obj, mapping):
  30. if isinstance(obj, six.string_types):
  31. return interpolate(obj, mapping)
  32. elif isinstance(obj, dict):
  33. return dict(
  34. (key, recursive_interpolate(val, mapping))
  35. for (key, val) in obj.items()
  36. )
  37. elif isinstance(obj, list):
  38. return [recursive_interpolate(val, mapping) for val in obj]
  39. else:
  40. return obj
  41. def interpolate(string, mapping):
  42. try:
  43. return Template(string).substitute(mapping)
  44. except ValueError:
  45. raise InvalidInterpolation(string)
  46. class InvalidInterpolation(Exception):
  47. def __init__(self, string):
  48. self.string = string