Skip to content

Commit 7be95f9

Browse files
authored
code: do not truncate args when running with -vvv (#12241)
Related to #2871.
1 parent 177f2ae commit 7be95f9

File tree

6 files changed

+73
-1
lines changed

6 files changed

+73
-1
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ Michael Droettboom
279279
Michael Goerz
280280
Michael Krebs
281281
Michael Seifert
282+
Michael Vogt
282283
Michal Wajszczuk
283284
Michał Górny
284285
Michał Zięba

changelog/2871.improvement.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Do not truncate arguments to functions in output when running with `-vvv`.

src/_pytest/_code/code.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,7 @@ def getrepr(
635635
] = True,
636636
funcargs: bool = False,
637637
truncate_locals: bool = True,
638+
truncate_args: bool = True,
638639
chain: bool = True,
639640
) -> Union["ReprExceptionInfo", "ExceptionChainRepr"]:
640641
"""Return str()able representation of this exception info.
@@ -665,6 +666,9 @@ def getrepr(
665666
:param bool truncate_locals:
666667
With ``showlocals==True``, make sure locals can be safely represented as strings.
667668
669+
:param bool truncate_args:
670+
With ``showargs==True``, make sure args can be safely represented as strings.
671+
668672
:param bool chain:
669673
If chained exceptions in Python 3 should be shown.
670674
@@ -691,6 +695,7 @@ def getrepr(
691695
tbfilter=tbfilter,
692696
funcargs=funcargs,
693697
truncate_locals=truncate_locals,
698+
truncate_args=truncate_args,
694699
chain=chain,
695700
)
696701
return fmt.repr_excinfo(self)
@@ -809,6 +814,7 @@ class FormattedExcinfo:
809814
tbfilter: Union[bool, Callable[[ExceptionInfo[BaseException]], Traceback]] = True
810815
funcargs: bool = False
811816
truncate_locals: bool = True
817+
truncate_args: bool = True
812818
chain: bool = True
813819
astcache: Dict[Union[str, Path], ast.AST] = dataclasses.field(
814820
default_factory=dict, init=False, repr=False
@@ -839,7 +845,11 @@ def repr_args(self, entry: TracebackEntry) -> Optional["ReprFuncArgs"]:
839845
if self.funcargs:
840846
args = []
841847
for argname, argvalue in entry.frame.getargs(var=True):
842-
args.append((argname, saferepr(argvalue)))
848+
if self.truncate_args:
849+
str_repr = saferepr(argvalue)
850+
else:
851+
str_repr = saferepr(argvalue, maxsize=None)
852+
args.append((argname, str_repr))
843853
return ReprFuncArgs(args)
844854
return None
845855

src/_pytest/nodes.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,8 @@ def _repr_failure_py(
448448
else:
449449
truncate_locals = True
450450

451+
truncate_args = False if self.config.getoption("verbose", 0) > 2 else True
452+
451453
# excinfo.getrepr() formats paths relative to the CWD if `abspath` is False.
452454
# It is possible for a fixture/test to change the CWD while this code runs, which
453455
# would then result in the user seeing confusing paths in the failure message.
@@ -466,6 +468,7 @@ def _repr_failure_py(
466468
style=style,
467469
tbfilter=tbfilter,
468470
truncate_locals=truncate_locals,
471+
truncate_args=truncate_args,
469472
)
470473

471474
def repr_failure(

testing/code/test_excinfo.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import sys
1212
import textwrap
1313
from typing import Any
14+
from typing import cast
1415
from typing import TYPE_CHECKING
1516

1617
import _pytest._code
@@ -712,6 +713,29 @@ def test_repr_local_truncated(self) -> None:
712713
assert full_reprlocals.lines
713714
assert full_reprlocals.lines[0] == "l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"
714715

716+
def test_repr_args_not_truncated(self, importasmod) -> None:
717+
mod = importasmod(
718+
"""
719+
def func1(m):
720+
raise ValueError("hello\\nworld")
721+
"""
722+
)
723+
excinfo = pytest.raises(ValueError, mod.func1, "m" * 500)
724+
excinfo.traceback = excinfo.traceback.filter(excinfo)
725+
entry = excinfo.traceback[-1]
726+
p = FormattedExcinfo(funcargs=True, truncate_args=True)
727+
reprfuncargs = p.repr_args(entry)
728+
assert reprfuncargs is not None
729+
arg1 = cast(str, reprfuncargs.args[0][1])
730+
assert len(arg1) < 500
731+
assert "..." in arg1
732+
# again without truncate
733+
p = FormattedExcinfo(funcargs=True, truncate_args=False)
734+
reprfuncargs = p.repr_args(entry)
735+
assert reprfuncargs is not None
736+
assert reprfuncargs.args[0] == ("m", repr("m" * 500))
737+
assert "..." not in cast(str, reprfuncargs.args[0][1])
738+
715739
def test_repr_tracebackentry_lines(self, importasmod) -> None:
716740
mod = importasmod(
717741
"""

testing/test_assertion.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2045,3 +2045,36 @@ def test_long_text_fail():
20452045
f"E AssertionError: assert 'hello world' in '{long_text}'",
20462046
]
20472047
)
2048+
2049+
2050+
def test_full_output_vvv(pytester: Pytester) -> None:
2051+
pytester.makepyfile(
2052+
r"""
2053+
def crash_helper(m):
2054+
assert 1 == 2
2055+
def test_vvv():
2056+
crash_helper(500 * "a")
2057+
"""
2058+
)
2059+
result = pytester.runpytest("")
2060+
# without -vvv, the passed args are truncated
2061+
expected_non_vvv_arg_line = "m = 'aaaaaaaaaaaaaaa*..aaaaaaaaaaaa*"
2062+
result.stdout.fnmatch_lines(
2063+
[
2064+
expected_non_vvv_arg_line,
2065+
"test_full_output_vvv.py:2: AssertionError",
2066+
],
2067+
)
2068+
# double check that the untruncated part is not in the output
2069+
expected_vvv_arg_line = "m = '{}'".format(500 * "a")
2070+
result.stdout.no_fnmatch_line(expected_vvv_arg_line)
2071+
2072+
# but with "-vvv" the args are not truncated
2073+
result = pytester.runpytest("-vvv")
2074+
result.stdout.fnmatch_lines(
2075+
[
2076+
expected_vvv_arg_line,
2077+
"test_full_output_vvv.py:2: AssertionError",
2078+
]
2079+
)
2080+
result.stdout.no_fnmatch_line(expected_non_vvv_arg_line)

0 commit comments

Comments
 (0)