Bug#839538: diffoscope: json: detect order-only differences
Daniel Shahaf
danielsh at apache.org
Wed Oct 26 10:52:29 UTC 2016
Mattia Rizzolo wrote on Sun, Oct 23, 2016 at 23:21:53 +0000:
> Though I'd really prefer to see some tests for this before applying it;
Attached.
The code change is unchanged from the previous patch.
Test test works; I'm not sure whether is idiomatic pytest, though.
Cheers
Daniel
[[[
diff --git a/diffoscope/comparators/json.py b/diffoscope/comparators/json.py
index d16a762..8d0c104 100644
--- a/diffoscope/comparators/json.py
+++ b/diffoscope/comparators/json.py
@@ -17,6 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with diffoscope. If not, see <http://www.gnu.org/licenses/>.
+from collections import OrderedDict
import re
import json
@@ -34,18 +35,26 @@ class JSONFile(File):
with open(file.path) as f:
try:
- file.parsed = json.load(f)
+ file.parsed = json.load(f, object_pairs_hook=OrderedDict)
except json.JSONDecodeError:
return False
return True
def compare_details(self, other, source=None):
- return [Difference.from_text(self.dumps(self), self.dumps(other),
- self.path, other.path)]
+ difference = Difference.from_text(self.dumps(self), self.dumps(other),
+ self.path, other.path)
+ if difference:
+ return [difference]
+
+ difference = Difference.from_text(self.dumps(self, sort_keys=False),
+ self.dumps(other, sort_keys=False),
+ self.path, other.path,
+ comment="ordering differences only")
+ return [difference]
@staticmethod
- def dumps(file):
+ def dumps(file, sort_keys=True):
if not hasattr(file, 'parsed'):
return ""
- return json.dumps(file.parsed, indent=4, sort_keys=True)
+ return json.dumps(file.parsed, indent=4, sort_keys=sort_keys)
diff --git a/tests/comparators/test_json.py b/tests/comparators/test_json.py
index 26ea110..57c2006 100644
--- a/tests/comparators/test_json.py
+++ b/tests/comparators/test_json.py
@@ -25,6 +25,8 @@ from utils import data, load_fixture, assert_non_existing
json1 = load_fixture(data('test1.json'))
json2 = load_fixture(data('test2.json'))
+json3a = load_fixture(data('order1a.json'))
+json3b = load_fixture(data('order1b.json'))
def test_identification(json1):
assert isinstance(json1, JSONFile)
@@ -43,3 +45,8 @@ def test_diff(differences):
def test_compare_non_existing(monkeypatch, json1):
assert_non_existing(monkeypatch, json1)
+
+def test_ordering_differences(json3a, json3b):
+ diff = json3a.compare(json3b)
+ assert diff.details[0]._comments == ['ordering differences only']
+ assert diff.details[0].unified_diff == open(data('order1.diff')).read()
diff --git a/tests/data/order1.diff b/tests/data/order1.diff
index e69de29..92c7861 100644
--- a/tests/data/order1.diff
+++ b/tests/data/order1.diff
@@ -0,0 +1,7 @@
+@@ -1,4 +1,4 @@
+ {
+- "hello": 42,
+- "world": 43
++ "world": 43,
++ "hello": 42
+ }
diff --git a/tests/data/order1a.json b/tests/data/order1a.json
index e69de29..92ba8aa 100644
--- a/tests/data/order1a.json
+++ b/tests/data/order1a.json
@@ -0,0 +1 @@
+{ "hello": 42, "world": 43 }
diff --git a/tests/data/order1b.json b/tests/data/order1b.json
index e69de29..bb3a742 100644
--- a/tests/data/order1b.json
+++ b/tests/data/order1b.json
@@ -0,0 +1 @@
+{ "world": 43, "hello": 42 }
]]]
More information about the Reproducible-builds
mailing list