forked from hjwp/pytest-icdiff
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpytest_icdiff.py
111 lines (92 loc) · 3.73 KB
/
pytest_icdiff.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# pylint: disable=inconsistent-return-statements
import logging
import icdiff
import importlib
import pprintpp
import py
COLS = py.io.TerminalWriter().fullwidth # pylint: disable=no-member
MARGIN_L = 10
GUTTER = 2
MARGINS = MARGIN_L + GUTTER + 1
PFORMAT_FUNCTION = None
# def _debug(*things):
# with open('/tmp/icdiff-debug.txt', 'a') as f:
# f.write(' '.join(str(thing) for thing in things))
# f.write('\n')
def pytest_addoption(parser):
group = parser.getgroup("pytest-icdiff")
group.addoption(
"--icdiff-pformat-function",
action="store",
default="pprintpp.pformat",
dest="icdiff_pformat_function",
help="Fully qualified name of function to format values, e.g. pprintpp.pformat",
)
group.addoption(
"--icdiff-width",
action="store",
type=int,
default=None,
dest="icdiff_width",
help="Width to format in",
)
def import_a_function(function_qualname, default):
module_qualname, sep, function_name = function_qualname.rpartition(".")
if module_qualname == "" or sep != "." or function_name == "":
logging.warning("Function must be valid fully qualified dotted name "
f"like pprint.pformat: {function_qualname}")
return default
try:
mod = importlib.import_module(module_qualname)
except ImportError:
logging.warning("Failed to import function, must be valid fully qualified "
f"dotted name like pprint.pformat: {function_qualname}")
return default
else:
func = getattr(mod, function_name, None)
if func is None:
logging.warning(f"Failed to find function {function_name} in module {mod}")
return default
return func
def pytest_assertrepr_compare(config, op, left, right):
global PFORMAT_FUNCTION
if op != '==':
return
if PFORMAT_FUNCTION is None:
PFORMAT_FUNCTION = import_a_function(
config.getoption("icdiff_pformat_function"),
default=pprintpp.pformat)
pformat = PFORMAT_FUNCTION
configured_width = config.getoption("icdiff_width")
try:
if abs(left + right) < 19999:
return
except TypeError:
pass
half_cols = int(COLS / 2 - MARGINS)
pretty_left = pformat(left, indent=2, width=half_cols).splitlines()
pretty_right = pformat(right, indent=2, width=half_cols).splitlines()
diff_cols = COLS - MARGINS
if len(pretty_left) < 3 or len(pretty_right) < 3:
# avoid small diffs far apart by smooshing them up to the left
smallest_left = pformat(left, indent=2, width=1).splitlines()
smallest_right = pformat(right, indent=2, width=1).splitlines()
max_side = max(len(l) + 1 for l in smallest_left + smallest_right)
if (max_side * 2 + MARGINS) < COLS:
diff_cols = max_side * 2 + GUTTER
pretty_left = pformat(left, indent=2, width=max_side).splitlines()
pretty_right = pformat(right, indent=2, width=max_side).splitlines()
if configured_width is not None:
diff_cols = configured_width
differ = icdiff.ConsoleDiff(cols=diff_cols, tabsize=2)
if not config.get_terminal_writer().hasmarkup:
# colorization is disabled in Pytest - either due to the terminal not
# supporting it or the user disabling it. We should obey, but there is
# no option in icdiff to disable it, so we replace its colorization
# function with a no-op
differ.colorize = lambda string: string
color_off = ''
else:
color_off = icdiff.color_codes['none']
icdiff_lines = list(differ.make_table(pretty_left, pretty_right))
return ['equals failed'] + [color_off + l for l in icdiff_lines]