Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog/15333.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed excessive memory usage during doctest collection on modules importing ``unittest.mock.call`` when the recursion limit is raised.
16 changes: 16 additions & 0 deletions src/_pytest/doctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,22 @@ def _find_lineno(self, obj, source_lines):
source_lines,
)

def _find(
self, tests, obj, name, module, source_lines, globs, seen
) -> None:
"""Override _find to work around issue in stdlib.

https://github.com/pytest-dev/pytest/issues/3456
https://github.com/python/cpython/issues/69718
"""
if _is_mocked(obj):
return # pragma: no cover
with _patch_unwrap_mock_aware():
# Type ignored because this is a private function.
super()._find( # type:ignore[misc]
tests, obj, name, module, source_lines, globs, seen
)

if sys.version_info < (3, 13):

def _from_module(self, module, object):
Expand Down
20 changes: 20 additions & 0 deletions testing/test_doctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1812,6 +1812,26 @@ class Example(object):
result.stdout.fnmatch_lines(["* 1 passed *"])


def test_doctest_mock_objects_high_recursion_limit(pytester: Pytester) -> None:
pytester.makeconftest(
"""
import sys
sys.setrecursionlimit(5000)
"""
)
pytester.makepyfile(
"""
'''
>>> 1
1
'''
from unittest.mock import call
"""
)
result = pytester.runpytest("--doctest-modules")
result.stdout.fnmatch_lines(["* 1 passed *"])


class Broken:
def __getattr__(self, _):
raise KeyError("This should be an AttributeError")
Expand Down
Loading