Last active
December 15, 2019 15:34
-
-
Save keriszafir/e6086a78a61d0ecd268b96351c9e9678 to your computer and use it in GitHub Desktop.
configuration module with attribute-like option access and json file data storage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- 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