diff options
author | Daniel Hahler <git@thequod.de> | 2019-10-23 06:59:18 +0200 |
---|---|---|
committer | Daniel Hahler <git@thequod.de> | 2019-11-06 22:08:10 +0100 |
commit | eb7a4e32ad920b4cdd9c956763535fed194ae8a7 (patch) | |
tree | 3a111410860e9ff9742fdfbe73140bcbf6c4add2 /src/_pytest/_io | |
parent | 5be3a9b5cee3ef73b627049272db5bd2e34f5026 (diff) | |
download | pytest-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.py | 32 |
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) |