Skip to content

Instantly share code, notes, and snippets.

@Klortho
Last active April 21, 2016 16:30
Show Gist options
  • Save Klortho/273335612b427fc9482a34c01e0911cb to your computer and use it in GitHub Desktop.
Save Klortho/273335612b427fc9482a34c01e0911cb to your computer and use it in GitHub Desktop.
SettingsDeferrer - one way to implement lazy settings with overrides, in Django
#!/usr/bin/env python
from os import path, getenv
import settings_deferrer as s
# Put normal settings here, if you want, or put them all into the `fill_defaults()`
# function below. If the latter, though, you'll have to use the `s.MY_SETTING` syntax.
MY_SETTING = 'zormulon'
# ...
# This function is executed later, after the overrides are brought in. It defines
# all of the *default* settings, any of which can be overridden, even if they are
# dependent on each other.
def fill_defaults():
# Here's the default for the `JIG_BASE` setting.
s.JIG_BASE = 'https://www.ncbi.nlm.nih.gov'
# Default for `JIG_VERSION` -- we'll override this
s.JIG_VERSION = '1.14.7'
# Default for computing `JIG_URL` from previously-defined settings. In a naive settings.py,
# you wouldn't be able to override JIG_VERSION in this statement -- it would use the value
# just assigned above.
# This works by proxying through getters and setters in the `s` object. This was as clean
# a syntax as I was able to come up with.
s.JIG_URL = s.JIG_BASE + '/core/jig/' + s.JIG_VERSION + '/js/jig.min.js'
# Here we override JIG_VERSION. This is where we'd use settings_overrider to get values
# from yaml or env. vars.
JIG_VERSION = '2.5'
# This method finishes filling in everything
s.config(globals(), fill_defaults)
print('Final settings: ')
print(' JIG_BASE: ' + JIG_BASE)
print(' JIG_VERSION: ' + JIG_VERSION)
print(' JIG_URL: ' + JIG_URL)
import sys
class SettingsDeferrer(object):
# Direct get, private:
def _get(self, name):
d = self.__dict__
return d[name] if name in d else None
def _set(self, name, value):
self.__dict__[name] = value
# If an overrides value is set, return that; otherwise, return
# the default
def __getattr__(self, name):
merged = self._get('merged')
v = merged[name] if (merged and name in merged) else None
return v
# This gets called from within fill_defaults. It only sets the value in
# `merged` if there isn't something there already
def __setattr__(self, name, value):
merged = self._get('merged')
if not(merged): return
if not(name in merged): merged[name] = value
def config(self, _overrides, fill_defaults):
self._set('merged', _overrides)
fill_defaults()
this = SettingsDeferrer()
sys.modules[__name__] = this
Django~=1.9.0
settings-overrider~=0.5
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment