10000 bpo-30181: parse docstring using pydoc by brianmay · Pull Request #1505 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-30181: parse docstring using pydoc #1505

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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
26 changes: 19 additions & 7 deletions Lib/unittest/case.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import difflib
import logging
import pprint
import pydoc
import re
import warnings
import collections
Expand Down Expand Up @@ -338,6 +339,20 @@ def __exit__(self, exc_type, exc_value, tb):
.format(logging.getLevelName(self.level), self.logger.name))


def _get_short_description(doc):
"""
Return the summary line from a docstring.

If there is no summary line, return None.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is no summary line, return None.

I don't think this is accurate. If there is no summary line, it can also return the empty string.

"""
if not doc:
return None

(synopsis, long_description) = pydoc.splitdoc(doc)
synopsis = synopsis.strip()
return synopsis


class TestCase(object):
"""A class whose instances are single test cases.

Expand Down Expand Up @@ -466,12 +481,10 @@ def shortDescription(self):
"""Returns a one-line description of the test, or None if no
description has been provided.

The default implementation of this method returns the first line of
the specified test method's docstring.
This method returns the summary line of
the specified test method's docstring, as per PEP-257.
"""
doc = self._testMethodDoc
10000 return doc and doc.split("\n")[0].strip() or None

return _get_short_description(self._testMethodDoc)

def id(self):
return "%s.%s" % (strclass(self.__class__), self._testMethodName)
Expand Down Expand Up @@ -1395,8 +1408,7 @@ def __repr__(self):
def shortDescription(self):
if self._description is not None:
return self._description
doc = self._testFunc.__doc__
return doc and doc.split("\n")[0].strip() or None
return _get_short_description(self._testFunc.__doc__)


class _SubTest(TestCase):
Expand Down
36 changes: 34 additions & 2 deletions Lib/unittest/test/test_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -577,15 +577,15 @@ def testShortDescriptionWithoutDocstring(self):
@unittest.skipIf(sys.flags.optimize >= 2,
"Docstrings are omitted with -O2 and above")
def testShortDescriptionWithOneLineDocstring(self):
"""Tests shortDescription() for a method with a docstring."""
""" Tests shortDescription() for a method with a docstring."""
self.assertEqual(
self.shortDescription(),
'Tests shortDescription() for a method with a docstring.')

@unittest.skipIf(sys.flags.optimize >= 2,
"Docstrings are omitted with -O2 and above")
def testShortDescriptionWithMultiLineDocstring(self):
"""Tests shortDescription() for a method with a longer docstring.
""" Tests shortDescription() for a method with a longer docstring.

This method ensures that only the first line of a docstring is
returned used in the short description, no matter how long the
Expand All @@ -596,6 +596,38 @@ def testShortDescriptionWithMultiLineDocstring(self):
'Tests shortDescription() for a method with a longer '
'docstring.')

@unittest.skipIf(
sys.flags.optimize >= 2,
"Docstrings are omitted with -O2 and above")
def testShortDescriptionWithSurroundingNewlineOneLineDocstring(self):
"""
Surrounding newlines should be stripped to get the shortDescription.
"""
expected_description = (
"Surrounding newlines should be stripped"
" to get the shortDescription.")
self.assertEqual(self.shortDescription(), expected_description)

@unittest.skipIf(
sys.flags.optimize >= 2,
"Docstrings are omitted with -O2 and above")
def testShortDescriptionWithSurroundingNewlineMultiLineDocstring(self):
"""
Surrounding newlines should be stripped to get the shortDescription.

The specification of how docstring space should be parsed is at
https://www.python.org/dev/peps/pep-0257/#handling-docstring-indentation
which requires that “Blank lines should be removed from the
beginning and end of the docstring.”

The PEP 257 algorithm is implemented by `pydoc.splitdoc`.

"""
expected_description = (
"Surrounding newlines should be stripped"
" to get the shortDescription.")
self.assertEqual(self.shortDescription(), expected_description)

def testAddTypeEqualityFunc(self):
class SadSnake(object):
"""Dummy class for test_addTypeEqualityFunc."""
Expand Down
58 changes: 50 additions & 8 deletions Lib/unittest/test/test_functiontestcase.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,23 +126,65 @@ def test_id(self):

self.assertIsInstance(test.id(), str)

# "Returns a one-line description of the test, or None if no description
# has been provided. The default implementation of this method returns
# the first line of the test method's docstring, if available, or None."
def test_shortDescription__no_docstring(self):
def test_shortDescription__no_description_no_docstring(self):
""" Should return None by default for shortDescription. """
test = unittest.FunctionTestCase(lambda: None)

self.assertEqual(test.shortDescription(), None)

# "Returns a one-line description of the test, or None if no description
# has been provided. The default implementation of this method returns
# the first line of the test method's docstring, if available, or None."
def test_shortDescription__singleline_docstring(self):
def test_shortDescription__singleline_description(self):
""" Should use the specified description for shortDescription. """
desc = "this tests foo"
test = unittest.FunctionTestCase(lambda: None, description=desc)

self.assertEqual(test.shortDescription(), "this tests foo")

def test_shortDescription__no_description_singleline_docstring(self):
""" Should use the function docstring for the shortDescription. """
test_function = (lambda: None)
test_function.__doc__ = """Should use the function docstring."""
test = unittest.FunctionTestCase(test_function)
expected_description = "Should use the function docstring."
self.assertEqual(test.shortDescription(), expected_description)

def test_shortDescription__singleline_docstring_space_surrounded(self):
""" Surrounding space should be stripped to get the shortDescription. """
test_function = (lambda: None)
test_function.__doc__ = """ Surrounding space should be stripped. """
test = unittest.FunctionTestCase(test_function)
expected_description = "Surrounding space should be stripped."
self.assertEqual(test.shortDescription(), expected_description)

def test_shortDescription__singleline_docstring_newline_surrounded(self):
"""
Surrounding newlines should be stripped to get the shortDescription.
"""
test_function = (lambda: None)
test_function.__doc__ = """
Surrounding newlines should be stripped.
"""
test = unittest.FunctionTestCase(test_function)
expected_description = "Surrounding newlines should be stripped."
self.assertEqual(test.shortDescription(), expected_description)

def test_shortDescription__multiline_docstring_newline_surrounded(self):
"""
Surrounding newlines should be stripped to get the shortDescription.
"""
test_function = (lambda: None)
test_function.__doc__ = """
Surrounding newlines should be stripped.

The specification of how docstring space should be parsed is at
https://www.python.org/dev/peps/pep-0257/#handling-docstring-indentation
which requires that “Blank lines should be removed from the
beginning and end of the docstring.”

"""
test = unittest.FunctionTestCase(test_function)
expected_description = "Surrounding newlines should be stripped."
self.assertEqual(test.shortDescription(), expected_description)


if __name__ == "__main__":
unittest.main()
2 changes: 2 additions & 0 deletions Lib/unittest/test/test_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ def testGetSubTestDescriptionWithOneLineDocstring(self):
"Docstrings are omitted with -O2 and above")
def testGetDescriptionWithMultiLineDocstring(self):
"""Tests getDescription() for a method with a longer docstring.

The second line of the docstring.
"""
result = unittest.TextTestResult(None, True, 1)
Expand All @@ -383,6 +384,7 @@ def testGetDescriptionWithMultiLineDocstring(self):
"Docstrings are omitted with -O2 and above")
def testGetSubTestDescriptionWithMultiLineDocstring(self):
"""Tests getDescription() for a method with a longer docstring.

The second line of the docstring.
"""
result = unittest.TextTestResult(None, True, 1)
Expand Down
0