code: do not truncate args when running with -vvv (#12241)
Related to #2871.
This commit is contained in:
parent
177f2ae6c4
commit
7be95f9b30
1
AUTHORS
1
AUTHORS
|
@ -279,6 +279,7 @@ Michael Droettboom
|
|||
Michael Goerz
|
||||
Michael Krebs
|
||||
Michael Seifert
|
||||
Michael Vogt
|
||||
Michal Wajszczuk
|
||||
Michał Górny
|
||||
Michał Zięba
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Do not truncate arguments to functions in output when running with `-vvv`.
|
|
@ -635,6 +635,7 @@ class ExceptionInfo(Generic[E]):
|
|||
] = True,
|
||||
funcargs: bool = False,
|
||||
truncate_locals: bool = True,
|
||||
truncate_args: bool = True,
|
||||
chain: bool = True,
|
||||
) -> Union["ReprExceptionInfo", "ExceptionChainRepr"]:
|
||||
"""Return str()able representation of this exception info.
|
||||
|
@ -665,6 +666,9 @@ class ExceptionInfo(Generic[E]):
|
|||
:param bool truncate_locals:
|
||||
With ``showlocals==True``, make sure locals can be safely represented as strings.
|
||||
|
||||
:param bool truncate_args:
|
||||
With ``showargs==True``, make sure args can be safely represented as strings.
|
||||
|
||||
:param bool chain:
|
||||
If chained exceptions in Python 3 should be shown.
|
||||
|
||||
|
@ -691,6 +695,7 @@ class ExceptionInfo(Generic[E]):
|
|||
tbfilter=tbfilter,
|
||||
funcargs=funcargs,
|
||||
truncate_locals=truncate_locals,
|
||||
truncate_args=truncate_args,
|
||||
chain=chain,
|
||||
)
|
||||
return fmt.repr_excinfo(self)
|
||||
|
@ -809,6 +814,7 @@ class FormattedExcinfo:
|
|||
tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]] = True
|
||||
funcargs: bool = False
|
||||
truncate_locals: bool = True
|
||||
truncate_args: bool = True
|
||||
chain: bool = True
|
||||
astcache: Dict[Union[str, Path], ast.AST] = dataclasses.field(
|
||||
default_factory=dict, init=False, repr=False
|
||||
|
@ -839,7 +845,11 @@ class FormattedExcinfo:
|
|||
if self.funcargs:
|
||||
args = []
|
||||
for argname, argvalue in entry.frame.getargs(var=True):
|
||||
args.append((argname, saferepr(argvalue)))
|
||||
if self.truncate_args:
|
||||
str_repr = saferepr(argvalue)
|
||||
else:
|
||||
str_repr = saferepr(argvalue, maxsize=None)
|
||||
args.append((argname, str_repr))
|
||||
return ReprFuncArgs(args)
|
||||
return None
|
||||
|
||||
|
|
|
@ -448,6 +448,8 @@ class Node(abc.ABC, metaclass=NodeMeta):
|
|||
else:
|
||||
truncate_locals = True
|
||||
|
||||
truncate_args = False if self.config.getoption("verbose", 0) > 2 else True
|
||||
|
||||
# excinfo.getrepr() formats paths relative to the CWD if `abspath` is False.
|
||||
# It is possible for a fixture/test to change the CWD while this code runs, which
|
||||
# would then result in the user seeing confusing paths in the failure message.
|
||||
|
@ -466,6 +468,7 @@ class Node(abc.ABC, metaclass=NodeMeta):
|
|||
style=style,
|
||||
tbfilter=tbfilter,
|
||||
truncate_locals=truncate_locals,
|
||||
truncate_args=truncate_args,
|
||||
)
|
||||
|
||||
def repr_failure(
|
||||
|
|
|
@ -11,6 +11,7 @@ import re
|
|||
import sys
|
||||
import textwrap
|
||||
from typing import Any
|
||||
from typing import cast
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import _pytest._code
|
||||
|
@ -712,6 +713,29 @@ raise ValueError()
|
|||
assert full_reprlocals.lines
|
||||
assert full_reprlocals.lines[0] == "l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"
|
||||
|
||||
def test_repr_args_not_truncated(self, importasmod) -> None:
|
||||
mod = importasmod(
|
||||
"""
|
||||
def func1(m):
|
||||
raise ValueError("hello\\nworld")
|
||||
"""
|
||||
)
|
||||
excinfo = pytest.raises(ValueError, mod.func1, "m" * 500)
|
||||
excinfo.traceback = excinfo.traceback.filter(excinfo)
|
||||
entry = excinfo.traceback[-1]
|
||||
p = FormattedExcinfo(funcargs=True, truncate_args=True)
|
||||
reprfuncargs = p.repr_args(entry)
|
||||
assert reprfuncargs is not None
|
||||
arg1 = cast(str, reprfuncargs.args[0][1])
|
||||
assert len(arg1) < 500
|
||||
assert "..." in arg1
|
||||
# again without truncate
|
||||
p = FormattedExcinfo(funcargs=True, truncate_args=False)
|
||||
reprfuncargs = p.repr_args(entry)
|
||||
assert reprfuncargs is not None
|
||||
assert reprfuncargs.args[0] == ("m", repr("m" * 500))
|
||||
assert "..." not in cast(str, reprfuncargs.args[0][1])
|
||||
|
||||
def test_repr_tracebackentry_lines(self, importasmod) -> None:
|
||||
mod = importasmod(
|
||||
"""
|
||||
|
|
|
@ -2045,3 +2045,36 @@ def test_fine_grained_assertion_verbosity(pytester: Pytester):
|
|||
f"E AssertionError: assert 'hello world' in '{long_text}'",
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def test_full_output_vvv(pytester: Pytester) -> None:
|
||||
pytester.makepyfile(
|
||||
r"""
|
||||
def crash_helper(m):
|
||||
assert 1 == 2
|
||||
def test_vvv():
|
||||
crash_helper(500 * "a")
|
||||
"""
|
||||
)
|
||||
result = pytester.runpytest("")
|
||||
# without -vvv, the passed args are truncated
|
||||
expected_non_vvv_arg_line = "m = 'aaaaaaaaaaaaaaa*..aaaaaaaaaaaa*"
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
expected_non_vvv_arg_line,
|
||||
"test_full_output_vvv.py:2: AssertionError",
|
||||
],
|
||||
)
|
||||
# double check that the untruncated part is not in the output
|
||||
expected_vvv_arg_line = "m = '{}'".format(500 * "a")
|
||||
result.stdout.no_fnmatch_line(expected_vvv_arg_line)
|
||||
|
||||
# but with "-vvv" the args are not truncated
|
||||
result = pytester.runpytest("-vvv")
|
||||
result.stdout.fnmatch_lines(
|
||||
[
|
||||
expected_vvv_arg_line,
|
||||
"test_full_output_vvv.py:2: AssertionError",
|
||||
]
|
||||
)
|
||||
result.stdout.no_fnmatch_line(expected_non_vvv_arg_line)
|
||||
|
|
Loading…
Reference in New Issue