[diffoscope] 01/01: Add a reader for the json format
Ximin Luo
infinity0 at debian.org
Mon May 29 22:05:16 CEST 2017
This is an automated email from the git hooks/post-receive script.
infinity0 pushed a commit to branch experimental
in repository diffoscope.
commit 4cd861e4fb8cced920c9f9eb1897d48b59819b20
Author: Ximin Luo <infinity0 at debian.org>
Date: Mon May 29 22:04:46 2017 +0200
Add a reader for the json format
---
debian/diffoscope.1.rst | 11 +++--
diffoscope/difference.py | 13 +++++-
diffoscope/main.py | 29 +++++++++----
.../{comparators/ipk.py => readers/__init__.py} | 13 +++---
diffoscope/readers/json.py | 45 +++++++++++++++++++
diffoscope/{__init__.py => readers/utils.py} | 6 ++-
tests/comparators/utils/data.py | 13 ++++++
tests/test_readers.py | 50 ++++++++++++++++++++++
8 files changed, 158 insertions(+), 22 deletions(-)
diff --git a/debian/diffoscope.1.rst b/debian/diffoscope.1.rst
index 396975d..23c7e1a 100644
--- a/debian/diffoscope.1.rst
+++ b/debian/diffoscope.1.rst
@@ -14,7 +14,9 @@ in-depth comparison of files, archives, and directories
SYNOPSIS
========
- diffoscope [-h] [--version] [--debug] [--html output] [--text output] [--max-report-size bytes] [--css url] file1 file2
+ diffoscope [-h] [--json output] [OPTIONS] file1 file2
+ diffoscope [-h] [OPTIONS] diff_file
+ diffoscope [-h] [OPTIONS] < diff_file
DESCRIPTION
===========
@@ -36,13 +38,16 @@ project and was formerly known as “debbindiff”.
OPTIONS
=======
--h, --help show this help message and exit
+-h, --help show a detailed help message and exit
--version show program's version number and exit
--debug display debug messages
---html output write HTML report to given file
+--json output write JSON report to given file
(use - for standard output)
--text output write plain text report to given file
(use - for standard output)
+--html output write HTML report to given file
+ (use - for standard output)
+--html-dir output write multi-HTML report to given directory
--max-report-size BYTES
maximum bytes written in report (default: 2048000)
--max-diff-block-lines MAX_DIFF_BLOCK_LINES
diff --git a/diffoscope/difference.py b/diffoscope/difference.py
index 53e1dda..38853f1 100644
--- a/diffoscope/difference.py
+++ b/diffoscope/difference.py
@@ -52,7 +52,7 @@ class VisualDifference(object):
class Difference(object):
- def __init__(self, unified_diff, path1, path2, source=None, comment=None, has_internal_linenos=False):
+ def __init__(self, unified_diff, path1, path2, source=None, comment=None, has_internal_linenos=False, details=None):
self._comments = []
if comment:
if type(comment) is list:
@@ -78,12 +78,21 @@ class Difference(object):
raise TypeError("path2/source[1] is not a string")
# Whether the unified_diff already contains line numbers inside itself
self._has_internal_linenos = has_internal_linenos
- self._details = []
+ self._details = details or []
self._visuals = []
def __repr__(self):
return '<Difference %s -- %s %s>' % (self._source1, self._source2, self._details)
+ def equals(self, other):
+ return self == other or (
+ self.unified_diff == other.unified_diff and
+ self.source1 == other.source1 and
+ self.source2 == other.source2 and
+ self.comments == other.comments and
+ self.has_internal_linenos == other.has_internal_linenos and
+ all(x.equals(y) for x, y in zip(self.details, other.details)))
+
@staticmethod
def from_feeder(feeder1, feeder2, path1, path2, source=None, comment=None, **kwargs):
try:
diff --git a/diffoscope/main.py b/diffoscope/main.py
index f97607d..74e26ba 100644
--- a/diffoscope/main.py
+++ b/diffoscope/main.py
@@ -42,6 +42,7 @@ from .external_tools import EXTERNAL_TOOLS
from .presenters.html import JQUERY_SYSTEM_LOCATIONS
from .presenters.formats import PresenterManager
from .comparators.utils.compare import compare_root_paths
+from .readers import load_diff, load_diff_from_path
logger = logging.getLogger(__name__)
@@ -61,8 +62,12 @@ def create_parser():
parser = argparse.ArgumentParser(
description='Calculate differences between two files or directories',
add_help=False)
- parser.add_argument('path1', help='First file or directory to compare')
- parser.add_argument('path2', help='Second file or directory to compare')
+ parser.add_argument('path1', nargs='?', help='First file or directory to '
+ 'compare. If omitted, tries to read a diffoscope diff from stdin.')
+ parser.add_argument('path2', nargs='?', help='Second file or directory to '
+ 'compare. If omitted, no comparison is done but instead we read a '
+ 'diffoscope diff from path1 and will output this in the formats '
+ 'specified by the rest of the command line.')
parser.add_argument('--debug', action='store_true',
default=False, help='Display debug messages')
parser.add_argument('--debugger', action='store_true',
@@ -289,16 +294,22 @@ def run_diffoscope(parsed_args):
Config().compute_visual_diffs = PresenterManager().compute_visual_diffs()
set_path()
set_locale()
- logger.debug('Starting comparison')
- with Progress():
- with profile('main', 'outputs'):
- difference = compare_root_paths(
- parsed_args.path1, parsed_args.path2)
- ProgressManager().finish()
+ path1, path2 = parsed_args.path1, parsed_args.path2
+ if path2 is None:
+ if path1 is None or path1 == '-':
+ difference = load_diff(sys.stdin, "stdin")
+ else:
+ difference = load_diff_from_path(path1)
+ else:
+ logger.debug('Starting comparison')
+ with Progress():
+ with profile('main', 'outputs'):
+ difference = compare_root_paths(path1, path2)
+ ProgressManager().finish()
# Generate an empty, dummy diff to write, saving the exit code first.
has_differences = bool(difference is not None)
if difference is None and parsed_args.output_empty:
- difference = Difference(None, parsed_args.path1, parsed_args.path2)
+ difference = Difference(None, path1, path2)
with profile('main', 'outputs'):
PresenterManager().output(difference, parsed_args, has_differences)
return 1 if has_differences else 0
diff --git a/diffoscope/comparators/ipk.py b/diffoscope/readers/__init__.py
similarity index 74%
copy from diffoscope/comparators/ipk.py
copy to diffoscope/readers/__init__.py
index 3131dcc..391be39 100644
--- a/diffoscope/comparators/ipk.py
+++ b/diffoscope/readers/__init__.py
@@ -2,8 +2,7 @@
#
# diffoscope: in-depth comparison of files, archives, and directories
#
-# Copyright © 2015 Reiner Herrmann <reiner at reiner-h.de>
-# 2015 Jérémy Bobbio <lunar at debian.org>
+# Copyright © 2017 Ximin Luo <infinity0 at debian.org>
#
# diffoscope is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -18,10 +17,12 @@
# You should have received a copy of the GNU General Public License
# along with diffoscope. If not, see <https://www.gnu.org/licenses/>.
-import re
+from .json import JSONReaderV1
-from .gzip import GzipFile
+def load_diff_from_path(path):
+ with open(path, 'rb') as fp:
+ return load_diff(fp, path)
-class IpkFile(GzipFile):
- RE_FILE_EXTENSION = re.compile('\.ipk$')
+def load_diff(fp, path):
+ return JSONReaderV1().load(fp, "stdin")
diff --git a/diffoscope/readers/json.py b/diffoscope/readers/json.py
new file mode 100644
index 0000000..0891e52
--- /dev/null
+++ b/diffoscope/readers/json.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+#
+# diffoscope: in-depth comparison of files, archives, and directories
+#
+# Copyright © 2017 Ximin Luo <infinity0 at debian.org>
+#
+# diffoscope is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# diffoscope is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with diffoscope. If not, see <https://www.gnu.org/licenses/>.
+
+import codecs
+import json
+from collections import OrderedDict
+
+from ..difference import Difference
+from ..presenters.json import JSON_FORMAT_MAGIC
+from .utils import UnrecognizedFormatError
+
+
+class JSONReaderV1(object):
+
+ def load(self, fp, fn):
+ raw = json.load(codecs.getreader("utf-8")(fp))
+ if JSON_FORMAT_MAGIC not in raw:
+ raise UnrecognizedFormatError("magic not found in json: %s" % JSON_FORMAT_MAGIC)
+ return self.load_rec(raw)
+
+ def load_rec(self, raw):
+ source1 = raw["source1"]
+ source2 = raw["source2"]
+ unified_diff = raw["unified_diff"]
+ has_internal_linenos = raw.get("has_internal_linenos", False)
+ comments = raw.get("comments", [])
+ details = [self.load_rec(child) for child in raw.get("details", [])]
+
+ return Difference(unified_diff, source1, source2, comment=comments, details=details)
diff --git a/diffoscope/__init__.py b/diffoscope/readers/utils.py
similarity index 87%
copy from diffoscope/__init__.py
copy to diffoscope/readers/utils.py
index f510f82..ca54da4 100644
--- a/diffoscope/__init__.py
+++ b/diffoscope/readers/utils.py
@@ -2,7 +2,7 @@
#
# diffoscope: in-depth comparison of files, archives, and directories
#
-# Copyright © 2014-2015 Jérémy Bobbio <lunar at debian.org>
+# Copyright © 2017 Ximin Luo <infinity0 at debian.org>
#
# diffoscope is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -17,4 +17,6 @@
# You should have received a copy of the GNU General Public License
# along with diffoscope. If not, see <https://www.gnu.org/licenses/>.
-VERSION = "82"
+
+class UnrecognizedFormatError(Exception):
+ pass
diff --git a/tests/comparators/utils/data.py b/tests/comparators/utils/data.py
index fb6a1f5..d2420d1 100644
--- a/tests/comparators/utils/data.py
+++ b/tests/comparators/utils/data.py
@@ -18,6 +18,7 @@
# You should have received a copy of the GNU General Public License
# along with diffoscope. If not, see <https://www.gnu.org/licenses/>.
+import contextlib
import os
import re
import pytest
@@ -50,6 +51,18 @@ def get_data(filename):
return f.read()
+ at contextlib.contextmanager
+def cwd_data():
+ """A context manager which changes the working directory to the given
+ path, and then changes it back to its previous value on exit.
+
+ """
+ prev_cwd = os.getcwd()
+ os.chdir(data(""))
+ yield
+ os.chdir(prev_cwd)
+
+
def load_fixture(filename):
return init_fixture(data(filename))
diff --git a/tests/test_readers.py b/tests/test_readers.py
new file mode 100644
index 0000000..a765ecd
--- /dev/null
+++ b/tests/test_readers.py
@@ -0,0 +1,50 @@
+# -*- coding: utf-8 -*-
+#
+# diffoscope: in-depth comparison of files, archives, and directories
+#
+# Copyright © 2017 Ximin Luo <infinity0 at debian.org>
+#
+# diffoscope is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# diffoscope is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with diffoscope. If not, see <https://www.gnu.org/licenses/>.
+
+import os
+import re
+import pytest
+
+from diffoscope.main import main
+from diffoscope.comparators.utils.compare import compare_root_paths
+from diffoscope.readers import load_diff_from_path
+
+from comparators.utils.data import cwd_data, get_data
+
+
+def run_read_write(capsys, diff, *args):
+ with pytest.raises(SystemExit) as exc, cwd_data():
+ main(args + (diff,))
+
+ out, err = capsys.readouterr()
+
+ assert err == ''
+ assert exc.value.code == 1
+ assert out == get_data(diff) # presented-output is same as parsed-input
+ return out
+
+def run_diff_read(diffpath):
+ with cwd_data():
+ diff = compare_root_paths('test1.tar', 'test2.tar')
+ read = load_diff_from_path(diffpath)
+ assert diff.equals(read)
+
+def test_json(capsys):
+ run_read_write(capsys, 'output.json', '--json', '-')
+ run_diff_read('output.json')
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/diffoscope.git
More information about the diffoscope
mailing list