interpolation.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. from __future__ import absolute_import
  2. from __future__ import unicode_literals
  3. import logging
  4. import os
  5. from string import Template
  6. import six
  7. from .errors import ConfigurationError
  8. log = logging.getLogger(__name__)
  9. def interpolate_environment_variables(service_dicts):
  10. mapping = BlankDefaultDict(os.environ)
  11. return dict(
  12. (service_name, process_service(service_name, service_dict, mapping))
  13. for (service_name, service_dict) in service_dicts.items()
  14. )
  15. def process_service(service_name, service_dict, mapping):
  16. return dict(
  17. (key, interpolate_value(service_name, key, val, mapping))
  18. for (key, val) in service_dict.items()
  19. )
  20. def interpolate_value(service_name, config_key, value, mapping):
  21. try:
  22. return recursive_interpolate(value, mapping)
  23. except InvalidInterpolation as e:
  24. raise ConfigurationError(
  25. 'Invalid interpolation format for "{config_key}" option '
  26. 'in service "{service_name}": "{string}"'
  27. .format(
  28. config_key=config_key,
  29. service_name=service_name,
  30. string=e.string,
  31. )
  32. )
  33. def recursive_interpolate(obj, mapping):
  34. if isinstance(obj, six.string_types):
  35. return interpolate(obj, mapping)
  36. elif isinstance(obj, dict):
  37. return dict(
  38. (key, recursive_interpolate(val, mapping))
  39. for (key, val) in obj.items()
  40. )
  41. elif isinstance(obj, list):
  42. return [recursive_interpolate(val, mapping) for val in obj]
  43. else:
  44. return obj
  45. def interpolate(string, mapping):
  46. try:
  47. return Template(string).substitute(mapping)
  48. except ValueError:
  49. raise InvalidInterpolation(string)
  50. class BlankDefaultDict(dict):
  51. def __init__(self, *args, **kwargs):
  52. super(BlankDefaultDict, self).__init__(*args, **kwargs)
  53. self.missing_keys = []
  54. def __getitem__(self, key):
  55. try:
  56. return super(BlankDefaultDict, self).__getitem__(key)
  57. except KeyError:
  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. class InvalidInterpolation(Exception):
  66. def __init__(self, string):
  67. self.string = string