Skip to content

Instantly share code, notes, and snippets.

@davehughes
Last active December 29, 2015 20:18
Show Gist options
  • Save davehughes/7722532 to your computer and use it in GitHub Desktop.
Save davehughes/7722532 to your computer and use it in GitHub Desktop.
Utility object for expanding a dict of configuration template strings
class ConfigResolver(object):
def __init__(self, **kwargs):
self.config_templates = kwargs
self.config = resolve(copy.copy(kwargs))
def __getattr__(self, attr):
return self.config[attr]
def __getitem__(self, item):
return self.config[item]
def __unicode__(self):
return unicode(self.config)
def resolve(config_templates, initial_config=None):
config = initial_config or {}
while True:
error_keys = set()
resolved_one_or_more = False
for name, template in config_templates.items():
try:
config[name] = template.format(**config)
del config_templates[name]
resolved_one_or_more = True
except KeyError as e:
error_keys.add(e.message)
if len(config_templates) == 0:
break
if not resolved_one_or_more:
raise Exception('Failed to resolve all references')
return config

Basic configuration

The basic resolution mechanism just loops over a dict's key/value pairs, tries to fill in their format strings using the established configuration, and catches errors to retry in a later round of resolution:

template_dict = {
  'app_root': '/usr/local/myapp',
  'log': '{app_root}/logs',
  'uwsgi_log': '{log}/uwsgi.log',
  'deploy': '{app_root}/.deploy/{commit_sha}',
  'version_src': '{deploy}/src',
  'src_link': '{app_root}/src',
  'version_env': '{deploy}/env',
  'env_link': '{app_root}/env',
  'commit_sha': 'a1b2c3',
}

resolve(template_dict)
>>> {
  'app_root': '/usr/local/myapp',
  'log': '/usr/local/myapp/logs',
  'uwsgi_log': '/usr/local/myapp/logs/uwsgi.log',
  'deploy': '/usr/local/myapp/.deploy/a1b2c3',
  'version_src': '/usr/local/myapp/.deploy/a1b2c3/src',
  'src_link': '/usr/local/myapp/src',
  'version_env': '/usr/local/myapp/.deploy/a1b2c3/env',
  'env_link': '/usr/local/myapp/env',
  'commit_sha': 'a1b2c3',
}

Configuration object

The configuration wrapper object provides both attr- and item-based lookups on the resolved configuration, and takes **kwargs rather than a dict as configuration:

config = ConfigResolver(template_dict)
 
#  or, equivalently...
config = ConfigResolver(
  app_root='/usr/local/myapp',
  log='{app_root}/logs',
  uwsgi_log='{log}/uwsgi.log',
  deploy='{app_root}/.deploy/{commit_sha}',
  version_src='{deploy}/src',
  src_link='{app_root}/src',
  version_env='{deploy}/env',
  env_link='{app_root}/env',
  commit_sha='a1b2c3',
)

config['version_src']
>>> '/usr/local/myapp/.deploy/a1b2c3'

config.uwsgi_log
>>> '/usr/local/myapp/logs/uwsgi.log'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment