mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '1.7' into 4577_nested_enumlist
This commit is contained in:
commit
e0a74a3f40
@ -1,6 +1,6 @@
|
||||
coverage:
|
||||
status:
|
||||
patch:
|
||||
project:
|
||||
default:
|
||||
# allowed to drop X% and still result in a "success" commit status
|
||||
threshold: 0.05
|
||||
|
11
CHANGES
11
CHANGES
@ -10,6 +10,11 @@ Incompatible changes
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
* #4623: ``sphinx.build_main()`` is deprecated. Use
|
||||
``sphinx.cmd.build.build_main()`` instead.
|
||||
* autosummary: The interface of ``sphinx.ext.autosummary.get_documenter()`` has
|
||||
been changed (Since 1.7.0)
|
||||
|
||||
Features added
|
||||
--------------
|
||||
|
||||
@ -22,6 +27,12 @@ Bugs fixed
|
||||
* #4622: epub: :confval:`epub_scheme` does not effect to content.opf
|
||||
* #4627: graphviz: Fit graphviz images to page
|
||||
* #4617: quickstart: PROJECT_DIR argument is required
|
||||
* #4623: sphinx.build_main no longer exists in 1.7.0
|
||||
* #4615: The argument of ``sphinx.build`` has been changed in 1.7.0
|
||||
* 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
|
||||
* #4577: Enumerated sublists with explicit start with wrong number
|
||||
|
||||
Testing
|
||||
|
@ -15,6 +15,7 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
from os import path
|
||||
|
||||
@ -66,9 +67,30 @@ def main(*args, **kwargs):
|
||||
RemovedInSphinx20Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
args = args[1:] # skip first argument to adjust arguments (refs: #4615)
|
||||
return build.main(*args, **kwargs)
|
||||
|
||||
|
||||
def build_main(argv=sys.argv):
|
||||
"""Sphinx build "main" command-line entry."""
|
||||
warnings.warn(
|
||||
'`sphinx.build_main()` has moved to `sphinx.cmd.build.build_main()`.',
|
||||
RemovedInSphinx20Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return build.build_main(argv[1:]) # skip first argument to adjust arguments (refs: #4615)
|
||||
|
||||
|
||||
def make_main(argv=sys.argv):
|
||||
"""Sphinx build "make mode" entry."""
|
||||
warnings.warn(
|
||||
'`sphinx.build_main()` has moved to `sphinx.cmd.build.make_main()`.',
|
||||
RemovedInSphinx20Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return build.make_main(argv[1:]) # skip first argument to adjust arguments (refs: #4615)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from .cmd import build
|
||||
warnings.warn(
|
||||
|
@ -21,6 +21,7 @@ def main(*args, **kwargs):
|
||||
RemovedInSphinx20Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
args = args[1:] # skip first argument to adjust arguments (refs: #4615)
|
||||
_main(*args, **kwargs)
|
||||
|
||||
|
||||
|
@ -88,6 +88,7 @@ builtin_extensions = (
|
||||
'sphinx.roles',
|
||||
'sphinx.transforms.post_transforms',
|
||||
'sphinx.transforms.post_transforms.images',
|
||||
'sphinx.util.compat',
|
||||
# collectors should be loaded by specific order
|
||||
'sphinx.environment.collectors.dependencies',
|
||||
'sphinx.environment.collectors.asset',
|
||||
|
@ -12,7 +12,7 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from codecs import open
|
||||
from collections import defaultdict
|
||||
from collections import defaultdict, OrderedDict
|
||||
from datetime import datetime, tzinfo, timedelta
|
||||
from os import path, walk, getenv
|
||||
from time import time
|
||||
@ -68,8 +68,8 @@ class Catalog(object):
|
||||
# type: () -> None
|
||||
self.messages = [] # type: List[unicode]
|
||||
# retain insertion order, a la OrderedDict
|
||||
self.metadata = {} # type: Dict[unicode, List[Tuple[unicode, int, unicode]]]
|
||||
# msgid -> file, line, uid
|
||||
self.metadata = OrderedDict() # type: Dict[unicode, List[Tuple[unicode, int, unicode]]] # NOQA
|
||||
# msgid -> file, line, uid
|
||||
|
||||
def add(self, msg, origin):
|
||||
# type: (unicode, MsgOrigin) -> None
|
||||
@ -236,7 +236,8 @@ class MessageCatalogBuilder(I18nBuilder):
|
||||
|
||||
def _extract_from_template(self):
|
||||
# type: () -> None
|
||||
files = self._collect_templates()
|
||||
files = list(self._collect_templates())
|
||||
files.sort()
|
||||
logger.info(bold('building [%s]: ' % self.name), nonl=1)
|
||||
logger.info('targets for %d template files', len(files))
|
||||
|
||||
|
@ -58,23 +58,27 @@ import os
|
||||
import posixpath
|
||||
import re
|
||||
import sys
|
||||
import warnings
|
||||
from types import ModuleType
|
||||
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
|
||||
|
||||
import sphinx
|
||||
from sphinx import addnodes
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.environment.adapters.toctree import TocTree
|
||||
from sphinx.ext.autodoc import get_documenters
|
||||
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
|
||||
@ -153,13 +157,17 @@ def autosummary_table_visit_html(self, node):
|
||||
|
||||
# -- autodoc integration -------------------------------------------------------
|
||||
|
||||
# current application object (used in `get_documenter()`).
|
||||
_app = None # type: Sphinx
|
||||
|
||||
|
||||
class FakeDirective(DocumenterBridge):
|
||||
def __init__(self):
|
||||
super(FakeDirective, self).__init__({}, None, Options(), 0) # type: ignore
|
||||
|
||||
|
||||
def get_documenter(app, obj, parent):
|
||||
# type: (Sphinx, Any, Any) -> Type[Documenter]
|
||||
def get_documenter(*args):
|
||||
# type: (Any) -> Type[Documenter]
|
||||
"""Get an autodoc.Documenter class suitable for documenting the given
|
||||
object.
|
||||
|
||||
@ -168,6 +176,16 @@ def get_documenter(app, obj, parent):
|
||||
belongs to.
|
||||
"""
|
||||
from sphinx.ext.autodoc import DataDocumenter, ModuleDocumenter
|
||||
if len(args) == 3:
|
||||
# new style arguments: (app, obj, parent)
|
||||
app, obj, parent = args
|
||||
else:
|
||||
# old style arguments: (obj, parent)
|
||||
app = _app
|
||||
obj, parent = args
|
||||
warnings.warn('the interface of get_documenter() has been changed. '
|
||||
'Please give application object as first argument.',
|
||||
RemovedInSphinx20Warning)
|
||||
|
||||
if inspect.ismodule(obj):
|
||||
# ModuleDocumenter.can_document_member always returns False
|
||||
@ -324,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))
|
||||
|
||||
@ -451,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*.
|
||||
|
@ -22,6 +22,7 @@ def main(*args, **kwargs):
|
||||
RemovedInSphinx20Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
args = args[1:] # skip first argument to adjust arguments (refs: #4615)
|
||||
_main(*args, **kwargs)
|
||||
|
||||
|
||||
|
44
sphinx/util/compat.py
Normal file
44
sphinx/util/compat.py
Normal file
@ -0,0 +1,44 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
sphinx.util.compat
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
modules for backward compatibility
|
||||
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import sys
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from typing import Any, Dict # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
|
||||
def register_application_for_autosummary(app):
|
||||
# type: (Sphinx) -> None
|
||||
"""Register application object to autosummary module.
|
||||
|
||||
Since Sphinx-1.7, documenters and attrgetters are registered into
|
||||
applicaiton object. As a result, the arguments of
|
||||
``get_documenter()`` has been changed. To keep compatibility,
|
||||
this handler registers application object to the module.
|
||||
"""
|
||||
if 'sphinx.ext.autosummary' in sys.modules:
|
||||
from sphinx.ext import autosummary
|
||||
autosummary._app = app
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[unicode, Any]
|
||||
app.connect('builder-inited', register_application_for_autosummary)
|
||||
|
||||
return {
|
||||
'version': 'builtin',
|
||||
'parallel_read_safe': True,
|
||||
'parallel_write_safe': True,
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block body %}
|
||||
<h1>{{ _('Template 1') }}</h1>
|
||||
<p>{%trans%}This is Template 1.{%endtrans%}</p>
|
||||
{% endblock %}
|
@ -0,0 +1,5 @@
|
||||
{% extends "layout.html" %}
|
||||
{% block body %}
|
||||
<h1>{{ _('Template 2') }}</h1>
|
||||
<p>{%trans%}This is Template 2.{%endtrans%}</p>
|
||||
{% endblock %}
|
3
tests/roots/test-gettext-template/conf.py
Normal file
3
tests/roots/test-gettext-template/conf.py
Normal file
@ -0,0 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
templates_path = ['_templates']
|
0
tests/roots/test-gettext-template/contents.rst
Normal file
0
tests/roots/test-gettext-template/contents.rst
Normal file
@ -165,3 +165,18 @@ def test_gettext_template(app):
|
||||
result = (app.outdir / 'sphinx.pot').text(encoding='utf-8')
|
||||
assert "Welcome" in result
|
||||
assert "Sphinx %(version)s" in result
|
||||
|
||||
|
||||
@pytest.mark.sphinx('gettext', testroot='gettext-template')
|
||||
def test_gettext_template_msgid_order_in_sphinxpot(app):
|
||||
app.builder.build_all()
|
||||
assert (app.outdir / 'sphinx.pot').isfile()
|
||||
|
||||
result = (app.outdir / 'sphinx.pot').text(encoding='utf-8')
|
||||
assert re.search(
|
||||
('msgid "Template 1".*'
|
||||
'msgid "This is Template 1\.".*'
|
||||
'msgid "Template 2".*'
|
||||
'msgid "This is Template 2\.".*'),
|
||||
result,
|
||||
flags=re.S)
|
||||
|
@ -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',
|
||||
|
Loading…
Reference in New Issue
Block a user