changeset 127:5b62d2c0e5a8

Use the available "OrderedDict" class as dict for the JSON parser
author Franz Glasner <hg@dom66.de>
date Wed, 04 Apr 2018 20:53:06 +0200
parents 93964bac7ef6
children 95ad65c69561
files configmix/json.py tests/test.py
diffstat 2 files changed, 27 insertions(+), 5 deletions(-) [+]
line wrap: on
line diff
--- a/configmix/json.py	Wed Apr 04 10:57:49 2018 +0200
+++ b/configmix/json.py	Wed Apr 04 20:53:06 2018 +0200
@@ -11,11 +11,30 @@
 
 import io
 import json.decoder
+try:
+    from collections import OrderedDict as DictImpl
+except ImportError:
+    try:
+        from ordereddict import OrderedDict as DictImpl
+    except ImportError:
+        DictImpl = dict
 
 
 __all__ = ["load"]
 
 
+#
+# Determine whether the JSONDecoder has the "object_pairs_hook"
+# parameter once
+#
+try:
+    json.decoder.JSONDecoder(object_pairs_hook=DictImpl)
+except TypeError:
+    _with_object_pairs_hook = False
+else:
+    _with_object_pairs_hook = True
+
+
 def load(filename, encoding="utf-8"):
     """Load a single JSON file with name `filename` and encoding `encoding`.
 
@@ -23,11 +42,13 @@
 
     .. todo:: Allow all Python string literals
 
-    .. todo:: Use OrderedDict as default mapping implementation (Python 2.7+)
-
     """
     with io.open(filename, mode="rt", encoding=encoding) as jsfp:
-        decoder = json.decoder.JSONDecoder(
-            parse_int=lambda n: int(n, 0),
-            strict=False)
+        kwds = {
+            "parse_int": lambda n: int(n, 0),
+            "strict": False
+        }
+        if _with_object_pairs_hook:
+            kwds["object_pairs_hook"] = DictImpl
+        decoder = json.decoder.JSONDecoder(**kwds)
         return decoder.decode(jsfp.read())
--- a/tests/test.py	Wed Apr 04 10:57:49 2018 +0200
+++ b/tests/test.py	Wed Apr 04 20:53:06 2018 +0200
@@ -70,6 +70,7 @@
 
     def test04_json_types(self):
         cfg = configmix.json.load(os.path.join(TESTDATADIR, "conf1.json"))
+        self.assertTrue(isinstance(cfg, configmix.json.DictImpl))
         self.__check_types(cfg)
 
     def test05_py_export_all(self):