# HG changeset patch # User Franz Glasner # Date 1522912349 -7200 # Node ID 2f2e819e8d1795ac092e9e7a8eac41613ce3fc27 # Parent 05cb18c8697a3910acdee20a55ecc6e13e31d65b Check the return type of the JSON and YAML loading functions: they must be a dict alike diff -r 05cb18c8697a -r 2f2e819e8d17 configmix/json.py --- a/configmix/json.py Wed Apr 04 23:51:07 2018 +0200 +++ b/configmix/json.py Thu Apr 05 09:12:29 2018 +0200 @@ -53,4 +53,7 @@ if _with_object_pairs_hook: kwds["object_pairs_hook"] = DictImpl decoder = json.decoder.JSONDecoder(**kwds) - return decoder.decode(jsfp.read()) + data = decoder.decode(jsfp.read()) + if not isinstance(data, DictImpl): + raise TypeError("JSON root must be an object") + return data diff -r 05cb18c8697a -r 2f2e819e8d17 configmix/yaml.py --- a/configmix/yaml.py Wed Apr 04 23:51:07 2018 +0200 +++ b/configmix/yaml.py Thu Apr 05 09:12:29 2018 +0200 @@ -151,16 +151,34 @@ def load(stream, Loader=ConfigLoader): - return yaml.load(stream, Loader) + data = yaml.load(stream, Loader) + if OrderedDict: + if not isinstance(data, OrderedDict): + raise TypeError("YAML root object must be a mapping") + return data def load_all(stream, Loader=ConfigLoader): - return yaml.load_all(stream, Loader) + data_all = yaml.load_all(stream, Loader) + if OrderedDict: + for data in data_all: + if not isinstance(data, OrderedDict): + raise TypeError("YAML root object must be a mapping") + return data_all def safe_load(stream): - return yaml.load(stream, Loader=ConfigSafeLoader) + data = yaml.load(stream, Loader=ConfigSafeLoader) + if OrderedDict: + if not isinstance(data, OrderedDict): + raise TypeError("YAML root object must be a mapping") + return data def safe_load_all(stream): - return yaml.load_all(stream, Loader=ConfigSafeLoader) + data_all = yaml.load_all(stream, Loader=ConfigSafeLoader) + if OrderedDict: + for data in data_all: + if not isinstance(data, OrderedDict): + raise TypeError("YAML root object must be a mapping") + return data_all diff -r 05cb18c8697a -r 2f2e819e8d17 doc/introduction.rst --- a/doc/introduction.rst Wed Apr 04 23:51:07 2018 +0200 +++ b/doc/introduction.rst Thu Apr 05 09:12:29 2018 +0200 @@ -22,8 +22,9 @@ .. note:: All strings are returned as Unicode text strings. -.. note:: The root object must be a *mapping* and therefore decode into - a Python :class:`dict` alike. +.. note:: The root object must be a *mapping* and therefore decode + into a Python :class:`dict` alike. This is checked by the + implementation. An example is: @@ -40,8 +41,9 @@ .. note:: All strings are returned as Unicode text strings. -.. note:: The root object must be an *object* and therefore decode into - a Python :class:`dict` alike. +.. note:: The root object must be an *object* and therefore decode + into a Python :class:`dict` alike. This is checked by the + implementation. .. todo:: Handle JSON comments by special attributes which will filtered out on further processing. Javascript comments are diff -r 05cb18c8697a -r 2f2e819e8d17 tests/test.py --- a/tests/test.py Wed Apr 04 23:51:07 2018 +0200 +++ b/tests/test.py Thu Apr 05 09:12:29 2018 +0200 @@ -66,6 +66,8 @@ with io.open(os.path.join(TESTDATADIR, "conf1.yml"), "rt", encoding="utf-8") as f: cfg = configmix.yaml.safe_load(f) + if configmix.yaml.OrderedDict: + self.assertTrue(isinstance(cfg, configmix.yaml.OrderedDict)) self.__check_types(cfg) def test04_json_types(self):