[7.4.x] Fix doctest collection of `functools.cached_property` objects. (#11403)

Co-authored-by: Ronny Pfannschmidt <opensource@ronnypfannschmidt.de>
This commit is contained in:
github-actions[bot] 2023-09-07 13:33:12 +00:00 committed by GitHub
parent 79c2012d40
commit 6e49a74089
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 0 deletions

View File

@ -374,6 +374,7 @@ Tony Narlock
Tor Colvin Tor Colvin
Trevor Bekolay Trevor Bekolay
Tyler Goodlet Tyler Goodlet
Tyler Smart
Tzu-ping Chung Tzu-ping Chung
Vasily Kuznetsov Vasily Kuznetsov
Victor Maryama Victor Maryama

View File

@ -0,0 +1 @@
Fix doctest collection of `functools.cached_property` objects.

View File

@ -1,5 +1,6 @@
"""Discover and run doctests in modules and test files.""" """Discover and run doctests in modules and test files."""
import bdb import bdb
import functools
import inspect import inspect
import os import os
import platform import platform
@ -536,6 +537,25 @@ class DoctestModule(Module):
tests, obj, name, module, source_lines, globs, seen tests, obj, name, module, source_lines, globs, seen
) )
if sys.version_info < (3, 13):
def _from_module(self, module, object):
"""`cached_property` objects are never considered a part
of the 'current module'. As such they are skipped by doctest.
Here we override `_from_module` to check the underlying
function instead. https://github.com/python/cpython/issues/107995
"""
if hasattr(functools, "cached_property") and isinstance(
object, functools.cached_property
):
object = object.func
# Type ignored because this is a private function.
return super()._from_module(module, object) # type: ignore[misc]
else: # pragma: no cover
pass
if self.path.name == "conftest.py": if self.path.name == "conftest.py":
module = self.config.pluginmanager._importconftest( module = self.config.pluginmanager._importconftest(
self.path, self.path,

View File

@ -482,6 +482,27 @@ class TestDoctests:
reprec = pytester.inline_run(p, "--doctest-modules") reprec = pytester.inline_run(p, "--doctest-modules")
reprec.assertoutcome(failed=1) reprec.assertoutcome(failed=1)
@pytest.mark.skipif(
sys.version_info[:2] <= (3, 7), reason="Only Python 3.7 or less"
)
def test_doctest_cached_property(self, pytester: Pytester):
p = pytester.makepyfile(
"""
import functools
class Foo:
@functools.cached_property
def foo(self):
'''
>>> assert False, "Tacos!"
'''
...
"""
)
result = pytester.runpytest(p, "--doctest-modules")
result.assert_outcomes(failed=1)
assert "Tacos!" in result.stdout.str()
def test_doctestmodule_external_and_issue116(self, pytester: Pytester): def test_doctestmodule_external_and_issue116(self, pytester: Pytester):
p = pytester.mkpydir("hello") p = pytester.mkpydir("hello")
p.joinpath("__init__.py").write_text( p.joinpath("__init__.py").write_text(