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:
parent
9947ec3ad1
commit
34e28295a7
1
AUTHORS
1
AUTHORS
|
@ -149,6 +149,7 @@ Evgeny Seliverstov
|
|||
Fabian Sturm
|
||||
Fabien Zarifian
|
||||
Fabio Zadrozny
|
||||
Farbod Ahmadian
|
||||
faph
|
||||
Felix Hofstätter
|
||||
Felix Nieuwenhuizen
|
||||
|
|
|
@ -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 ===========================
|
|
@ -60,7 +60,6 @@ class SafeRepr(reprlib.Repr):
|
|||
s = ascii(x)
|
||||
else:
|
||||
s = super().repr(x)
|
||||
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
raise
|
||||
except BaseException as exc:
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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'>"
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue