refactor: simplify bound method representation (#12492)

Co-authored-by: Sviatoslav Sydorenko <webknjaz@redhat.com>
Co-authored-by: Farbod Ahmadian <farbod@datachef.com>
This commit is contained in:
Farbod Ahmadian 2024-06-21 18:20:44 +02:00 committed by GitHub
parent 9947ec3ad1
commit 34e28295a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 71 additions and 2 deletions

View File

@ -149,6 +149,7 @@ Evgeny Seliverstov
Fabian Sturm
Fabien Zarifian
Fabio Zadrozny
Farbod Ahmadian
faph
Felix Hofstätter
Felix Nieuwenhuizen

View File

@ -0,0 +1,38 @@
The readability of assertion introspection of bound methods has been enhanced
-- by :user:`farbodahm`, :user:`webknjaz`, :user:`obestwalter`, :user:`flub`
and :user:`glyphack`.
Earlier, it was like:
.. code-block:: console
=================================== FAILURES ===================================
_____________________________________ test _____________________________________
def test():
> assert Help().fun() == 2
E assert 1 == 2
E + where 1 = <bound method Help.fun of <example.Help instance at 0x256a830>>()
E + where <bound method Help.fun of <example.Help instance at 0x256a830>> = <example.Help instance at 0x256a830>.fun
E + where <example.Help instance at 0x256a830> = Help()
example.py:7: AssertionError
=========================== 1 failed in 0.03 seconds ===========================
And now it's like:
.. code-block:: console
=================================== FAILURES ===================================
_____________________________________ test _____________________________________
def test():
> assert Help().fun() == 2
E assert 1 == 2
E + where 1 = fun()
E + where fun = <test_local.Help object at 0x1074be230>.fun
E + where <test_local.Help object at 0x1074be230> = Help()
test_local.py:13: AssertionError
=========================== 1 failed in 0.03 seconds ===========================

View File

@ -60,7 +60,6 @@ class SafeRepr(reprlib.Repr):
s = ascii(x)
else:
s = super().repr(x)
except (KeyboardInterrupt, SystemExit):
raise
except BaseException as exc:

View File

@ -417,6 +417,10 @@ def _saferepr(obj: object) -> str:
sequences, especially '\n{' and '\n}' are likely to be present in
JSON reprs.
"""
if isinstance(obj, types.MethodType):
# for bound methods, skip redundant <bound method ...> information
return obj.__name__
maxsize = _get_maxsize_for_saferepr(util._config)
return saferepr(obj, maxsize=maxsize).replace("\n", "\\n")

View File

@ -10,6 +10,7 @@ import marshal
import os
from pathlib import Path
import py_compile
import re
import stat
import sys
import textwrap
@ -24,6 +25,7 @@ from _pytest._io.saferepr import DEFAULT_REPR_MAX_SIZE
from _pytest.assertion import util
from _pytest.assertion.rewrite import _get_assertion_exprs
from _pytest.assertion.rewrite import _get_maxsize_for_saferepr
from _pytest.assertion.rewrite import _saferepr
from _pytest.assertion.rewrite import AssertionRewritingHook
from _pytest.assertion.rewrite import get_cache_dir
from _pytest.assertion.rewrite import PYC_TAIL
@ -2036,7 +2038,9 @@ class TestPyCacheDir:
assert test_foo_pyc.is_file()
# normal file: not touched by pytest, normal cache tag
bar_init_pyc = get_cache_dir(bar_init) / f"__init__.{sys.implementation.cache_tag}.pyc"
bar_init_pyc = (
get_cache_dir(bar_init) / f"__init__.{sys.implementation.cache_tag}.pyc"
)
assert bar_init_pyc.is_file()
@ -2103,3 +2107,26 @@ class TestIssue11140:
)
result = pytester.runpytest()
assert result.ret == 0
class TestSafereprUnbounded:
class Help:
def bound_method(self): # pragma: no cover
pass
def test_saferepr_bound_method(self):
"""saferepr() of a bound method should show only the method name"""
assert _saferepr(self.Help().bound_method) == "bound_method"
def test_saferepr_unbounded(self):
"""saferepr() of an unbound method should still show the full information"""
obj = self.Help()
# using id() to fetch memory address fails on different platforms
pattern = re.compile(
rf"<{Path(__file__).stem}.{self.__class__.__name__}.Help object at 0x[0-9a-fA-F]*>",
)
assert pattern.match(_saferepr(obj))
assert (
_saferepr(self.Help)
== f"<class '{Path(__file__).stem}.{self.__class__.__name__}.Help'>"
)