Merge pull request #4637 from tk0miya/4563_extract_summary

Fix #4563: autosummary: Incorrect end of line punctuation detection
This commit is contained in:
Takeshi KOMIYA 2018-02-19 22:45:21 +09:00 committed by GitHub
commit bce5fe76b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 26 deletions

View File

@ -32,6 +32,7 @@ Bugs fixed
* autosummary: The interface of ``sphinx.ext.autosummary.get_documenter()`` has
been changed
* #4630: Have order on msgids in sphinx.pot deterministic
* #4563: autosummary: Incorrect end of line punctuation detection
Testing
--------

View File

@ -64,6 +64,7 @@ from typing import TYPE_CHECKING
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst.states import RSTStateMachine, state_classes
from docutils.statemachine import ViewList
from six import string_types
from six import text_type
@ -77,6 +78,7 @@ from sphinx.ext.autodoc.directive import DocumenterBridge, Options
from sphinx.ext.autodoc.importer import import_module
from sphinx.pycode import ModuleAnalyzer, PycodeError
from sphinx.util import import_object, rst, logging
from sphinx.util.docutils import new_document
if TYPE_CHECKING:
from typing import Any, Dict, List, Tuple, Type, Union # NOQA
@ -340,27 +342,7 @@ class Autosummary(Directive):
# -- Grab the summary
documenter.add_content(None)
doc = self.result.data
while doc and not doc[0].strip():
doc.pop(0)
# If there's a blank line, then we can assume the first sentence /
# paragraph has ended, so anything after shouldn't be part of the
# summary
for i, piece in enumerate(doc):
if not piece.strip():
doc = doc[:i]
break
# Try to find the "first sentence", which may span multiple lines
m = re.search(r"^([A-Z].*?\.)(?:\s|$)", " ".join(doc).strip())
if m:
summary = m.group(1).strip()
elif doc:
summary = doc[0].strip()
else:
summary = ''
summary = extract_summary(self.result.data[:], self.state.document)
items.append((display_name, sig, summary, real_name))
@ -467,6 +449,40 @@ def mangle_signature(sig, max_chars=30):
return u"(%s)" % sig
def extract_summary(doc, document):
# type: (List[unicode], Any) -> unicode
"""Extract summary from docstring."""
# Skip a blank lines at the top
while doc and not doc[0].strip():
doc.pop(0)
# If there's a blank line, then we can assume the first sentence /
# paragraph has ended, so anything after shouldn't be part of the
# summary
for i, piece in enumerate(doc):
if not piece.strip():
doc = doc[:i]
break
# Try to find the "first sentence", which may span multiple lines
sentences = " ".join(doc).split('.')
if len(sentences) == 1:
summary = sentences[0].strip()
else:
summary = ''
state_machine = RSTStateMachine(state_classes, 'Body')
while sentences:
summary += sentences.pop(0) + '.'
node = new_document('', document.settings)
state_machine.run([summary], node)
if not node.traverse(nodes.system_message):
# considered as that splitting by period does not break inline markups
break
return summary
def limited_join(sep, items, max_chars=30, overflow_marker="..."):
# type: (unicode, List[unicode], int, unicode) -> unicode
"""Join a number of strings to one, limiting the length to *max_chars*.

View File

@ -9,14 +9,12 @@
:license: BSD, see LICENSE for details.
"""
import pytest
from six import iteritems, StringIO
from sphinx.ext.autosummary import mangle_signature, import_by_name
from sphinx.ext.autosummary import mangle_signature, import_by_name, extract_summary
from sphinx.testing.util import etree_parse
import pytest
html_warnfile = StringIO()
@ -57,6 +55,29 @@ def test_mangle_signature():
assert res == outp, (u"'%s' -> '%s' != '%s'" % (inp, res, outp))
def test_extract_summary():
from sphinx.util.docutils import new_document
from mock import Mock
settings = Mock(language_code='',
id_prefix='',
auto_id_prefix='',
pep_reference=False,
rfc_reference=False)
document = new_document('', settings)
# normal case
doc = ['',
'This is a first sentence. And second one.',
'',
'Second block is here']
assert extract_summary(doc, document) == 'This is a first sentence.'
# inliner case
doc = ['This sentence contains *emphasis text having dots.*,',
'it does not break sentence.']
assert extract_summary(doc, document) == ' '.join(doc)
@pytest.mark.sphinx('dummy', **default_kw)
def test_get_items_summary(make_app, app_params):
import sphinx.ext.autosummary
@ -95,7 +116,7 @@ def test_get_items_summary(make_app, app_params):
expected_values = {
'withSentence': 'I have a sentence which spans multiple lines.',
'noSentence': "this doesn't start with a",
'noSentence': "this doesn't start with a capital.",
'emptyLine': "This is the real summary",
'module_attr': 'This is a module attribute',
'C.class_attr': 'This is a class attribute',