Skip to content

Instantly share code, notes, and snippets.

@stavxyz
Last active March 3, 2016 18:31
Show Gist options
  • Save stavxyz/c6862a30d3a52e622b5d to your computer and use it in GitHub Desktop.
Save stavxyz/c6862a30d3a52e622b5d to your computer and use it in GitHub Desktop.
a no frills config module
"""A no frills config module.
A global config is encapsulated at the module level.
This module automatically looks for a config.json
in the project root when it is imported, and will
bootstrap the config with it if found.
# main.py
import config
config.bootstrap(some_data)
config.set('time', time.time())
----------
# module.py
import config
db = config.get('db_connection_string')
----------
You can bootstrap the config with a json string,
python dict, path to file, or file-like object.
"""
from __future__ import print_function
import json
import os
class Config(object):
"""Class for containing configuration."""
def get(self, key, default=None):
"""Get key from object."""
return getattr(self, key, default)
def set(self, key, value):
"""Set key with value."""
return setattr(self, key, value)
def clear(self):
for key in vars(self).keys():
if isinstance(key, basestring):
delattr(self, key)
return self
def __repr__(self):
return '<Config at {}: {}>'.format(
hex(id(self)), list(vars(self).keys()))
_CONFIG = Config()
def get(key, default=None):
"""Get key from current config object."""
return _CONFIG.get(key, default)
def set(key, value):
"""Get key from current config object."""
return _CONFIG.set(key, value)
def clear():
"""Clear all options from the current config object."""
return _CONFIG.clear()
def load():
"""Return current config object."""
return _CONFIG
def pprint():
return json.dumps(vars(load()), indent=2, sort_keys=2)
def bootstrap(data):
"""Load data into current config object.
This function is idempotent, and will
update the existing config if bootstrapped
multiple times.
Argument can be a local path to a json file,
an open file-like object with a read() method,
a json string to deserialize, or a python mapping
with an items() method.
"""
if isinstance(data, basestring) and os.path.isfile(data):
# path to local file
with open(data, 'r') as _d:
data = json.load(_d)
elif callable(getattr(data, 'read', None)):
# file-like object
data = json.load(data)
elif isinstance(data, basestring):
# only do this if its not already a python mapping
data = json.loads(data)
_cfg = load()
for key, value in data.items():
_cfg.set(key, value)
return _cfg
_config_file = os.path.realpath(
os.path.join(os.path.dirname(os.path.realpath(__file__)),
os.path.pardir, 'config.json')
)
if os.path.isfile(_config_file):
bootstrap(_config_file)
@stavxyz
Copy link
Author

stavxyz commented Mar 3, 2016

For use with https://github.com/mitsuhiko/click, add this to the bottom of config,py

import click


def _click_load(ctx, param, value):
    bootstrap(value)

click_option = click.option(
    '--config-file', '-c',
    callback=_click_load,
    default='path/to/config.json',
    show_default=True,
    expose_value=False,
)

and in your cli module, something like this works:

import config

@click.group()
@config.click_option
def click_group():
    pass

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment