From 96da4ee1d44cf4d071a70b9eb88292e844bad12a Mon Sep 17 00:00:00 2001 From: James Graham <J.A.Graham@soton.ac.uk> Date: Thu, 12 May 2016 11:23:47 +0100 Subject: [PATCH] Documentation and small changes to parsers/json --- doc/source/pycgtool.parsers.json.rst | 7 ++++++ doc/source/pycgtool.parsers.rst | 1 + pycgtool/parsers/json.py | 36 +++++++++++++++++++--------- test/test_parsers_json.py | 4 ++++ 4 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 doc/source/pycgtool.parsers.json.rst diff --git a/doc/source/pycgtool.parsers.json.rst b/doc/source/pycgtool.parsers.json.rst new file mode 100644 index 0000000..f761dae --- /dev/null +++ b/doc/source/pycgtool.parsers.json.rst @@ -0,0 +1,7 @@ +pycgtool.parsers.json module +============================ + +.. automodule:: pycgtool.parsers.json + :members: + :undoc-members: + :show-inheritance: diff --git a/doc/source/pycgtool.parsers.rst b/doc/source/pycgtool.parsers.rst index e1fea8b..1bf99ce 100644 --- a/doc/source/pycgtool.parsers.rst +++ b/doc/source/pycgtool.parsers.rst @@ -7,6 +7,7 @@ Submodules .. toctree:: pycgtool.parsers.cfg + pycgtool.parsers.json Module contents --------------- diff --git a/pycgtool/parsers/json.py b/pycgtool/parsers/json.py index bbfe9ae..9fc342f 100644 --- a/pycgtool/parsers/json.py +++ b/pycgtool/parsers/json.py @@ -2,23 +2,34 @@ import json import os -class Record(dict): - def __setattr__(self, key, value): - self[key] = value - - def __getattr__(self, item): - return self[item] +class AttrDict(dict): + """ + Class allowing dictionary entries to be accessed as attributes as well as keys. + """ + def __init__(self, *args, **kwargs): + super(AttrDict, self).__init__(*args, **kwargs) + self.__dict__ = self class CFG: + """ + Class to read data from JSON files. Supports including other files and filtering a single section. + """ def __init__(self, filename, from_section=None): + """ + Create a new CFG JSON parser. + + :param filename: JSON file to read + :param from_section: Optional section to select from file + """ with open(filename) as f: - self._json = json.load(f, object_hook=Record) + self._json = json.load(f, object_hook=AttrDict) + # Recurse through include lists and add to self._json while self._json.include: include_file = os.path.join(os.path.dirname(filename), self._json.include.pop()) with open(include_file) as include_file: - include_json = json.load(include_file, object_hook=Record) + include_json = json.load(include_file, object_hook=AttrDict) for curr, incl in zip(self._json.values(), include_json.values()): try: @@ -26,10 +37,13 @@ class CFG: except TypeError: curr.update(incl) + self._records = self._json if from_section is not None: - self._records = self._json[from_section] - else: - self._records = self._json + try: + self._records = self._json[from_section] + except KeyError as e: + e.args = ("Section '{0}' not in file '{1}'".format(from_section, filename),) + raise def __getitem__(self, item): return self._records[item] diff --git a/test/test_parsers_json.py b/test/test_parsers_json.py index c6f6c05..5878d96 100644 --- a/test/test_parsers_json.py +++ b/test/test_parsers_json.py @@ -49,6 +49,10 @@ class TestParsersJson(unittest.TestCase): self.assertTrue("DOPC" in cfg) self.assertTrue("GLY" in cfg) + def test_missing_section(self): + with self.assertRaises(KeyError): + cfg = CFG("test/data/water.json", "potato") + if __name__ == '__main__': unittest.main() -- GitLab