summaryrefslogtreecommitdiff
path: root/src/_pytest/_io
diff options
context:
space:
mode:
authorDaniel Hahler <git@thequod.de>2019-10-23 06:59:18 +0200
committerDaniel Hahler <git@thequod.de>2019-11-06 22:08:10 +0100
commiteb7a4e32ad920b4cdd9c956763535fed194ae8a7 (patch)
tree3a111410860e9ff9742fdfbe73140bcbf6c4add2 /src/_pytest/_io
parent5be3a9b5cee3ef73b627049272db5bd2e34f5026 (diff)
downloadpytest-eb7a4e32ad920b4cdd9c956763535fed194ae8a7.tar.gz
saferepr: handle BaseExceptions
This causes INTERNALERRORs with pytest-django, which uses `pytest.fail` (derived from `BaseException`) to prevent DB access, when pytest then tries to e.g. display the `repr()` for a Django `QuerySet` etc. Ref: https://github.com/pytest-dev/pytest-django/pull/776
Diffstat (limited to 'src/_pytest/_io')
-rw-r--r--src/_pytest/_io/saferepr.py32
1 files changed, 23 insertions, 9 deletions
diff --git a/src/_pytest/_io/saferepr.py b/src/_pytest/_io/saferepr.py
index 908fd2183..7fded872d 100644
--- a/src/_pytest/_io/saferepr.py
+++ b/src/_pytest/_io/saferepr.py
@@ -3,14 +3,24 @@ import reprlib
from typing import Any
-def _format_repr_exception(exc: Exception, obj: Any) -> str:
- exc_name = type(exc).__name__
+def _try_repr_or_str(obj):
try:
- exc_info = str(exc)
- except Exception:
- exc_info = "unknown"
- return '<[{}("{}") raised in repr()] {} object at 0x{:x}>'.format(
- exc_name, exc_info, obj.__class__.__name__, id(obj)
+ return repr(obj)
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except BaseException:
+ return '{}("{}")'.format(type(obj).__name__, obj)
+
+
+def _format_repr_exception(exc: BaseException, obj: Any) -> str:
+ try:
+ exc_info = _try_repr_or_str(exc)
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except BaseException as exc:
+ exc_info = "unpresentable exception ({})".format(_try_repr_or_str(exc))
+ return "<[{} raised in repr()] {} object at 0x{:x}>".format(
+ exc_info, obj.__class__.__name__, id(obj)
)
@@ -35,14 +45,18 @@ class SafeRepr(reprlib.Repr):
def repr(self, x: Any) -> str:
try:
s = super().repr(x)
- except Exception as exc:
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except BaseException as exc:
s = _format_repr_exception(exc, x)
return _ellipsize(s, self.maxsize)
def repr_instance(self, x: Any, level: int) -> str:
try:
s = repr(x)
- except Exception as exc:
+ except (KeyboardInterrupt, SystemExit):
+ raise
+ except BaseException as exc:
s = _format_repr_exception(exc, x)
return _ellipsize(s, self.maxsize)