aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/pytest/py3/_pytest/_io
diff options
context:
space:
mode:
authorDevtools Arcadia <arcadia-devtools@yandex-team.ru>2022-02-07 18:08:42 +0300
committerDevtools Arcadia <arcadia-devtools@mous.vla.yp-c.yandex.net>2022-02-07 18:08:42 +0300
commit1110808a9d39d4b808aef724c861a2e1a38d2a69 (patch)
treee26c9fed0de5d9873cce7e00bc214573dc2195b7 /contrib/python/pytest/py3/_pytest/_io
downloadydb-1110808a9d39d4b808aef724c861a2e1a38d2a69.tar.gz
intermediate changes
ref:cde9a383711a11544ce7e107a78147fb96cc4029
Diffstat (limited to 'contrib/python/pytest/py3/_pytest/_io')
-rw-r--r--contrib/python/pytest/py3/_pytest/_io/__init__.py39
-rw-r--r--contrib/python/pytest/py3/_pytest/_io/saferepr.py103
2 files changed, 142 insertions, 0 deletions
diff --git a/contrib/python/pytest/py3/_pytest/_io/__init__.py b/contrib/python/pytest/py3/_pytest/_io/__init__.py
new file mode 100644
index 0000000000..f56579806c
--- /dev/null
+++ b/contrib/python/pytest/py3/_pytest/_io/__init__.py
@@ -0,0 +1,39 @@
+from typing import List
+from typing import Sequence
+
+from py.io import TerminalWriter as BaseTerminalWriter # noqa: F401
+
+
+class TerminalWriter(BaseTerminalWriter):
+ def _write_source(self, lines: List[str], indents: Sequence[str] = ()) -> None:
+ """Write lines of source code possibly highlighted.
+
+ Keeping this private for now because the API is clunky. We should discuss how
+ to evolve the terminal writer so we can have more precise color support, for example
+ being able to write part of a line in one color and the rest in another, and so on.
+ """
+ if indents and len(indents) != len(lines):
+ raise ValueError(
+ "indents size ({}) should have same size as lines ({})".format(
+ len(indents), len(lines)
+ )
+ )
+ if not indents:
+ indents = [""] * len(lines)
+ source = "\n".join(lines)
+ new_lines = self._highlight(source).splitlines()
+ for indent, new_line in zip(indents, new_lines):
+ self.line(indent + new_line)
+
+ def _highlight(self, source):
+ """Highlight the given source code according to the "code_highlight" option"""
+ if not self.hasmarkup:
+ return source
+ try:
+ from pygments.formatters.terminal import TerminalFormatter
+ from pygments.lexers.python import PythonLexer
+ from pygments import highlight
+ except ImportError:
+ return source
+ else:
+ return highlight(source, PythonLexer(), TerminalFormatter(bg="dark"))
diff --git a/contrib/python/pytest/py3/_pytest/_io/saferepr.py b/contrib/python/pytest/py3/_pytest/_io/saferepr.py
new file mode 100644
index 0000000000..47a00de606
--- /dev/null
+++ b/contrib/python/pytest/py3/_pytest/_io/saferepr.py
@@ -0,0 +1,103 @@
+import pprint
+import reprlib
+from typing import Any
+
+
+def _try_repr_or_str(obj):
+ try:
+ 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, type(obj).__name__, id(obj)
+ )
+
+
+def _ellipsize(s: str, maxsize: int) -> str:
+ if len(s) > maxsize:
+ i = max(0, (maxsize - 3) // 2)
+ j = max(0, maxsize - 3 - i)
+ return s[:i] + "..." + s[len(s) - j :]
+ return s
+
+
+class SafeRepr(reprlib.Repr):
+ """subclass of repr.Repr that limits the resulting size of repr()
+ and includes information on exceptions raised during the call.
+ """
+
+ def __init__(self, maxsize: int) -> None:
+ super().__init__()
+ self.maxstring = maxsize
+ self.maxsize = maxsize
+
+ def repr(self, x: Any) -> str:
+ try:
+ s = super().repr(x)
+ 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 (KeyboardInterrupt, SystemExit):
+ raise
+ except BaseException as exc:
+ s = _format_repr_exception(exc, x)
+ return _ellipsize(s, self.maxsize)
+
+
+def safeformat(obj: Any) -> str:
+ """return a pretty printed string for the given object.
+ Failing __repr__ functions of user instances will be represented
+ with a short exception info.
+ """
+ try:
+ return pprint.pformat(obj)
+ except Exception as exc:
+ return _format_repr_exception(exc, obj)
+
+
+def saferepr(obj: Any, maxsize: int = 240) -> str:
+ """return a size-limited safe repr-string for the given object.
+ Failing __repr__ functions of user instances will be represented
+ with a short exception info and 'saferepr' generally takes
+ care to never raise exceptions itself. This function is a wrapper
+ around the Repr/reprlib functionality of the standard 2.6 lib.
+ """
+ return SafeRepr(maxsize).repr(obj)
+
+
+class AlwaysDispatchingPrettyPrinter(pprint.PrettyPrinter):
+ """PrettyPrinter that always dispatches (regardless of width)."""
+
+ def _format(self, object, stream, indent, allowance, context, level):
+ p = self._dispatch.get(type(object).__repr__, None)
+
+ objid = id(object)
+ if objid in context or p is None:
+ return super()._format(object, stream, indent, allowance, context, level)
+
+ context[objid] = 1
+ p(self, object, stream, indent, allowance, context, level + 1)
+ del context[objid]
+
+
+def _pformat_dispatch(object, indent=1, width=80, depth=None, *, compact=False):
+ return AlwaysDispatchingPrettyPrinter(
+ indent=indent, width=width, depth=depth, compact=compact
+ ).pformat(object)