Do not swallow outcomes.Exit in assertrepr_compare
This commit is contained in:
		
							parent
							
								
									15d608867d
								
							
						
					
					
						commit
						0d00be4f4f
					
				|  | @ -0,0 +1 @@ | ||||||
|  | ``outcomes.Exit`` is not swallowed in ``assertrepr_compare`` anymore. | ||||||
|  | @ -9,6 +9,7 @@ import six | ||||||
| 
 | 
 | ||||||
| import _pytest._code | import _pytest._code | ||||||
| from ..compat import Sequence | from ..compat import Sequence | ||||||
|  | from _pytest import outcomes | ||||||
| from _pytest._io.saferepr import saferepr | from _pytest._io.saferepr import saferepr | ||||||
| 
 | 
 | ||||||
| # The _reprcompare attribute on the util module is used by the new assertion | # The _reprcompare attribute on the util module is used by the new assertion | ||||||
|  | @ -102,6 +103,38 @@ except NameError: | ||||||
|     basestring = str |     basestring = str | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | def issequence(x): | ||||||
|  |     return isinstance(x, Sequence) and not isinstance(x, basestring) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def istext(x): | ||||||
|  |     return isinstance(x, basestring) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def isdict(x): | ||||||
|  |     return isinstance(x, dict) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def isset(x): | ||||||
|  |     return isinstance(x, (set, frozenset)) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def isdatacls(obj): | ||||||
|  |     return getattr(obj, "__dataclass_fields__", None) is not None | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def isattrs(obj): | ||||||
|  |     return getattr(obj, "__attrs_attrs__", None) is not None | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def isiterable(obj): | ||||||
|  |     try: | ||||||
|  |         iter(obj) | ||||||
|  |         return not istext(obj) | ||||||
|  |     except TypeError: | ||||||
|  |         return False | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| def assertrepr_compare(config, op, left, right): | def assertrepr_compare(config, op, left, right): | ||||||
|     """Return specialised explanations for some operators/operands""" |     """Return specialised explanations for some operators/operands""" | ||||||
|     width = 80 - 15 - len(op) - 2  # 15 chars indentation, 1 space around op |     width = 80 - 15 - len(op) - 2  # 15 chars indentation, 1 space around op | ||||||
|  | @ -110,31 +143,6 @@ def assertrepr_compare(config, op, left, right): | ||||||
| 
 | 
 | ||||||
|     summary = u"%s %s %s" % (ecu(left_repr), op, ecu(right_repr)) |     summary = u"%s %s %s" % (ecu(left_repr), op, ecu(right_repr)) | ||||||
| 
 | 
 | ||||||
|     def issequence(x): |  | ||||||
|         return isinstance(x, Sequence) and not isinstance(x, basestring) |  | ||||||
| 
 |  | ||||||
|     def istext(x): |  | ||||||
|         return isinstance(x, basestring) |  | ||||||
| 
 |  | ||||||
|     def isdict(x): |  | ||||||
|         return isinstance(x, dict) |  | ||||||
| 
 |  | ||||||
|     def isset(x): |  | ||||||
|         return isinstance(x, (set, frozenset)) |  | ||||||
| 
 |  | ||||||
|     def isdatacls(obj): |  | ||||||
|         return getattr(obj, "__dataclass_fields__", None) is not None |  | ||||||
| 
 |  | ||||||
|     def isattrs(obj): |  | ||||||
|         return getattr(obj, "__attrs_attrs__", None) is not None |  | ||||||
| 
 |  | ||||||
|     def isiterable(obj): |  | ||||||
|         try: |  | ||||||
|             iter(obj) |  | ||||||
|             return not istext(obj) |  | ||||||
|         except TypeError: |  | ||||||
|             return False |  | ||||||
| 
 |  | ||||||
|     verbose = config.getoption("verbose") |     verbose = config.getoption("verbose") | ||||||
|     explanation = None |     explanation = None | ||||||
|     try: |     try: | ||||||
|  | @ -162,6 +170,8 @@ def assertrepr_compare(config, op, left, right): | ||||||
|         elif op == "not in": |         elif op == "not in": | ||||||
|             if istext(left) and istext(right): |             if istext(left) and istext(right): | ||||||
|                 explanation = _notin_text(left, right, verbose) |                 explanation = _notin_text(left, right, verbose) | ||||||
|  |     except outcomes.Exit: | ||||||
|  |         raise | ||||||
|     except Exception: |     except Exception: | ||||||
|         explanation = [ |         explanation = [ | ||||||
|             u"(pytest_assertion plugin: representation of details failed.  " |             u"(pytest_assertion plugin: representation of details failed.  " | ||||||
|  |  | ||||||
|  | @ -11,6 +11,7 @@ import six | ||||||
| 
 | 
 | ||||||
| import _pytest.assertion as plugin | import _pytest.assertion as plugin | ||||||
| import pytest | import pytest | ||||||
|  | from _pytest import outcomes | ||||||
| from _pytest.assertion import truncate | from _pytest.assertion import truncate | ||||||
| from _pytest.assertion import util | from _pytest.assertion import util | ||||||
| 
 | 
 | ||||||
|  | @ -1305,3 +1306,13 @@ def test_issue_1944(testdir): | ||||||
|         "AttributeError: 'Module' object has no attribute '_obj'" |         "AttributeError: 'Module' object has no attribute '_obj'" | ||||||
|         not in result.stdout.str() |         not in result.stdout.str() | ||||||
|     ) |     ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def test_exit_from_assertrepr_compare(monkeypatch): | ||||||
|  |     def raise_exit(obj): | ||||||
|  |         outcomes.exit("Quitting debugger") | ||||||
|  | 
 | ||||||
|  |     monkeypatch.setattr(util, "istext", raise_exit) | ||||||
|  | 
 | ||||||
|  |     with pytest.raises(outcomes.Exit, match="Quitting debugger"): | ||||||
|  |         callequal(1, 1) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue