Skip to content

Instantly share code, notes, and snippets.

@keriszafir
Last active December 15, 2019 15:34
Show Gist options
  • Save keriszafir/e6086a78a61d0ecd268b96351c9e9678 to your computer and use it in GitHub Desktop.
Save keriszafir/e6086a78a61d0ecd268b96351c9e9678 to your computer and use it in GitHub Desktop.
configuration module with attribute-like option access and json file data storage
# -*- coding: utf-8 -*-
"""Configuration class storing data as jsonfile.
Written for micropython which has no configparser module, but can be
used on regular python as well. The goal is to make a configuration class
that is simpler and less painful to use than ConfigParser."""
try:
# micropython module
import ujson as json
except ImportError:
# "regular" python module
import json
class Config(dict):
"""Configuration class using a JSON file to read and write settings.
Options are accessed and assigned as attributes. For example:
config.foo is equivalent to config['foo']
config.foo = 'bar' is equivalent to config['foo'] = 'bar'
NB. if attribute is absent, KeyError is raised."""
# these two assignments allow us to read/write dictionary items
# using object attribute protocol
__getattr__ = dict.__getitem__
__setattr__ = dict.__setitem__
def __init__(self, filename=None, *args, **kwargs):
if filename is None:
raise ValueError('You MUST specify a filename as the first arg!')
# store the filename in a low-level object's dict
# so that clear() doesn't erase it
self.__dict__['filename'] = filename
# fill the underlying dictionary with keys and values
super().__init__(*args, **kwargs)
try:
# read conffile contents, then update with arguments,
# so that arguments have precedence over file
self.load(self.filename)
super().update(*args, **kwargs)
except FileNotFoundError:
# create a new conffile
self.save()
def save_as(self, filename):
"""Save the current config to file"""
with open(filename, 'w+') as jsonfile:
contents = json.dumps(self)
jsonfile.write(contents)
def save(self):
"""Save the current config to self.filename"""
self.save_as(self.filename)
def load(self, filename, clear=False):
"""Load configuration data from a specified file"""
with open(filename, 'r') as jsonfile:
raw = jsonfile.read()
contents = json.loads(raw)
if clear:
super().clear()
super().update(**contents)
def reload(self):
"""Load self.filename and overwrite all unsaved changes"""
self.load(self.filename, clear=True)
def update(self, *args, **kwargs):
"""Update the configuration data and save it to file"""
# args = dict-like objects; kwargs = key-value mappings
super().update(*args, **kwargs)
self.save()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment