Skip to content

Commit 241b743

Browse files
authored
Merge pull request #4978 from blueyed/exit-from-from_assertrepr_compare
Do not swallow outcomes.Exit in assertrepr_compare
2 parents 057c978 + 0d00be4 commit 241b743

File tree

3 files changed

+46
-24
lines changed

3 files changed

+46
-24
lines changed

changelog/4978.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
``outcomes.Exit`` is not swallowed in ``assertrepr_compare`` anymore.

src/_pytest/assertion/util.py

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import _pytest._code
1111
from ..compat import Sequence
12+
from _pytest import outcomes
1213
from _pytest._io.saferepr import saferepr
1314

1415
# The _reprcompare attribute on the util module is used by the new assertion
@@ -102,38 +103,45 @@ def _format_lines(lines):
102103
basestring = str
103104

104105

105-
def assertrepr_compare(config, op, left, right):
106-
"""Return specialised explanations for some operators/operands"""
107-
width = 80 - 15 - len(op) - 2 # 15 chars indentation, 1 space around op
108-
left_repr = saferepr(left, maxsize=int(width // 2))
109-
right_repr = saferepr(right, maxsize=width - len(left_repr))
106+
def issequence(x):
107+
return isinstance(x, Sequence) and not isinstance(x, basestring)
108+
109+
110+
def istext(x):
111+
return isinstance(x, basestring)
112+
113+
114+
def isdict(x):
115+
return isinstance(x, dict)
110116

111-
summary = u"%s %s %s" % (ecu(left_repr), op, ecu(right_repr))
112117

113-
def issequence(x):
114-
return isinstance(x, Sequence) and not isinstance(x, basestring)
118+
def isset(x):
119+
return isinstance(x, (set, frozenset))
115120

116-
def istext(x):
117-
return isinstance(x, basestring)
118121

119-
def isdict(x):
120-
return isinstance(x, dict)
122+
def isdatacls(obj):
123+
return getattr(obj, "__dataclass_fields__", None) is not None
121124

122-
def isset(x):
123-
return isinstance(x, (set, frozenset))
124125

125-
def isdatacls(obj):
126-
return getattr(obj, "__dataclass_fields__", None) is not None
126+
def isattrs(obj):
127+
return getattr(obj, "__attrs_attrs__", None) is not None
127128

128-
def isattrs(obj):
129-
return getattr(obj, "__attrs_attrs__", None) is not None
130129

131-
def isiterable(obj):
132-
try:
133-
iter(obj)
134-
return not istext(obj)
135-
except TypeError:
136-
return False
130+
def isiterable(obj):
131+
try:
132+
iter(obj)
133+
return not istext(obj)
134+
except TypeError:
135+
return False
136+
137+
138+
def assertrepr_compare(config, op, left, right):
139+
"""Return specialised explanations for some operators/operands"""
140+
width = 80 - 15 - len(op) - 2 # 15 chars indentation, 1 space around op
141+
left_repr = saferepr(left, maxsize=int(width // 2))
142+
right_repr = saferepr(right, maxsize=width - len(left_repr))
143+
144+
summary = u"%s %s %s" % (ecu(left_repr), op, ecu(right_repr))
137145

138146
verbose = config.getoption("verbose")
139147
explanation = None
@@ -162,6 +170,8 @@ def isiterable(obj):
162170
elif op == "not in":
163171
if istext(left) and istext(right):
164172
explanation = _notin_text(left, right, verbose)
173+
except outcomes.Exit:
174+
raise
165175
except Exception:
166176
explanation = [
167177
u"(pytest_assertion plugin: representation of details failed. "

testing/test_assertion.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import _pytest.assertion as plugin
1313
import pytest
14+
from _pytest import outcomes
1415
from _pytest.assertion import truncate
1516
from _pytest.assertion import util
1617

@@ -1305,3 +1306,13 @@ def f():
13051306
"AttributeError: 'Module' object has no attribute '_obj'"
13061307
not in result.stdout.str()
13071308
)
1309+
1310+
1311+
def test_exit_from_assertrepr_compare(monkeypatch):
1312+
def raise_exit(obj):
1313+
outcomes.exit("Quitting debugger")
1314+
1315+
monkeypatch.setattr(util, "istext", raise_exit)
1316+
1317+
with pytest.raises(outcomes.Exit, match="Quitting debugger"):
1318+
callequal(1, 1)

0 commit comments

Comments
 (0)