mirror of
https://github.com/python/cpython.git
synced 2025-10-09 16:34:44 +00:00
bpo-28249: fix lineno
location for empty DocTest
instances (GH-30498)
Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com> Co-authored-by: Łukasz Langa <lukasz@langa.pl>
This commit is contained in:
parent
09be18a73d
commit
8db2b3b687
4 changed files with 83 additions and 6 deletions
|
@ -1085,19 +1085,21 @@ class DocTestFinder:
|
||||||
|
|
||||||
def _find_lineno(self, obj, source_lines):
|
def _find_lineno(self, obj, source_lines):
|
||||||
"""
|
"""
|
||||||
Return a line number of the given object's docstring. Note:
|
Return a line number of the given object's docstring.
|
||||||
this method assumes that the object has a docstring.
|
|
||||||
|
Returns `None` if the given object does not have a docstring.
|
||||||
"""
|
"""
|
||||||
lineno = None
|
lineno = None
|
||||||
|
docstring = getattr(obj, '__doc__', None)
|
||||||
|
|
||||||
# Find the line number for modules.
|
# Find the line number for modules.
|
||||||
if inspect.ismodule(obj):
|
if inspect.ismodule(obj) and docstring is not None:
|
||||||
lineno = 0
|
lineno = 0
|
||||||
|
|
||||||
# Find the line number for classes.
|
# Find the line number for classes.
|
||||||
# Note: this could be fooled if a class is defined multiple
|
# Note: this could be fooled if a class is defined multiple
|
||||||
# times in a single file.
|
# times in a single file.
|
||||||
if inspect.isclass(obj):
|
if inspect.isclass(obj) and docstring is not None:
|
||||||
if source_lines is None:
|
if source_lines is None:
|
||||||
return None
|
return None
|
||||||
pat = re.compile(r'^\s*class\s*%s\b' %
|
pat = re.compile(r'^\s*class\s*%s\b' %
|
||||||
|
@ -1109,7 +1111,9 @@ class DocTestFinder:
|
||||||
|
|
||||||
# Find the line number for functions & methods.
|
# Find the line number for functions & methods.
|
||||||
if inspect.ismethod(obj): obj = obj.__func__
|
if inspect.ismethod(obj): obj = obj.__func__
|
||||||
if inspect.isfunction(obj): obj = obj.__code__
|
if inspect.isfunction(obj) and getattr(obj, '__doc__', None):
|
||||||
|
# We don't use `docstring` var here, because `obj` can be changed.
|
||||||
|
obj = obj.__code__
|
||||||
if inspect.istraceback(obj): obj = obj.tb_frame
|
if inspect.istraceback(obj): obj = obj.tb_frame
|
||||||
if inspect.isframe(obj): obj = obj.f_code
|
if inspect.isframe(obj): obj = obj.f_code
|
||||||
if inspect.iscode(obj):
|
if inspect.iscode(obj):
|
||||||
|
|
50
Lib/test/doctest_lineno.py
Normal file
50
Lib/test/doctest_lineno.py
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# This module is used in `test_doctest`.
|
||||||
|
# It must not have a docstring.
|
||||||
|
|
||||||
|
def func_with_docstring():
|
||||||
|
"""Some unrelated info."""
|
||||||
|
|
||||||
|
|
||||||
|
def func_without_docstring():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def func_with_doctest():
|
||||||
|
"""
|
||||||
|
This function really contains a test case.
|
||||||
|
|
||||||
|
>>> func_with_doctest.__name__
|
||||||
|
'func_with_doctest'
|
||||||
|
"""
|
||||||
|
return 3
|
||||||
|
|
||||||
|
|
||||||
|
class ClassWithDocstring:
|
||||||
|
"""Some unrelated class information."""
|
||||||
|
|
||||||
|
|
||||||
|
class ClassWithoutDocstring:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ClassWithDoctest:
|
||||||
|
"""This class really has a test case in it.
|
||||||
|
|
||||||
|
>>> ClassWithDoctest.__name__
|
||||||
|
'ClassWithDoctest'
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class MethodWrapper:
|
||||||
|
def method_with_docstring(self):
|
||||||
|
"""Method with a docstring."""
|
||||||
|
|
||||||
|
def method_without_docstring(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def method_with_doctest(self):
|
||||||
|
"""
|
||||||
|
This has a doctest!
|
||||||
|
>>> MethodWrapper.method_with_doctest.__name__
|
||||||
|
'method_with_doctest'
|
||||||
|
"""
|
|
@ -25,6 +25,7 @@ if not support.has_subprocess_support:
|
||||||
|
|
||||||
# NOTE: There are some additional tests relating to interaction with
|
# NOTE: There are some additional tests relating to interaction with
|
||||||
# zipimport in the test_zipimport_support test module.
|
# zipimport in the test_zipimport_support test module.
|
||||||
|
# There are also related tests in `test_doctest2` module.
|
||||||
|
|
||||||
######################################################################
|
######################################################################
|
||||||
## Sample Objects (used by test cases)
|
## Sample Objects (used by test cases)
|
||||||
|
@ -460,7 +461,7 @@ We'll simulate a __file__ attr that ends in pyc:
|
||||||
>>> tests = finder.find(sample_func)
|
>>> tests = finder.find(sample_func)
|
||||||
|
|
||||||
>>> print(tests) # doctest: +ELLIPSIS
|
>>> print(tests) # doctest: +ELLIPSIS
|
||||||
[<DocTest sample_func from test_doctest.py:33 (1 example)>]
|
[<DocTest sample_func from test_doctest.py:34 (1 example)>]
|
||||||
|
|
||||||
The exact name depends on how test_doctest was invoked, so allow for
|
The exact name depends on how test_doctest was invoked, so allow for
|
||||||
leading path components.
|
leading path components.
|
||||||
|
@ -642,6 +643,26 @@ displays.
|
||||||
1 SampleClass.double
|
1 SampleClass.double
|
||||||
1 SampleClass.get
|
1 SampleClass.get
|
||||||
|
|
||||||
|
When used with `exclude_empty=False` we are also interested in line numbers
|
||||||
|
of doctests that are empty.
|
||||||
|
It used to be broken for quite some time until `bpo-28249`.
|
||||||
|
|
||||||
|
>>> from test import doctest_lineno
|
||||||
|
>>> tests = doctest.DocTestFinder(exclude_empty=False).find(doctest_lineno)
|
||||||
|
>>> for t in tests:
|
||||||
|
... print('%5s %s' % (t.lineno, t.name))
|
||||||
|
None test.doctest_lineno
|
||||||
|
22 test.doctest_lineno.ClassWithDocstring
|
||||||
|
30 test.doctest_lineno.ClassWithDoctest
|
||||||
|
None test.doctest_lineno.ClassWithoutDocstring
|
||||||
|
None test.doctest_lineno.MethodWrapper
|
||||||
|
39 test.doctest_lineno.MethodWrapper.method_with_docstring
|
||||||
|
45 test.doctest_lineno.MethodWrapper.method_with_doctest
|
||||||
|
None test.doctest_lineno.MethodWrapper.method_without_docstring
|
||||||
|
4 test.doctest_lineno.func_with_docstring
|
||||||
|
12 test.doctest_lineno.func_with_doctest
|
||||||
|
None test.doctest_lineno.func_without_docstring
|
||||||
|
|
||||||
Turning off Recursion
|
Turning off Recursion
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
DocTestFinder can be told not to look for tests in contained objects
|
DocTestFinder can be told not to look for tests in contained objects
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Set :attr:`doctest.DocTest.lineno` to ``None`` when object does not have
|
||||||
|
:attr:`__doc__`.
|
Loading…
Add table
Add a link
Reference in a new issue