summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikita Sobolev <mail@sobolevn.me>2024-04-10 09:52:47 (GMT)
committerGitHub <noreply@github.com>2024-04-10 09:52:47 (GMT)
commit4bb7d121bc0a3fd00a3c72cd915b5dd8fac5616e (patch)
tree4a65571d5ee468170c5d3422fd5425c42d716ebe
parentf90ff0367271ea474b4ce3c8e2643cb51d188c18 (diff)
downloadcpython-4bb7d121bc0a3fd00a3c72cd915b5dd8fac5616e.zip
cpython-4bb7d121bc0a3fd00a3c72cd915b5dd8fac5616e.tar.gz
cpython-4bb7d121bc0a3fd00a3c72cd915b5dd8fac5616e.tar.bz2
gh-117692: Fix `AttributeError` in `DocTestFinder` on wrapped `builtin_or_method` (#117699)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
-rw-r--r--Lib/doctest.py9
-rw-r--r--Lib/test/test_doctest/test_doctest.py14
-rw-r--r--Misc/NEWS.d/next/Library/2024-04-09-23-22-21.gh-issue-117692.EciInD.rst2
3 files changed, 24 insertions, 1 deletions
diff --git a/Lib/doctest.py b/Lib/doctest.py
index fc0da59..4e362cb 100644
--- a/Lib/doctest.py
+++ b/Lib/doctest.py
@@ -1140,7 +1140,14 @@ class DocTestFinder:
obj = obj.fget
if inspect.isfunction(obj) and getattr(obj, '__doc__', None):
# We don't use `docstring` var here, because `obj` can be changed.
- obj = inspect.unwrap(obj).__code__
+ obj = inspect.unwrap(obj)
+ try:
+ obj = obj.__code__
+ except AttributeError:
+ # Functions implemented in C don't necessarily
+ # have a __code__ attribute.
+ # If there's no code, there's no lineno
+ return None
if inspect.istraceback(obj): obj = obj.tb_frame
if inspect.isframe(obj): obj = obj.f_code
if inspect.iscode(obj):
diff --git a/Lib/test/test_doctest/test_doctest.py b/Lib/test/test_doctest/test_doctest.py
index 0a2a016..f71d62c 100644
--- a/Lib/test/test_doctest/test_doctest.py
+++ b/Lib/test/test_doctest/test_doctest.py
@@ -2553,6 +2553,20 @@ def test_look_in_unwrapped():
'one other test'
"""
+@doctest_skip_if(support.check_impl_detail(cpython=False))
+def test_wrapped_c_func():
+ """
+ # https://github.com/python/cpython/issues/117692
+ >>> import binascii
+ >>> from test.test_doctest.decorator_mod import decorator
+
+ >>> c_func_wrapped = decorator(binascii.b2a_hex)
+ >>> tests = doctest.DocTestFinder(exclude_empty=False).find(c_func_wrapped)
+ >>> for test in tests:
+ ... print(test.lineno, test.name)
+ None b2a_hex
+ """
+
def test_unittest_reportflags():
"""Default unittest reporting flags can be set to control reporting
diff --git a/Misc/NEWS.d/next/Library/2024-04-09-23-22-21.gh-issue-117692.EciInD.rst b/Misc/NEWS.d/next/Library/2024-04-09-23-22-21.gh-issue-117692.EciInD.rst
new file mode 100644
index 0000000..98a6e12
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-04-09-23-22-21.gh-issue-117692.EciInD.rst
@@ -0,0 +1,2 @@
+Fixes a bug when :class:`doctest.DocTestFinder` was failing on wrapped
+``builtin_function_or_method``.