From de356149cda6076555fbff768590aa1ab483fec1 Mon Sep 17 00:00:00 2001 From: Anselm Kruis Date: Fri, 5 Feb 2016 17:15:27 +0100 Subject: [PATCH 001/275] Test for bug #2298: automodule fails to document a class attribute This test case demonstrates a bug, where automodule:: with option :members: fails to document a class attribute of a class, that was imported into the documented module. This commit extends test_ext_viewcode, instead of creating a separate test module, because the development guide recommends it for performance reasons. --- tests/roots/test-ext-viewcode/index.rst | 5 +++++ tests/roots/test-ext-viewcode/spam/mod1.py | 7 +++++++ tests/roots/test-ext-viewcode/spam/mod3.py | 2 ++ tests/test_ext_viewcode.py | 6 ++++++ 4 files changed, 20 insertions(+) create mode 100644 tests/roots/test-ext-viewcode/spam/mod3.py diff --git a/tests/roots/test-ext-viewcode/index.rst b/tests/roots/test-ext-viewcode/index.rst index b5776cfa7..e7956e723 100644 --- a/tests/roots/test-ext-viewcode/index.rst +++ b/tests/roots/test-ext-viewcode/index.rst @@ -28,6 +28,11 @@ viewcode :language: python :pyobject: func1 +.. autoclass:: spam.mod3.Class3 + :members: + +.. automodule:: spam.mod3 + :members: .. toctree:: diff --git a/tests/roots/test-ext-viewcode/spam/mod1.py b/tests/roots/test-ext-viewcode/spam/mod1.py index 7133fc829..226f0c8a2 100644 --- a/tests/roots/test-ext-viewcode/spam/mod1.py +++ b/tests/roots/test-ext-viewcode/spam/mod1.py @@ -13,3 +13,10 @@ class Class1(object): """ this is Class1 """ + +class Class3(object): + """ + this is Class3 + """ + class_attr = 42 + """this is the class attribute class_attr""" diff --git a/tests/roots/test-ext-viewcode/spam/mod3.py b/tests/roots/test-ext-viewcode/spam/mod3.py new file mode 100644 index 000000000..f7b6afbe0 --- /dev/null +++ b/tests/roots/test-ext-viewcode/spam/mod3.py @@ -0,0 +1,2 @@ +from spam.mod1 import Class3 +__all__ = ('Class3',) diff --git a/tests/test_ext_viewcode.py b/tests/test_ext_viewcode.py index 93e681a5d..eaa7a736d 100644 --- a/tests/test_ext_viewcode.py +++ b/tests/test_ext_viewcode.py @@ -31,6 +31,12 @@ def test_viewcode(app, status, warning): assert result.count('href="_modules/spam/mod1.html#Class1"') == 2 assert result.count('href="_modules/spam/mod2.html#Class2"') == 2 + # test that the class attribute is correctly documented + assert result.count('this is Class3') == 2 + assert 'this is the class attribute class_attr' in result + # the next assert fails, until the autodoc bug gets fixed + assert result.count('this is the class attribute class_attr') == 2 + @with_app(testroot='ext-viewcode', tags=['test_linkcode']) def test_linkcode(app, status, warning): From c44608234d5eb8821f7b3c204b52fdcce0823cd2 Mon Sep 17 00:00:00 2001 From: Anselm Kruis Date: Fri, 5 Feb 2016 17:56:25 +0100 Subject: [PATCH 002/275] Fix #2298 automodule fails to document a class attribute. This commit adds the method ClassDocumenter.generate. This method calls the implementation from the super class without passing the optional argument real_modname. This causes Documenter.generate() to use the module of the imported class. Why is this change save: if the class can't be imported in Documenter.generate(), Documenter.generate() returns early and the module name is not used. If Documenter.generate() can import the class, Documenter.get_real_modname() always returns a module name. --- sphinx/ext/autodoc.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index f906d9666..095dea93b 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -1193,6 +1193,17 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): return ModuleLevelDocumenter.document_members(self, all_members) + def generate(self, more_content=None, real_modname=None, + check_module=False, all_members=False): + # Do not pass real_modname and use the name from the __module__ + # attribute of the class. + # If a class gets imported into the module real_modname + # the analyzer won't find the source of the class, if + # it looks in real_modname. + return super(ClassDocumenter, self).generate(more_content=more_content, + check_module=check_module, + all_members=all_members) + class ExceptionDocumenter(ClassDocumenter): """ From 72e70b1b361a649f1e81ed4ed29cbb8a31024563 Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Thu, 21 Jan 2016 11:13:29 +0200 Subject: [PATCH 003/275] Add tests for sphinx.ext.inheritance_diagram --- AUTHORS | 1 + CHANGES | 1 + .../roots/test-inheritance/basic_diagram.rst | 5 ++ tests/roots/test-inheritance/conf.py | 6 ++ tests/roots/test-inheritance/contents.rst | 4 ++ .../test-inheritance/diagram_w_parts.rst | 7 ++ .../roots/test-inheritance/dummy/__init__.py | 0 tests/roots/test-inheritance/dummy/test.py | 30 +++++++++ tests/test_ext_inheritance.py | 67 +++++++++++++++++++ 9 files changed, 121 insertions(+) create mode 100644 tests/roots/test-inheritance/basic_diagram.rst create mode 100644 tests/roots/test-inheritance/conf.py create mode 100644 tests/roots/test-inheritance/contents.rst create mode 100644 tests/roots/test-inheritance/diagram_w_parts.rst create mode 100644 tests/roots/test-inheritance/dummy/__init__.py create mode 100644 tests/roots/test-inheritance/dummy/test.py create mode 100644 tests/test_ext_inheritance.py diff --git a/AUTHORS b/AUTHORS index 580feeb32..bafe242e8 100644 --- a/AUTHORS +++ b/AUTHORS @@ -18,6 +18,7 @@ Other co-maintainers: Other contributors, listed alphabetically, are: * Alastair Houghton -- Apple Help builder +* Alexander Todorov -- inheritance_diagram tests and improvements * Andi Albrecht -- agogo theme * Jakob Lykke Andersen -- Rewritten C++ domain * Henrique Bastos -- SVG support for graphviz extension diff --git a/CHANGES b/CHANGES index 85b660775..30d6a5aae 100644 --- a/CHANGES +++ b/CHANGES @@ -52,6 +52,7 @@ Bugs fixed Testing -------- +* Add tests for the ``sphinx.ext.inheritance_diagram`` extension. Release 1.6.3 (in development) ============================== diff --git a/tests/roots/test-inheritance/basic_diagram.rst b/tests/roots/test-inheritance/basic_diagram.rst new file mode 100644 index 000000000..4c3838e65 --- /dev/null +++ b/tests/roots/test-inheritance/basic_diagram.rst @@ -0,0 +1,5 @@ +Basic Diagram +============== + +.. inheritance-diagram:: + dummy.test diff --git a/tests/roots/test-inheritance/conf.py b/tests/roots/test-inheritance/conf.py new file mode 100644 index 000000000..f1ddb4ad6 --- /dev/null +++ b/tests/roots/test-inheritance/conf.py @@ -0,0 +1,6 @@ +import sys, os + +sys.path.insert(0, os.path.abspath('.')) + +extensions = ['sphinx.ext.inheritance_diagram'] +source_suffix = '.rst' diff --git a/tests/roots/test-inheritance/contents.rst b/tests/roots/test-inheritance/contents.rst new file mode 100644 index 000000000..db4fbacb8 --- /dev/null +++ b/tests/roots/test-inheritance/contents.rst @@ -0,0 +1,4 @@ +.. toctree:: + :glob: + + * diff --git a/tests/roots/test-inheritance/diagram_w_parts.rst b/tests/roots/test-inheritance/diagram_w_parts.rst new file mode 100644 index 000000000..65a831802 --- /dev/null +++ b/tests/roots/test-inheritance/diagram_w_parts.rst @@ -0,0 +1,7 @@ +Diagram using the parts option +============================== + +.. inheritance-diagram:: + dummy.test + :parts: 1 + diff --git a/tests/roots/test-inheritance/dummy/__init__.py b/tests/roots/test-inheritance/dummy/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/roots/test-inheritance/dummy/test.py b/tests/roots/test-inheritance/dummy/test.py new file mode 100644 index 000000000..cafa07886 --- /dev/null +++ b/tests/roots/test-inheritance/dummy/test.py @@ -0,0 +1,30 @@ +""" + + Test with a class diagram like this:: + + A + / \ + B C + / \ / \ + E D F + +""" + +class A(object): + pass + +class B(A): + pass + +class C(A): + pass + +class D(B, C): + pass + +class E(B): + pass + +class F(C): + pass + diff --git a/tests/test_ext_inheritance.py b/tests/test_ext_inheritance.py new file mode 100644 index 000000000..ce4b50a56 --- /dev/null +++ b/tests/test_ext_inheritance.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +""" + test_inheritance + ~~~~~~~~~~~~~~~~ + + Tests for :mod:`sphinx.ext.inheritance_diagram` module. + + :copyright: Copyright 2015 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import os +import pytest +from sphinx.ext.inheritance_diagram import InheritanceDiagram + +@pytest.mark.sphinx(buildername="html", testroot="inheritance") +@pytest.mark.usefixtures('if_graphviz_found') +def test_inheritance_diagram(app, status, warning): + # monkey-patch InheritaceDiagram.run() so we can get access to its + # results. + orig_run = InheritanceDiagram.run + graphs = {} + + def new_run(self): + result = orig_run(self) + node = result[0] + source = os.path.basename(node.document.current_source).replace(".rst", "") + graphs[source] = node['graph'] + return result + + InheritanceDiagram.run = new_run + + try: + app.builder.build_all() + finally: + InheritanceDiagram.run = orig_run + + assert app.statuscode == 0 + + html_warnings = warning.getvalue() + assert html_warnings == "" + + # note: it is better to split these asserts into separate test functions + # but I can't figure out how to build only a specific .rst file + + # basic inheritance diagram showing all classes + for cls in graphs['basic_diagram'].class_info: + # use in b/c traversing order is different sometimes + assert cls in [ + ('dummy.test.A', 'dummy.test.A', [], None), + ('dummy.test.F', 'dummy.test.F', ['dummy.test.C'], None), + ('dummy.test.C', 'dummy.test.C', ['dummy.test.A'], None), + ('dummy.test.E', 'dummy.test.E', ['dummy.test.B'], None), + ('dummy.test.D', 'dummy.test.D', ['dummy.test.B', 'dummy.test.C'], None), + ('dummy.test.B', 'dummy.test.B', ['dummy.test.A'], None) + ] + + # inheritance diagram using :parts: 1 option + for cls in graphs['diagram_w_parts'].class_info: + assert cls in [ + ('A', 'dummy.test.A', [], None), + ('F', 'dummy.test.F', ['C'], None), + ('C', 'dummy.test.C', ['A'], None), + ('E', 'dummy.test.E', ['B'], None), + ('D', 'dummy.test.D', ['B', 'C'], None), + ('B', 'dummy.test.B', ['A'], None) + ] From 9486f0d8f78c5683ed4df2015fd42b24ab147ab8 Mon Sep 17 00:00:00 2001 From: "Mr. Senko" Date: Thu, 21 Jan 2016 11:11:06 +0200 Subject: [PATCH 004/275] Add top-classes option to sphinx.ext.inheritance_diagram This will limit the scope of inheritance traversal --- CHANGES | 4 ++ doc/ext/inheritance.rst | 52 ++++++++++++++ sphinx/ext/inheritance_diagram.py | 26 +++++-- .../diagram_module_w_2_top_classes.rst | 6 ++ .../diagram_w_1_top_class.rst | 7 ++ .../diagram_w_2_top_classes.rst | 9 +++ tests/test_ext_inheritance.py | 68 ++++++++++++++++++- 7 files changed, 165 insertions(+), 7 deletions(-) create mode 100644 tests/roots/test-inheritance/diagram_module_w_2_top_classes.rst create mode 100644 tests/roots/test-inheritance/diagram_w_1_top_class.rst create mode 100644 tests/roots/test-inheritance/diagram_w_2_top_classes.rst diff --git a/CHANGES b/CHANGES index 30d6a5aae..67db95381 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,8 @@ Features added * C++, add a ``cpp:expr`` role for inserting inline C++ expressions or types. * #3638: Allow to change a label of reference to equation using ``math_eqref_format`` +* Add ``top-classes`` option for the ``sphinx.ext.inheritance_diagram`` + extension to limit the scope of inheritance graphs. Features removed ---------------- @@ -52,8 +54,10 @@ Bugs fixed Testing -------- + * Add tests for the ``sphinx.ext.inheritance_diagram`` extension. + Release 1.6.3 (in development) ============================== diff --git a/doc/ext/inheritance.rst b/doc/ext/inheritance.rst index bd287aa49..4a8a3c0f1 100644 --- a/doc/ext/inheritance.rst +++ b/doc/ext/inheritance.rst @@ -42,6 +42,58 @@ It adds this directive: .. versionchanged:: 1.5 Added ``caption`` option + It also supports a ``top-classes`` option which requires one or more class + names separated by comma. If specified inheritance traversal will stop at the + specified class names. Given the following Python module:: + + """ + A + / \ + B C + / \ / \ + E D F + """ + + class A(object): + pass + + class B(A): + pass + + class C(A): + pass + + class D(B, C): + pass + + class E(B): + pass + + class F(C): + pass + + If you have specified a module in the inheritance diagram like this:: + + .. inheritance-diagram:: + dummy.test + :top-classes: dummy.test.B, dummy.test.C + + any base classes which are ancestors to ``top-classes`` and are also defined + in the same module will be rendered as stand alone nodes. In this example + class A will be rendered as stand alone node in the graph. This is a known + issue due to how this extension works internally. + + If you don't want class A (or any other ancestors) to be visible then specify + only the classes you would like to generate the diagram for like this:: + + .. inheritance-diagram:: + dummy.test.D + dummy.test.E + dummy.test.F + :top-classes: dummy.test.B, dummy.test.C + + .. versionchanged:: 1.7 + Added ``top-classes`` option to limit the scope of inheritance graphs. New config values are: diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py index f5b0228a5..7ba972f9f 100644 --- a/sphinx/ext/inheritance_diagram.py +++ b/sphinx/ext/inheritance_diagram.py @@ -133,8 +133,8 @@ class InheritanceGraph(object): graphviz dot graph from them. """ def __init__(self, class_names, currmodule, show_builtins=False, - private_bases=False, parts=0): - # type: (unicode, str, bool, bool, int) -> None + private_bases=False, parts=0, top_classes=[]): + # type: (unicode, str, bool, bool, int, List[Any]) -> None """*class_names* is a list of child classes to show bases from. If *show_builtins* is True, then Python builtins will be shown @@ -143,7 +143,7 @@ class InheritanceGraph(object): self.class_names = class_names classes = self._import_classes(class_names, currmodule) self.class_info = self._class_info(classes, show_builtins, - private_bases, parts) + private_bases, parts, top_classes) if not self.class_info: raise InheritanceException('No classes found for ' 'inheritance diagram') @@ -156,13 +156,16 @@ class InheritanceGraph(object): classes.extend(import_classes(name, currmodule)) return classes - def _class_info(self, classes, show_builtins, private_bases, parts): - # type: (List[Any], bool, bool, int) -> List[Tuple[unicode, unicode, List[unicode], unicode]] # NOQA + def _class_info(self, classes, show_builtins, private_bases, parts, top_classes): + # type: (List[Any], bool, bool, int, List[Any]) -> List[Tuple[unicode, unicode, List[unicode], unicode]] # NOQA """Return name and bases for all classes that are ancestors of *classes*. *parts* gives the number of dotted name parts that is removed from the displayed node names. + + *top_classes* gives the name(s) of the top most ancestor class to traverse + to. Multiple names can be specified separated by comma. """ all_classes = {} py_builtins = vars(builtins).values() @@ -192,6 +195,10 @@ class InheritanceGraph(object): baselist = [] # type: List[unicode] all_classes[cls] = (nodename, fullname, baselist, tooltip) + + if fullname in top_classes: + return + for base in cls.__bases__: if not show_builtins and base in py_builtins: continue @@ -321,6 +328,7 @@ class InheritanceDiagram(Directive): 'parts': directives.nonnegative_int, 'private-bases': directives.flag, 'caption': directives.unchanged, + 'top-classes': directives.unchanged_required, } def run(self): @@ -333,13 +341,19 @@ class InheritanceDiagram(Directive): # Store the original content for use as a hash node['parts'] = self.options.get('parts', 0) node['content'] = ', '.join(class_names) + node['top-classes'] = [] + for cls in self.options.get('top-classes', '').split(','): + cls = cls.strip() + if cls: + node['top-classes'].append(cls) # Create a graph starting with the list of classes try: graph = InheritanceGraph( class_names, env.ref_context.get('py:module'), parts=node['parts'], - private_bases='private-bases' in self.options) + private_bases='private-bases' in self.options, + top_classes=node['top-classes']) except InheritanceException as err: return [node.document.reporter.warning(err.args[0], line=self.lineno)] diff --git a/tests/roots/test-inheritance/diagram_module_w_2_top_classes.rst b/tests/roots/test-inheritance/diagram_module_w_2_top_classes.rst new file mode 100644 index 000000000..cc4365e9c --- /dev/null +++ b/tests/roots/test-inheritance/diagram_module_w_2_top_classes.rst @@ -0,0 +1,6 @@ +Diagram using module with 2 top classes +======================================= + +.. inheritance-diagram:: + dummy.test + :top-classes: dummy.test.B, dummy.test.C diff --git a/tests/roots/test-inheritance/diagram_w_1_top_class.rst b/tests/roots/test-inheritance/diagram_w_1_top_class.rst new file mode 100644 index 000000000..97da82557 --- /dev/null +++ b/tests/roots/test-inheritance/diagram_w_1_top_class.rst @@ -0,0 +1,7 @@ +Diagram using 1 top class +========================= + +.. inheritance-diagram:: + dummy.test + :top-classes: dummy.test.B + diff --git a/tests/roots/test-inheritance/diagram_w_2_top_classes.rst b/tests/roots/test-inheritance/diagram_w_2_top_classes.rst new file mode 100644 index 000000000..8a6ae5865 --- /dev/null +++ b/tests/roots/test-inheritance/diagram_w_2_top_classes.rst @@ -0,0 +1,9 @@ +Diagram using 2 top classes +=========================== + +.. inheritance-diagram:: + dummy.test.F + dummy.test.D + dummy.test.E + :top-classes: dummy.test.B, dummy.test.C + diff --git a/tests/test_ext_inheritance.py b/tests/test_ext_inheritance.py index ce4b50a56..fcf313a30 100644 --- a/tests/test_ext_inheritance.py +++ b/tests/test_ext_inheritance.py @@ -13,6 +13,7 @@ import os import pytest from sphinx.ext.inheritance_diagram import InheritanceDiagram + @pytest.mark.sphinx(buildername="html", testroot="inheritance") @pytest.mark.usefixtures('if_graphviz_found') def test_inheritance_diagram(app, status, warning): @@ -51,7 +52,8 @@ def test_inheritance_diagram(app, status, warning): ('dummy.test.F', 'dummy.test.F', ['dummy.test.C'], None), ('dummy.test.C', 'dummy.test.C', ['dummy.test.A'], None), ('dummy.test.E', 'dummy.test.E', ['dummy.test.B'], None), - ('dummy.test.D', 'dummy.test.D', ['dummy.test.B', 'dummy.test.C'], None), + ('dummy.test.D', 'dummy.test.D', + ['dummy.test.B', 'dummy.test.C'], None), ('dummy.test.B', 'dummy.test.B', ['dummy.test.A'], None) ] @@ -65,3 +67,67 @@ def test_inheritance_diagram(app, status, warning): ('D', 'dummy.test.D', ['B', 'C'], None), ('B', 'dummy.test.B', ['A'], None) ] + + # inheritance diagram with 1 top class + # :top-classes: dummy.test.B + # rendering should be + # A + # \ + # B C + # / \ / \ + # E D F + # + for cls in graphs['diagram_w_1_top_class'].class_info: + assert cls in [ + ('dummy.test.A', 'dummy.test.A', [], None), + ('dummy.test.F', 'dummy.test.F', ['dummy.test.C'], None), + ('dummy.test.C', 'dummy.test.C', ['dummy.test.A'], None), + ('dummy.test.E', 'dummy.test.E', ['dummy.test.B'], None), + ('dummy.test.D', 'dummy.test.D', + ['dummy.test.B', 'dummy.test.C'], None), + ('dummy.test.B', 'dummy.test.B', [], None) + ] + + + # inheritance diagram with 2 top classes + # :top-classes: dummy.test.B, dummy.test.C + # Note: we're specifying separate classes, not the entire module here + # rendering should be + # + # B C + # / \ / \ + # E D F + # + for cls in graphs['diagram_w_2_top_classes'].class_info: + assert cls in [ + ('dummy.test.F', 'dummy.test.F', ['dummy.test.C'], None), + ('dummy.test.C', 'dummy.test.C', [], None), + ('dummy.test.E', 'dummy.test.E', ['dummy.test.B'], None), + ('dummy.test.D', 'dummy.test.D', + ['dummy.test.B', 'dummy.test.C'], None), + ('dummy.test.B', 'dummy.test.B', [], None) + ] + + # inheritance diagram with 2 top classes and specifiying the entire module + # rendering should be + # + # A + # B C + # / \ / \ + # E D F + # + # Note: dummy.test.A is included in the graph before its descendants are even processed + # b/c we've specified to load the entire module. The way InheritanceGraph works it is very + # hard to exclude parent classes once after they have been included in the graph. + # If you'd like to not show class A in the graph don't specify the entire module. + # this is a known issue. + for cls in graphs['diagram_module_w_2_top_classes'].class_info: + assert cls in [ + ('dummy.test.F', 'dummy.test.F', ['dummy.test.C'], None), + ('dummy.test.C', 'dummy.test.C', [], None), + ('dummy.test.E', 'dummy.test.E', ['dummy.test.B'], None), + ('dummy.test.D', 'dummy.test.D', + ['dummy.test.B', 'dummy.test.C'], None), + ('dummy.test.B', 'dummy.test.B', [], None), + ('dummy.test.A', 'dummy.test.A', [], None), + ] From 7fc43d336574a305cd119981256e93d7a4a2ce7e Mon Sep 17 00:00:00 2001 From: Oliver Jahn Date: Thu, 5 Oct 2017 12:41:05 -0400 Subject: [PATCH 005/275] use numfig for numbering equations by section rather than page --- CHANGES | 1 + doc/ext/math.rst | 8 ++++++++ sphinx/ext/imgmath.py | 4 +++- sphinx/ext/jsmath.py | 4 +++- sphinx/ext/mathbase.py | 24 +++++++++++++++++++++++- sphinx/ext/mathjax.py | 4 +++- sphinx/ext/pngmath.py | 4 +++- 7 files changed, 44 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 957881a53..6e203777f 100644 --- a/CHANGES +++ b/CHANGES @@ -37,6 +37,7 @@ Features added * #4052: viewcode: Sort before highlighting module code * #1448: qthelp: Add new config value; :confval:`qthelp_namespace` * #4140: html themes: Make body tag inheritable +* #3991, #4080: Add :confval:`math_numfig` for equation numbering by section Features removed diff --git a/doc/ext/math.rst b/doc/ext/math.rst index 54d77ed6c..fe7b85c83 100644 --- a/doc/ext/math.rst +++ b/doc/ext/math.rst @@ -44,6 +44,14 @@ or use Python raw strings (``r"raw"``). Example: ``'Eq.{number}'`` is rendered as ``Eq.10`` +.. confval:: math_numfig + + If ``True``, displayed math equations are numbered across pages using numfig. + The :confval:`numfig` config value must be enabled and + :confval:`numfig_secnum_depth` is respected. The ``:eq:`` role must be used + to refererence these equation numbers, not the ``:numref:`` role. + Default is ``False``. + :mod:`.mathbase` defines these new markup elements: .. rst:role:: math diff --git a/sphinx/ext/imgmath.py b/sphinx/ext/imgmath.py index 8bf4fcad5..04d6b708a 100644 --- a/sphinx/ext/imgmath.py +++ b/sphinx/ext/imgmath.py @@ -30,6 +30,7 @@ from sphinx.util.png import read_png_depth, write_png_depth from sphinx.util.osutil import ensuredir, ENOENT, cd from sphinx.util.pycompat import sys_encoding from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath +from sphinx.ext.mathbase import get_node_equation_number if False: # For type annotation @@ -333,7 +334,8 @@ def html_visit_displaymath(self, node): self.body.append(self.starttag(node, 'div', CLASS='math')) self.body.append('

') if node['number']: - self.body.append('(%s)' % node['number']) + number = get_node_equation_number(self.builder.env, node) + self.body.append('(%s)' % number) self.add_permalink_ref(node, _('Permalink to this equation')) self.body.append('') if fname is None: diff --git a/sphinx/ext/jsmath.py b/sphinx/ext/jsmath.py index dc57c13c6..978e3f3d6 100644 --- a/sphinx/ext/jsmath.py +++ b/sphinx/ext/jsmath.py @@ -16,6 +16,7 @@ import sphinx from sphinx.locale import _ from sphinx.application import ExtensionError from sphinx.ext.mathbase import setup_math as mathbase_setup +from sphinx.ext.mathbase import get_node_equation_number def html_visit_math(self, node): @@ -35,7 +36,8 @@ def html_visit_displaymath(self, node): if i == 0: # necessary to e.g. set the id property correctly if node['number']: - self.body.append('(%s)' % node['number']) + number = get_node_equation_number(self.builder.env, node) + self.body.append('(%s)' % number) self.add_permalink_ref(node, _('Permalink to this equation')) self.body.append('') self.body.append(self.starttag(node, 'div', CLASS='math')) diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py index f83ca5da8..31b33fe2a 100644 --- a/sphinx/ext/mathbase.py +++ b/sphinx/ext/mathbase.py @@ -84,6 +84,13 @@ class MathDomain(Domain): newnode['target'] = target return newnode else: + if env.config.math_numfig and env.config.numfig: + if docname in env.toc_fignumbers: + id = 'equation-' + target + number = env.toc_fignumbers[docname]['displaymath'].get(id, ()) + number = '.'.join(map(str, number)) + else: + number = '' try: eqref_format = env.config.math_eqref_format or "({number})" title = nodes.Text(eqref_format.format(number=number)) @@ -126,6 +133,20 @@ class MathDomain(Domain): return len(targets) + 1 +def get_node_equation_number(env, node): + if env.config.math_numfig and env.config.numfig: + docname = node['docname'] + if docname in env.toc_fignumbers: + id = node['ids'][0] + number = env.toc_fignumbers[docname]['displaymath'].get(id, ()) + number = '.'.join(map(str, number)) + else: + number = '' + else: + number = node['number'] + return number + + def wrap_displaymath(math, label, numbering): # type: (unicode, unicode, bool) -> unicode def is_equation(part): @@ -341,6 +362,7 @@ def setup_math(app, htmlinlinevisitors, htmldisplayvisitors): # type: (Sphinx, Tuple[Callable, Any], Tuple[Callable, Any]) -> None app.add_config_value('math_number_all', False, 'env') app.add_config_value('math_eqref_format', None, 'env', string_classes) + app.add_config_value('math_numfig', False, 'env') app.add_domain(MathDomain) app.add_node(math, override=True, latex=(latex_visit_math, None), @@ -348,7 +370,7 @@ def setup_math(app, htmlinlinevisitors, htmldisplayvisitors): man=(man_visit_math, None), texinfo=(texinfo_visit_math, None), html=htmlinlinevisitors) - app.add_node(displaymath, + app.add_enumerable_node(displaymath, 'displaymath', latex=(latex_visit_displaymath, None), text=(text_visit_displaymath, None), man=(man_visit_displaymath, man_depart_displaymath), diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py index f25f91e74..aff5c103b 100644 --- a/sphinx/ext/mathjax.py +++ b/sphinx/ext/mathjax.py @@ -17,6 +17,7 @@ import sphinx from sphinx.locale import _ from sphinx.errors import ExtensionError from sphinx.ext.mathbase import setup_math as mathbase_setup +from sphinx.ext.mathbase import get_node_equation_number def html_visit_math(self, node): @@ -36,7 +37,8 @@ def html_visit_displaymath(self, node): # necessary to e.g. set the id property correctly if node['number']: - self.body.append('(%s)' % node['number']) + number = get_node_equation_number(self.builder.env, node) + self.body.append('(%s)' % number) self.add_permalink_ref(node, _('Permalink to this equation')) self.body.append('') self.body.append(self.builder.config.mathjax_display[0]) diff --git a/sphinx/ext/pngmath.py b/sphinx/ext/pngmath.py index 85010b799..968139f15 100644 --- a/sphinx/ext/pngmath.py +++ b/sphinx/ext/pngmath.py @@ -30,6 +30,7 @@ from sphinx.util.png import read_png_depth, write_png_depth from sphinx.util.osutil import ensuredir, ENOENT, cd from sphinx.util.pycompat import sys_encoding from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath +from sphinx.ext.mathbase import get_node_equation_number if False: # For type annotation @@ -242,7 +243,8 @@ def html_visit_displaymath(self, node): self.body.append(self.starttag(node, 'div', CLASS='math')) self.body.append('

') if node['number']: - self.body.append('(%s)' % node['number']) + number = get_node_equation_number(self.builder.env, node) + self.body.append('(%s)' % number) if fname is None: # something failed -- use text-only as a bad substitute self.body.append('%s

\n' % From 783cff44b388faa15f277fe29c9a26e1a9e63700 Mon Sep 17 00:00:00 2001 From: Oliver Jahn Date: Thu, 5 Oct 2017 12:41:22 -0400 Subject: [PATCH 006/275] add tests for math_numfig --- tests/roots/test-ext-math/index.rst | 2 ++ tests/roots/test-ext-math/page.rst | 9 ++++++ tests/test_ext_math.py | 49 +++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+) create mode 100644 tests/roots/test-ext-math/page.rst diff --git a/tests/roots/test-ext-math/index.rst b/tests/roots/test-ext-math/index.rst index 9d16824f6..4237b73ff 100644 --- a/tests/roots/test-ext-math/index.rst +++ b/tests/roots/test-ext-math/index.rst @@ -2,8 +2,10 @@ Test Math ========= .. toctree:: + :numbered: 1 math + page .. math:: a^2+b^2=c^2 diff --git a/tests/roots/test-ext-math/page.rst b/tests/roots/test-ext-math/page.rst new file mode 100644 index 000000000..ef8040910 --- /dev/null +++ b/tests/roots/test-ext-math/page.rst @@ -0,0 +1,9 @@ +Test multiple pages +=================== + +.. math:: + :label: bar + + a = b + 1 + +Referencing equations :eq:`foo` and :eq:`bar`. diff --git a/tests/test_ext_math.py b/tests/test_ext_math.py index 92501a3db..1ff34cf79 100644 --- a/tests/test_ext_math.py +++ b/tests/test_ext_math.py @@ -139,3 +139,52 @@ def test_math_eqref_format_latex(app, status, warning): content = (app.outdir / 'test.tex').text() macro = r'Referencing equation Eq.\\ref{equation:math:foo}.' assert re.search(macro, content, re.S) + + +@pytest.mark.sphinx('html', testroot='ext-math', + confoverrides={'extensions': ['sphinx.ext.mathjax'], + 'numfig': True, + 'math_numfig': True}) +def test_mathjax_numfig_html(app, status, warning): + app.builder.build_all() + + content = (app.outdir / 'math.html').text() + html = ('
\n' + '(1.2)') + assert html in content + html = ('

Referencing equation (1.1).

') + assert html in content + + +@pytest.mark.sphinx('html', testroot='ext-math', + confoverrides={'extensions': ['sphinx.ext.jsmath'], + 'jsmath_path': 'dummy.js', + 'numfig': True, + 'math_numfig': True}) +def test_jsmath_numfig_html(app, status, warning): + app.builder.build_all() + + content = (app.outdir / 'math.html').text() + html = '(1.2)Referencing equation (1.1).

') + assert html in content + + +@pytest.mark.sphinx('html', testroot='ext-math', + confoverrides={'extensions': ['sphinx.ext.imgmath'], + 'numfig': True, + 'numfig_secnum_depth': 0, + 'math_numfig': True}) +def test_imgmath_numfig_html(app, status, warning): + app.builder.build_all() + + content = (app.outdir / 'page.html').text() + html = '(3)Referencing equations (1) and ' + '(3).

') + assert html in content From fa6dd3485d4cd23127215668d888151b38a87989 Mon Sep 17 00:00:00 2001 From: Oliver Jahn Date: Wed, 18 Oct 2017 17:38:13 -0400 Subject: [PATCH 007/275] fix indentation --- sphinx/ext/mathbase.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py index 31b33fe2a..313f72bd4 100644 --- a/sphinx/ext/mathbase.py +++ b/sphinx/ext/mathbase.py @@ -371,11 +371,11 @@ def setup_math(app, htmlinlinevisitors, htmldisplayvisitors): texinfo=(texinfo_visit_math, None), html=htmlinlinevisitors) app.add_enumerable_node(displaymath, 'displaymath', - latex=(latex_visit_displaymath, None), - text=(text_visit_displaymath, None), - man=(man_visit_displaymath, man_depart_displaymath), - texinfo=(texinfo_visit_displaymath, texinfo_depart_displaymath), - html=htmldisplayvisitors) + latex=(latex_visit_displaymath, None), + text=(text_visit_displaymath, None), + man=(man_visit_displaymath, man_depart_displaymath), + texinfo=(texinfo_visit_displaymath, texinfo_depart_displaymath), + html=htmldisplayvisitors) app.add_node(eqref, latex=(latex_visit_eqref, None)) app.add_role('math', math_role) app.add_role('eq', EqXRefRole(warn_dangling=True)) From 9aac2420d3840873928e2af29452b0cca5e60ff1 Mon Sep 17 00:00:00 2001 From: lucdanton Date: Wed, 25 Oct 2017 22:41:42 +0200 Subject: [PATCH 008/275] C++: remove function concepts. --- CHANGES | 1 + doc/domains.rst | 17 +++-------------- sphinx/domains/cpp.py | 26 ++++---------------------- tests/test_domain_cpp.py | 4 ---- 4 files changed, 8 insertions(+), 40 deletions(-) diff --git a/CHANGES b/CHANGES index 1d10d01fd..ebeffec52 100644 --- a/CHANGES +++ b/CHANGES @@ -68,6 +68,7 @@ Features removed * ``sphinx.util.nodes.process_only_nodes()`` * LaTeX environment ``notice``, use ``sphinxadmonition`` instead * LaTeX ``\sphinxstylethead``, use ``\sphinxstyletheadfamily`` +* C++, support of function concepts Bugs fixed ---------- diff --git a/doc/domains.rst b/doc/domains.rst index 1697c6605..e6a860bcd 100644 --- a/doc/domains.rst +++ b/doc/domains.rst @@ -720,13 +720,12 @@ a visibility statement (``public``, ``private`` or ``protected``). .. rst:directive:: .. cpp:concept:: template-parameter-list name - .. cpp:concept:: template-parameter-list name() .. warning:: The support for concepts is experimental. It is based on the Concepts Technical Specification, and the features may change as the TS evolves. - Describe a variable concept or a function concept. Both must have exactly 1 - template parameter list. The name may be a nested name. Examples:: + Describe a concept. It must have exactly 1 template parameter list. The name may be a + nested name. Example:: .. cpp:concept:: template std::Iterator @@ -744,12 +743,7 @@ a visibility statement (``public``, ``private`` or ``protected``). - :cpp:expr:`*r`, when :cpp:expr:`r` is dereferenceable. - :cpp:expr:`++r`, with return type :cpp:expr:`It&`, when :cpp:expr:`r` is incrementable. - .. cpp:concept:: template std::Container() - - Holder of elements, to which it can provide access via - :cpp:concept:`Iterator` s. - - They will render as follows: + This will render as follows: .. cpp:concept:: template std::Iterator @@ -767,11 +761,6 @@ a visibility statement (``public``, ``private`` or ``protected``). - :cpp:expr:`*r`, when :cpp:expr:`r` is dereferenceable. - :cpp:expr:`++r`, with return type :cpp:expr:`It&`, when :cpp:expr:`r` is incrementable. - .. cpp:concept:: template std::Container() - - Holder of elements, to which it can provide access via - :cpp:concept:`Iterator` s. - Options ....... diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 1db374205..a1b0a71c3 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -224,13 +224,12 @@ logger = logging.getLogger(__name__) concept_object: goal: just a declaration of the name (for now) - either a variable concept or function concept grammar: only a single template parameter list, and the nested name may not have any template argument lists "template" "<" template-parameter-list ">" - nested-name-specifier "()"[opt] + nested-name-specifier type_object: goal: @@ -2780,10 +2779,9 @@ class ASTTypeUsing(ASTBase): class ASTConcept(ASTBase): - def __init__(self, nestedName, isFunction, initializer): - # type: (Any, bool, Any) -> None + def __init__(self, nestedName, initializer): + # type: (Any, Any) -> None self.nestedName = nestedName - self.isFunction = isFunction # otherwise it's a variable concept self.initializer = initializer @property @@ -2800,18 +2798,13 @@ class ASTConcept(ASTBase): def __unicode__(self): # type: () -> unicode res = text_type(self.nestedName) - if self.isFunction: - res += "()" if self.initializer: res += text_type(self.initializer) return res def describe_signature(self, signode, mode, env, symbol): # type: (addnodes.desc_signature, unicode, BuildEnvironment, Symbol) -> None - signode += nodes.Text(text_type("bool ")) self.nestedName.describe_signature(signode, mode, env, symbol) - if self.isFunction: - signode += nodes.Text("()") if self.initializer: self.initializer.describe_signature(signode, mode, env, symbol) @@ -4718,20 +4711,9 @@ class DefinitionParser(object): def _parse_concept(self): # type: () -> ASTConcept nestedName = self._parse_nested_name() - isFunction = False - self.skip_ws() - if self.skip_string('('): - isFunction = True - self.skip_ws() - if not self.skip_string(')'): - self.fail("Expected ')' in function concept declaration.") - initializer = self._parse_initializer('member') - if initializer and isFunction: - self.fail("Function concept with initializer.") - - return ASTConcept(nestedName, isFunction, initializer) + return ASTConcept(nestedName, initializer) def _parse_class(self): # type: () -> ASTClass diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py index 8c0fae2e3..63682237f 100644 --- a/tests/test_domain_cpp.py +++ b/tests/test_domain_cpp.py @@ -231,10 +231,6 @@ def test_concept_definitions(): {2:'I0EN1A1B7ConceptE'}) check('concept', 'template Foo', {2:'I00DpE3Foo'}) - check('concept', 'template A::B::Concept()', - {2:'I0EN1A1B7ConceptE'}) - check('concept', 'template Foo()', - {2:'I00DpE3Foo'}) with pytest.raises(DefinitionError): parse('concept', 'Foo') with pytest.raises(DefinitionError): From c05c4d19106bf4ffbd827e523f67e80f7620c13d Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 20 Mar 2017 23:10:10 +0900 Subject: [PATCH 009/275] Add BuildEnvironment.write_doctree() --- sphinx/environment/__init__.py | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index d438b7c0f..e3f5201f1 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -756,24 +756,12 @@ class BuildEnvironment(object): list(merge_doctrees( old_doctree, doctree, self.versioning_condition)) - # make it picklable - doctree.reporter = None - doctree.transformer = None - doctree.settings.warning_stream = None - doctree.settings.env = None - doctree.settings.record_dependencies = None - # cleanup self.temp_data.clear() self.ref_context.clear() roles._roles.pop('', None) # if a document has set a local default role - # save the parsed doctree - doctree_filename = self.doc2path(docname, self.doctreedir, - '.doctree') - ensuredir(path.dirname(doctree_filename)) - with open(doctree_filename, 'wb') as f: - pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL) + self.write_doctree(docname, doctree) # utilities to use while reading a document @@ -877,6 +865,21 @@ class BuildEnvironment(object): doctree.reporter = Reporter(self.doc2path(docname), 2, 5, stream=WarningStream()) return doctree + def write_doctree(self, docname, doctree): + # type: (unicode, nodes.Node) -> None + """Write the doctree to a file.""" + # make it picklable + doctree.reporter = None + doctree.transformer = None + doctree.settings.warning_stream = None + doctree.settings.env = None + doctree.settings.record_dependencies = None + + doctree_filename = self.doc2path(docname, self.doctreedir, '.doctree') + ensuredir(path.dirname(doctree_filename)) + with open(doctree_filename, 'wb') as f: + pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL) + def get_and_resolve_doctree(self, docname, builder, doctree=None, prune_toctrees=True, includehidden=False): # type: (unicode, Builder, nodes.Node, bool, bool) -> nodes.Node From 07220140ac18894d6102042ba3633df985df4942 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 31 Oct 2017 23:04:24 +0900 Subject: [PATCH 010/275] Add BuildEnvironment.prepare_settings() --- sphinx/environment/__init__.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index e3f5201f1..666d29129 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -663,10 +663,9 @@ class BuildEnvironment(object): location=(self.docname, lineno)) return (u'?', error.end) - def read_doc(self, docname, app=None): - # type: (unicode, Sphinx) -> None - """Parse a file and add/update inventory entries for the doctree.""" - + def prepare_settings(self, docname): + """Prepare to set up environment for reading.""" + # type: (unicode) -> None self.temp_data['docname'] = docname # defaults to the global default, but can be re-set in a document self.temp_data['default_role'] = self.config.default_role @@ -688,6 +687,11 @@ class BuildEnvironment(object): else: self.settings['smart_quotes'] = False + def read_doc(self, docname, app=None): + # type: (unicode, Sphinx) -> None + """Parse a file and add/update inventory entries for the doctree.""" + self.prepare_settings(docname) + docutilsconf = path.join(self.srcdir, 'docutils.conf') # read docutils.conf from source dir, not from current dir OptionParser.standard_config_files[1] = docutilsconf From d23f29f301648ba9f84641fb44ebab43b07deb48 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 31 Oct 2017 23:04:24 +0900 Subject: [PATCH 011/275] Refactor publishment --- sphinx/environment/__init__.py | 19 ++++++++++--------- sphinx/io.py | 5 +++++ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index 666d29129..8897f1d33 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -33,7 +33,9 @@ from docutils.parsers.rst.languages import en as english from docutils.frontend import OptionParser from sphinx import addnodes -from sphinx.io import SphinxStandaloneReader, SphinxDummyWriter, SphinxFileInput +from sphinx.io import ( + SphinxStandaloneReader, SphinxDummySourceClass, SphinxDummyWriter, SphinxFileInput +) from sphinx.util import logging from sphinx.util import get_matching_docs, FilenameUniqDict, status_iterator from sphinx.util.nodes import is_translatable @@ -713,17 +715,16 @@ class BuildEnvironment(object): # publish manually reader = SphinxStandaloneReader(self.app, parsers=self.app.registry.get_source_parsers()) - pub = Publisher(reader=reader, - writer=SphinxDummyWriter(), - destination_class=NullOutput) - pub.set_components(None, 'restructuredtext', None) - pub.process_programmatic_settings(None, self.settings, None) src_path = self.doc2path(docname) source = SphinxFileInput(app, self, source=None, source_path=src_path, encoding=self.config.source_encoding) - pub.source = source - pub.settings._source = src_path - pub.set_destination(None, None) + pub = Publisher(reader=reader, + writer=SphinxDummyWriter(), + source_class=SphinxDummySourceClass, + destination=NullOutput()) + pub.set_components(None, 'restructuredtext', None) + pub.process_programmatic_settings(None, self.settings, None) + pub.set_source(source, src_path) pub.publish() doctree = pub.document diff --git a/sphinx/io.py b/sphinx/io.py index 8813cb3b6..9b27e04fd 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -143,6 +143,11 @@ class SphinxDummyWriter(UnfilteredWriter): pass +def SphinxDummySourceClass(source, *args, **kwargs): + """Bypass source object as is to cheat Publisher.""" + return source + + class SphinxFileInput(FileInput): def __init__(self, app, env, *args, **kwds): # type: (Sphinx, BuildEnvironment, Any, Any) -> None From 1200ab48e1f24fcc8cf3232ae21c056ed6bca0f8 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 31 Oct 2017 23:04:25 +0900 Subject: [PATCH 012/275] Refactor parsing by docutils --- sphinx/environment/__init__.py | 23 ++--------------------- sphinx/io.py | 21 ++++++++++++++++++++- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index 8897f1d33..e8b157c3d 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -24,8 +24,6 @@ from collections import defaultdict from six import BytesIO, itervalues, class_types, next from six.moves import cPickle as pickle -from docutils.io import NullOutput -from docutils.core import Publisher from docutils.utils import Reporter, get_source_line, normalize_language_tag from docutils.utils.smartquotes import smartchars from docutils.parsers.rst import roles @@ -33,9 +31,7 @@ from docutils.parsers.rst.languages import en as english from docutils.frontend import OptionParser from sphinx import addnodes -from sphinx.io import ( - SphinxStandaloneReader, SphinxDummySourceClass, SphinxDummyWriter, SphinxFileInput -) +from sphinx.io import read_doc from sphinx.util import logging from sphinx.util import get_matching_docs, FilenameUniqDict, status_iterator from sphinx.util.nodes import is_translatable @@ -711,22 +707,7 @@ class BuildEnvironment(object): location=docname) codecs.register_error('sphinx', self.warn_and_replace) # type: ignore - - # publish manually - reader = SphinxStandaloneReader(self.app, - parsers=self.app.registry.get_source_parsers()) - src_path = self.doc2path(docname) - source = SphinxFileInput(app, self, source=None, source_path=src_path, - encoding=self.config.source_encoding) - pub = Publisher(reader=reader, - writer=SphinxDummyWriter(), - source_class=SphinxDummySourceClass, - destination=NullOutput()) - pub.set_components(None, 'restructuredtext', None) - pub.process_programmatic_settings(None, self.settings, None) - pub.set_source(source, src_path) - pub.publish() - doctree = pub.document + doctree = read_doc(self.app, self, self.doc2path(docname)) # post-processing for domain in itervalues(self.domains): diff --git a/sphinx/io.py b/sphinx/io.py index 9b27e04fd..ab8c9d068 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -8,7 +8,8 @@ :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ -from docutils.io import FileInput +from docutils.io import FileInput, NullOutput +from docutils.core import Publisher from docutils.readers import standalone from docutils.writers import UnfilteredWriter from six import string_types, text_type, iteritems @@ -185,3 +186,21 @@ class SphinxFileInput(FileInput): if self.env.config.rst_prolog: data = self.env.config.rst_prolog + '\n' + data return docinfo + data + + +def read_doc(app, env, filename): + """Parse a document and convert to doctree.""" + # type: (Sphinx, BuildEnvironment, unicode) -> nodes.document + reader = SphinxStandaloneReader(app, parsers=app.registry.get_source_parsers()) + source = SphinxFileInput(app, env, source=None, source_path=filename, + encoding=env.config.source_encoding) + + pub = Publisher(reader=reader, + writer=SphinxDummyWriter(), + source_class=SphinxDummySourceClass, + destination=NullOutput()) + pub.set_components(None, 'restructuredtext', None) + pub.process_programmatic_settings(None, env.settings, None) + pub.set_source(source, filename) + pub.publish() + return pub.document From f7dd8e94e2dca3ebb86acd4b1c00549b3c48a477 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 31 Oct 2017 23:04:25 +0900 Subject: [PATCH 013/275] Add default_role contextmanager to enable default-role temporarily --- sphinx/environment/__init__.py | 18 ++---------------- sphinx/util/rst.py | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index e8b157c3d..c8c2c4acd 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -26,13 +26,11 @@ from six.moves import cPickle as pickle from docutils.utils import Reporter, get_source_line, normalize_language_tag from docutils.utils.smartquotes import smartchars -from docutils.parsers.rst import roles -from docutils.parsers.rst.languages import en as english from docutils.frontend import OptionParser from sphinx import addnodes from sphinx.io import read_doc -from sphinx.util import logging +from sphinx.util import logging, rst from sphinx.util import get_matching_docs, FilenameUniqDict, status_iterator from sphinx.util.nodes import is_translatable from sphinx.util.osutil import SEP, ensuredir @@ -80,8 +78,6 @@ default_settings = { ENV_VERSION = 52 + (sys.version_info[0] - 2) -dummy_reporter = Reporter('', 4, 4) - versioning_conditions = { 'none': False, 'text': is_translatable, @@ -696,16 +692,7 @@ class BuildEnvironment(object): if path.isfile(docutilsconf): self.note_dependency(docutilsconf) - with sphinx_domains(self): - if self.config.default_role: - role_fn, messages = roles.role(self.config.default_role, english, - 0, dummy_reporter) - if role_fn: - roles._roles[''] = role_fn - else: - logger.warning('default role %s not found', self.config.default_role, - location=docname) - + with sphinx_domains(self), rst.default_role(docname, self.config.default_role): codecs.register_error('sphinx', self.warn_and_replace) # type: ignore doctree = read_doc(self.app, self, self.doc2path(docname)) @@ -745,7 +732,6 @@ class BuildEnvironment(object): # cleanup self.temp_data.clear() self.ref_context.clear() - roles._roles.pop('', None) # if a document has set a local default role self.write_doctree(docname, doctree) diff --git a/sphinx/util/rst.py b/sphinx/util/rst.py index 8186130cf..b77e75ebf 100644 --- a/sphinx/util/rst.py +++ b/sphinx/util/rst.py @@ -8,12 +8,37 @@ :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ +from __future__ import absolute_import import re +from contextlib import contextmanager + +from docutils.parsers.rst import roles +from docutils.parsers.rst.languages import en as english +from docutils.utils import Reporter + +from sphinx.util import logging symbols_re = re.compile(r'([!-/:-@\[-`{-~])') +logger = logging.getLogger(__name__) def escape(text): # type: (unicode) -> unicode return symbols_re.sub(r'\\\1', text) # type: ignore + + +@contextmanager +def default_role(docname, name): + # type: (unicode, unicode) -> None + if name: + dummy_reporter = Reporter('', 4, 4) + role_fn, _ = roles.role(name, english, 0, dummy_reporter) + if role_fn: + roles._roles[''] = role_fn + else: + logger.warning('default role %s not found', name, location=docname) + + yield + + roles._roles.pop('', None) # if a document has set a local default role From e2be2ca77f54897a00dd7dd60decfa34ae7b9a06 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 31 Oct 2017 23:04:26 +0900 Subject: [PATCH 014/275] Move env.warn_and_replace() to SphinxInput class --- sphinx/environment/__init__.py | 17 ----------------- sphinx/io.py | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index c8c2c4acd..76b360a0f 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -14,7 +14,6 @@ import os import sys import time import types -import codecs import fnmatch import warnings from os import path @@ -642,21 +641,6 @@ class BuildEnvironment(object): # --------- SINGLE FILE READING -------------------------------------------- - def warn_and_replace(self, error): - # type: (Any) -> Tuple - """Custom decoding error handler that warns and replaces.""" - linestart = error.object.rfind(b'\n', 0, error.start) - lineend = error.object.find(b'\n', error.start) - if lineend == -1: - lineend = len(error.object) - lineno = error.object.count(b'\n', 0, error.start) + 1 - logger.warning('undecodable source characters, replacing with "?": %r', - (error.object[linestart + 1:error.start] + b'>>>' + - error.object[error.start:error.end] + b'<<<' + - error.object[error.end:lineend]), - location=(self.docname, lineno)) - return (u'?', error.end) - def prepare_settings(self, docname): """Prepare to set up environment for reading.""" # type: (unicode) -> None @@ -693,7 +677,6 @@ class BuildEnvironment(object): self.note_dependency(docutilsconf) with sphinx_domains(self), rst.default_role(docname, self.config.default_role): - codecs.register_error('sphinx', self.warn_and_replace) # type: ignore doctree = read_doc(self.app, self, self.doc2path(docname)) # post-processing diff --git a/sphinx/io.py b/sphinx/io.py index ab8c9d068..b2e54622c 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -8,6 +8,8 @@ :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ +import codecs + from docutils.io import FileInput, NullOutput from docutils.core import Publisher from docutils.readers import standalone @@ -25,6 +27,7 @@ from sphinx.transforms.compact_bullet_list import RefOnlyBulletListTransform from sphinx.transforms.i18n import ( PreserveTranslatableMessages, Locale, RemoveTranslatableInline, ) +from sphinx.util import logging from sphinx.util import import_object, split_docinfo from sphinx.util.docutils import LoggingReporter @@ -40,6 +43,9 @@ if False: from sphinx.environment import BuildEnvironment # NOQA +logger = logging.getLogger(__name__) + + class SphinxBaseReader(standalone.Reader): """ Add our source parsers @@ -154,6 +160,10 @@ class SphinxFileInput(FileInput): # type: (Sphinx, BuildEnvironment, Any, Any) -> None self.app = app self.env = env + + # set up error handler + codecs.register_error('sphinx', self.warn_and_replace) # type: ignore + kwds['error_handler'] = 'sphinx' # py3: handle error on open. FileInput.__init__(self, *args, **kwds) @@ -187,6 +197,21 @@ class SphinxFileInput(FileInput): data = self.env.config.rst_prolog + '\n' + data return docinfo + data + def warn_and_replace(self, error): + # type: (Any) -> Tuple + """Custom decoding error handler that warns and replaces.""" + linestart = error.object.rfind(b'\n', 0, error.start) + lineend = error.object.find(b'\n', error.start) + if lineend == -1: + lineend = len(error.object) + lineno = error.object.count(b'\n', 0, error.start) + 1 + logger.warning('undecodable source characters, replacing with "?": %r', + (error.object[linestart + 1:error.start] + b'>>>' + + error.object[error.start:error.end] + b'<<<' + + error.object[error.end:lineend]), + location=(self.env.docname, lineno)) + return (u'?', error.end) + def read_doc(app, env, filename): """Parse a document and convert to doctree.""" From 7fab902561f2153e8c07b3bfd1368b148dca93a8 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 31 Oct 2017 23:04:26 +0900 Subject: [PATCH 015/275] Move UIDs assigning to sphinx.versioning --- sphinx/environment/__init__.py | 19 ++----------------- sphinx/versioning.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index 76b360a0f..2669710d9 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -27,7 +27,7 @@ from docutils.utils import Reporter, get_source_line, normalize_language_tag from docutils.utils.smartquotes import smartchars from docutils.frontend import OptionParser -from sphinx import addnodes +from sphinx import addnodes, versioning from sphinx.io import read_doc from sphinx.util import logging, rst from sphinx.util import get_matching_docs, FilenameUniqDict, status_iterator @@ -42,7 +42,6 @@ from sphinx.util.websupport import is_commentable from sphinx.errors import SphinxError, ExtensionError from sphinx.locale import __ from sphinx.transforms import SphinxTransformer -from sphinx.versioning import add_uids, merge_doctrees from sphinx.deprecation import RemovedInSphinx20Warning from sphinx.environment.adapters.indexentries import IndexEntries from sphinx.environment.adapters.toctree import TocTree @@ -695,22 +694,8 @@ class BuildEnvironment(object): time.time(), path.getmtime(self.doc2path(docname))) if self.versioning_condition: - old_doctree = None - if self.versioning_compare: - # get old doctree - try: - with open(self.doc2path(docname, - self.doctreedir, '.doctree'), 'rb') as f: - old_doctree = pickle.load(f) - except EnvironmentError: - pass - # add uids for versioning - if not self.versioning_compare or old_doctree is None: - list(add_uids(doctree, self.versioning_condition)) - else: - list(merge_doctrees( - old_doctree, doctree, self.versioning_condition)) + versioning.prepare(doctree) # cleanup self.temp_data.clear() diff --git a/sphinx/versioning.py b/sphinx/versioning.py index 97a013135..1e7c452bd 100644 --- a/sphinx/versioning.py +++ b/sphinx/versioning.py @@ -15,6 +15,9 @@ from itertools import product from six import iteritems from six.moves import range, zip_longest +from six.moves import cPickle as pickle + +from sphinx.transforms import SphinxTransform if False: # For type annotation @@ -148,3 +151,32 @@ def levenshtein_distance(a, b): current_row.append(min(insertions, deletions, substitutions)) previous_row = current_row # type: ignore return previous_row[-1] + + +class UIDTransform(SphinxTransform): + """Add UIDs to doctree for versioning.""" + default_priority = 100 + + def apply(self): + env = self.env + old_doctree = None + if env.versioning_compare: + # get old doctree + try: + filename = env.doc2path(env.docname, env.doctreedir, '.doctree') + with open(filename, 'rb') as f: + old_doctree = pickle.load(f) + except EnvironmentError: + pass + + # add uids for versioning + if not env.versioning_compare or old_doctree is None: + list(add_uids(self.document, env.versioning_condition)) + else: + list(merge_doctrees(old_doctree, self.document, env.versioning_condition)) + + +def prepare(document): + """Simple wrapper for UIDTransform.""" + transform = UIDTransform(document) + transform.apply() From d5bea6b85a56cb4ea052674bd0649818f8a89b2f Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Wed, 1 Nov 2017 22:03:45 +0100 Subject: [PATCH 016/275] autosummary: catch all exceptions when importing modules Module imports may raise any exceptions, including SystemExit, which need to be caught. --- sphinx/ext/autosummary/__init__.py | 23 +++++++++++++++++-- .../autosummary_importfail.py | 4 ++++ tests/roots/test-ext-autosummary/contents.rst | 5 ++++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 tests/roots/test-ext-autosummary/autosummary_importfail.py diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 67bbf6d91..4150ce83a 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -58,6 +58,8 @@ import re import sys import inspect import posixpath +import traceback +import warnings from six import string_types from types import ModuleType @@ -502,6 +504,22 @@ def import_by_name(name, prefixes=[None]): raise ImportError('no module named %s' % ' or '.join(tried)) +def _import_module(modname): + """ + Call __import__(modname), convert exceptions to ImportError + """ + try: + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=ImportWarning) + return __import__(modname) + except BaseException: + # Importing modules may cause any side effects, including + # SystemExit, so we need to catch all errors. + errmsg = "Failed to import %r: %s" % ( + modname, traceback.format_exc()) + raise ImportError(errmsg) + + def _import_by_name(name): # type: (str) -> Tuple[Any, Any, unicode] """Import a Python object given its full name.""" @@ -512,7 +530,7 @@ def _import_by_name(name): modname = '.'.join(name_parts[:-1]) if modname: try: - __import__(modname) + _import_module(modname) mod = sys.modules[modname] return getattr(mod, name_parts[-1]), mod, modname except (ImportError, IndexError, AttributeError): @@ -525,9 +543,10 @@ def _import_by_name(name): last_j = j modname = '.'.join(name_parts[:j]) try: - __import__(modname) + _import_module(modname) except ImportError: continue + if modname in sys.modules: break diff --git a/tests/roots/test-ext-autosummary/autosummary_importfail.py b/tests/roots/test-ext-autosummary/autosummary_importfail.py new file mode 100644 index 000000000..9e3f9f195 --- /dev/null +++ b/tests/roots/test-ext-autosummary/autosummary_importfail.py @@ -0,0 +1,4 @@ +import sys + +# Fail module import in a catastrophic way +sys.exit(1) diff --git a/tests/roots/test-ext-autosummary/contents.rst b/tests/roots/test-ext-autosummary/contents.rst index 3b43086a2..fc84927bb 100644 --- a/tests/roots/test-ext-autosummary/contents.rst +++ b/tests/roots/test-ext-autosummary/contents.rst @@ -1,6 +1,11 @@ +:autolink:`autosummary_dummy_module.Foo` + +:autolink:`autosummary_importfail` + .. autosummary:: :toctree: generated autosummary_dummy_module autosummary_dummy_module.Foo + autosummary_importfail From 17dc8beeaf5cdf1de7e833b223e3ca92f3576aaa Mon Sep 17 00:00:00 2001 From: Berker Peksag Date: Sat, 4 Nov 2017 14:08:59 +0300 Subject: [PATCH 017/275] Apply fixFirefoxAnchorBug only under Firefox A compatibility shim for `$.browser` was added in c608af4babe140626877be08535af095ff633c00. Fixes #3549 --- sphinx/themes/basic/static/doctools.js_t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/themes/basic/static/doctools.js_t b/sphinx/themes/basic/static/doctools.js_t index 9ceecef79..326856cfc 100644 --- a/sphinx/themes/basic/static/doctools.js_t +++ b/sphinx/themes/basic/static/doctools.js_t @@ -206,7 +206,7 @@ var Documentation = { * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 */ fixFirefoxAnchorBug : function() { - if (document.location.hash) + if (document.location.hash && $.browser.mozilla) window.setTimeout(function() { document.location.href += ''; }, 10); From 71d4bc4a3ef4f5c2957fca844760a68318e20afd Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 11 Nov 2017 16:21:17 +0900 Subject: [PATCH 018/275] Move import_module() to sphinx.ext.autodoc.importer --- sphinx/ext/autodoc/__init__.py | 10 ++++------ sphinx/ext/autodoc/importer.py | 17 +++++++++++++++++ sphinx/ext/autosummary/__init__.py | 24 +++--------------------- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index e8586943f..31fd47c1a 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -15,7 +15,6 @@ import re import sys import inspect import traceback -import warnings from six import PY2, iterkeys, iteritems, itervalues, text_type, class_types, string_types @@ -25,7 +24,7 @@ from docutils.parsers.rst import Directive from docutils.statemachine import ViewList import sphinx -from sphinx.ext.autodoc.importer import _MockImporter +from sphinx.ext.autodoc.importer import _MockImporter, import_module from sphinx.ext.autodoc.inspector import format_annotation, formatargspec # to keep compatibility # NOQA from sphinx.util import rpartition, force_decode from sphinx.locale import _ @@ -392,10 +391,7 @@ class Documenter(object): import_hook = _MockImporter(self.env.config.autodoc_mock_imports) try: logger.debug('[autodoc] import %s', self.modname) - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", category=ImportWarning) - with logging.skip_warningiserror(not self.env.config.autodoc_warningiserror): - __import__(self.modname) + import_module(self.modname, self.env.config.autodoc_warningiserror) parent = None obj = self.module = sys.modules[self.modname] logger.debug('[autodoc] => %r', obj) @@ -420,6 +416,8 @@ class Documenter(object): if isinstance(e, SystemExit): errmsg += ('; the module executes module level statement ' + 'and it might call sys.exit().') + elif isinstance(e, ImportError): + errmsg += '; the following exception was raised:\n%s' % e.args[0] else: errmsg += '; the following exception was raised:\n%s' % \ traceback.format_exc() diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py index 1234d716a..cfa7411ec 100644 --- a/sphinx/ext/autodoc/importer.py +++ b/sphinx/ext/autodoc/importer.py @@ -10,6 +10,8 @@ """ import sys +import traceback +import warnings from types import FunctionType, MethodType, ModuleType from sphinx.util import logging @@ -116,3 +118,18 @@ class _MockImporter(object): sys.modules[name] = module self.mocked_modules.append(name) return module + + +def import_module(modname, warningiserror=False): + """ + Call __import__(modname), convert exceptions to ImportError + """ + try: + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=ImportWarning) + with logging.skip_warningiserror(not warningiserror): + return __import__(modname) + except BaseException as exc: + # Importing modules may cause any side effects, including + # SystemExit, so we need to catch all errors. + raise ImportError(traceback.format_exc()) diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 4150ce83a..21bfe7b13 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -58,8 +58,6 @@ import re import sys import inspect import posixpath -import traceback -import warnings from six import string_types from types import ModuleType @@ -75,6 +73,7 @@ from sphinx.environment.adapters.toctree import TocTree from sphinx.util import import_object, rst, logging from sphinx.pycode import ModuleAnalyzer, PycodeError from sphinx.ext.autodoc import Options +from sphinx.ext.autodoc.importer import import_module if False: # For type annotation @@ -504,22 +503,6 @@ def import_by_name(name, prefixes=[None]): raise ImportError('no module named %s' % ' or '.join(tried)) -def _import_module(modname): - """ - Call __import__(modname), convert exceptions to ImportError - """ - try: - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", category=ImportWarning) - return __import__(modname) - except BaseException: - # Importing modules may cause any side effects, including - # SystemExit, so we need to catch all errors. - errmsg = "Failed to import %r: %s" % ( - modname, traceback.format_exc()) - raise ImportError(errmsg) - - def _import_by_name(name): # type: (str) -> Tuple[Any, Any, unicode] """Import a Python object given its full name.""" @@ -530,8 +513,7 @@ def _import_by_name(name): modname = '.'.join(name_parts[:-1]) if modname: try: - _import_module(modname) - mod = sys.modules[modname] + mod = import_module(modname) return getattr(mod, name_parts[-1]), mod, modname except (ImportError, IndexError, AttributeError): pass @@ -543,7 +525,7 @@ def _import_by_name(name): last_j = j modname = '.'.join(name_parts[:j]) try: - _import_module(modname) + import_module(modname) except ImportError: continue From 2c1ac5243cd88875700f1b6669713edb27ae8368 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 11 Nov 2017 16:47:51 +0900 Subject: [PATCH 019/275] Update CHANGES for PR #4212 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index 79c562606..f02b25a48 100644 --- a/CHANGES +++ b/CHANGES @@ -43,6 +43,7 @@ Features added * #4168: improve zh search with jieba * HTML themes can set up default sidebars through ``theme.conf`` * #3160: html: Use ```` to represent ``:kbd:`` role +* #4212: autosummary: catch all exceptions when importing modules Features removed From 8b090c6372513068d063dc74d614fcb6dbc60121 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 11 Nov 2017 17:00:50 +0900 Subject: [PATCH 020/275] Fix flake8 violation --- sphinx/ext/autodoc/importer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py index cfa7411ec..b517cf911 100644 --- a/sphinx/ext/autodoc/importer.py +++ b/sphinx/ext/autodoc/importer.py @@ -129,7 +129,7 @@ def import_module(modname, warningiserror=False): warnings.filterwarnings("ignore", category=ImportWarning) with logging.skip_warningiserror(not warningiserror): return __import__(modname) - except BaseException as exc: + except BaseException: # Importing modules may cause any side effects, including # SystemExit, so we need to catch all errors. raise ImportError(traceback.format_exc()) From c3113d2e17a9168097974bc8f01eb3f93277e660 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 11 Nov 2017 18:30:32 +0900 Subject: [PATCH 021/275] Update CHANGES for PR #4231 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index aa38012d1..85433e2b8 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,7 @@ Bugs fixed ---------- * #4206: latex: reST label between paragraphs loses paragraph break +* #4231: html: Apply fixFirefoxAnchorBug only under Firefox Testing -------- From 507f172866deb5d7223f9e61c30a68b45d6f8f38 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 11 Nov 2017 18:35:45 +0900 Subject: [PATCH 022/275] Make ShowUrlsTransform as a subclass of Transform --- sphinx/writers/latex.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 389d840c1..e48905757 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -25,6 +25,7 @@ from sphinx import addnodes from sphinx import highlighting from sphinx.errors import SphinxError from sphinx.locale import admonitionlabels, _ +from sphinx.transforms import SphinxTransform from sphinx.util import split_into, logging from sphinx.util.i18n import format_date from sphinx.util.nodes import clean_astext, traverse_parent @@ -222,12 +223,11 @@ class ExtBabel(Babel): return language -class ShowUrlsTransform(object): - expanded = False - - def __init__(self, document): - # type: (nodes.Node) -> None - self.document = document +class ShowUrlsTransform(SphinxTransform, object): + def __init__(self, document, startnode=None): + # type: (nodes.document, nodes.Node) -> None + super(ShowUrlsTransform, self).__init__(document, startnode) + self.expanded = False def apply(self): # type: () -> None From 3d8ce5a7c40b746aebc4113551ad1ae6144b9898 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 11 Nov 2017 18:47:35 +0900 Subject: [PATCH 023/275] Fix mypy violations --- sphinx/environment/__init__.py | 2 +- sphinx/io.py | 2 +- sphinx/util/rst.py | 6 +++++- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index 2669710d9..7c76da925 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -641,8 +641,8 @@ class BuildEnvironment(object): # --------- SINGLE FILE READING -------------------------------------------- def prepare_settings(self, docname): - """Prepare to set up environment for reading.""" # type: (unicode) -> None + """Prepare to set up environment for reading.""" self.temp_data['docname'] = docname # defaults to the global default, but can be re-set in a document self.temp_data['default_role'] = self.config.default_role diff --git a/sphinx/io.py b/sphinx/io.py index b2e54622c..84e1d7bb3 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -214,8 +214,8 @@ class SphinxFileInput(FileInput): def read_doc(app, env, filename): - """Parse a document and convert to doctree.""" # type: (Sphinx, BuildEnvironment, unicode) -> nodes.document + """Parse a document and convert to doctree.""" reader = SphinxStandaloneReader(app, parsers=app.registry.get_source_parsers()) source = SphinxFileInput(app, env, source=None, source_path=filename, encoding=env.config.source_encoding) diff --git a/sphinx/util/rst.py b/sphinx/util/rst.py index b77e75ebf..6977cda96 100644 --- a/sphinx/util/rst.py +++ b/sphinx/util/rst.py @@ -19,6 +19,10 @@ from docutils.utils import Reporter from sphinx.util import logging +if False: + # For type annotation + from typing import Generator # NOQA + symbols_re = re.compile(r'([!-/:-@\[-`{-~])') logger = logging.getLogger(__name__) @@ -30,7 +34,7 @@ def escape(text): @contextmanager def default_role(docname, name): - # type: (unicode, unicode) -> None + # type: (unicode, unicode) -> Generator if name: dummy_reporter = Reporter('', 4, 4) role_fn, _ = roles.role(name, english, 0, dummy_reporter) From 4abe6cb62e54683c60f699d963333b91ee4676c1 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 11 Nov 2017 21:53:20 +0900 Subject: [PATCH 024/275] Fix #4221: napoleon depends on autodoc, but users need to load it manually --- CHANGES | 1 + doc/ext/napoleon.rst | 9 ++++----- sphinx/ext/napoleon/__init__.py | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index 85433e2b8..4bd6399ae 100644 --- a/CHANGES +++ b/CHANGES @@ -20,6 +20,7 @@ Bugs fixed * #4206: latex: reST label between paragraphs loses paragraph break * #4231: html: Apply fixFirefoxAnchorBug only under Firefox +* #4221: napoleon depends on autodoc, but users need to load it manually Testing -------- diff --git a/doc/ext/napoleon.rst b/doc/ext/napoleon.rst index ea3e4042f..f7e9081f7 100644 --- a/doc/ext/napoleon.rst +++ b/doc/ext/napoleon.rst @@ -68,8 +68,8 @@ Getting Started # conf.py - # Add autodoc and napoleon to the extensions list - extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon'] + # Add napoleon to the extensions list + extensions = ['sphinx.ext.napoleon'] 2. Use `sphinx-apidoc` to build your API documentation:: @@ -246,13 +246,12 @@ Configuration Listed below are all the settings used by napoleon and their default values. These settings can be changed in the Sphinx `conf.py` file. Make -sure that both "sphinx.ext.autodoc" and "sphinx.ext.napoleon" are -enabled in `conf.py`:: +sure that "sphinx.ext.napoleon" is enabled in `conf.py`:: # conf.py # Add any Sphinx extension module names here, as strings - extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon'] + extensions = ['sphinx.ext.napoleon'] # Napoleon settings napoleon_google_docstring = True diff --git a/sphinx/ext/napoleon/__init__.py b/sphinx/ext/napoleon/__init__.py index f319a18c4..7aca9b629 100644 --- a/sphinx/ext/napoleon/__init__.py +++ b/sphinx/ext/napoleon/__init__.py @@ -27,13 +27,12 @@ class Config(object): Listed below are all the settings used by napoleon and their default values. These settings can be changed in the Sphinx `conf.py` file. Make - sure that both "sphinx.ext.autodoc" and "sphinx.ext.napoleon" are - enabled in `conf.py`:: + sure that "sphinx.ext.napoleon" is enabled in `conf.py`:: # conf.py # Add any Sphinx extension module names here, as strings - extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon'] + extensions = ['sphinx.ext.napoleon'] # Napoleon settings napoleon_google_docstring = True @@ -294,6 +293,7 @@ def setup(app): _patch_python_domain() + app.setup_extension('sphinx.ext.autodoc') app.connect('autodoc-process-docstring', _process_docstring) app.connect('autodoc-skip-member', _skip_member) From bdebbdf873074caca537a3829e55574db7b27823 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 12 Nov 2017 01:51:40 +0900 Subject: [PATCH 025/275] Update CHANGES for PR #2299 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index 85433e2b8..cf86e266e 100644 --- a/CHANGES +++ b/CHANGES @@ -20,6 +20,7 @@ Bugs fixed * #4206: latex: reST label between paragraphs loses paragraph break * #4231: html: Apply fixFirefoxAnchorBug only under Firefox +* #2298: automodule fails to document a class attribute Testing -------- From 189e25ac0e8c39db4f548a597ee566f5464124b0 Mon Sep 17 00:00:00 2001 From: Pauli Virtanen Date: Sat, 11 Nov 2017 14:26:12 +0100 Subject: [PATCH 026/275] Fix issue in import_module returning wrong module --- sphinx/ext/autodoc/__init__.py | 4 ++-- sphinx/ext/autodoc/importer.py | 3 ++- tests/test_ext_autosummary.py | 25 ++++++++++++++++++++++++- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 31fd47c1a..3d7f85618 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -391,9 +391,9 @@ class Documenter(object): import_hook = _MockImporter(self.env.config.autodoc_mock_imports) try: logger.debug('[autodoc] import %s', self.modname) - import_module(self.modname, self.env.config.autodoc_warningiserror) + obj = import_module(self.modname, self.env.config.autodoc_warningiserror) parent = None - obj = self.module = sys.modules[self.modname] + self.module = obj logger.debug('[autodoc] => %r', obj) for part in self.objpath: parent = obj diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py index b517cf911..e024d38f3 100644 --- a/sphinx/ext/autodoc/importer.py +++ b/sphinx/ext/autodoc/importer.py @@ -128,7 +128,8 @@ def import_module(modname, warningiserror=False): with warnings.catch_warnings(): warnings.filterwarnings("ignore", category=ImportWarning) with logging.skip_warningiserror(not warningiserror): - return __import__(modname) + __import__(modname) + return sys.modules[modname] except BaseException: # Importing modules may cause any side effects, including # SystemExit, so we need to catch all errors. diff --git a/tests/test_ext_autosummary.py b/tests/test_ext_autosummary.py index 81fd35762..b59f0cbc8 100644 --- a/tests/test_ext_autosummary.py +++ b/tests/test_ext_autosummary.py @@ -11,7 +11,7 @@ from six import iteritems, StringIO -from sphinx.ext.autosummary import mangle_signature +from sphinx.ext.autosummary import mangle_signature, import_by_name from sphinx.testing.util import etree_parse @@ -145,3 +145,26 @@ def test_autosummary_generate(app, status, warning): ' ~Foo.__init__\n' ' ~Foo.bar\n' ' \n' in Foo) + + +def test_import_by_name(): + import sphinx + import sphinx.ext.autosummary + + prefixed_name, obj, parent, modname = import_by_name('sphinx') + assert prefixed_name == 'sphinx' + assert obj is sphinx + assert parent is None + assert modname == 'sphinx' + + prefixed_name, obj, parent, modname = import_by_name('sphinx.ext.autosummary.__name__') + assert prefixed_name == 'sphinx.ext.autosummary.__name__' + assert obj is sphinx.ext.autosummary.__name__ + assert parent is sphinx.ext.autosummary + assert modname == 'sphinx.ext.autosummary' + + prefixed_name, obj, parent, modname = import_by_name('sphinx.ext.autosummary.Autosummary.get_items') + assert prefixed_name == 'sphinx.ext.autosummary.Autosummary.get_items' + assert obj == sphinx.ext.autosummary.Autosummary.get_items + assert parent is sphinx.ext.autosummary.Autosummary + assert modname == 'sphinx.ext.autosummary' From 199256e675a29309b08e4ae8fb26245c4bd3e40d Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 12 Nov 2017 12:26:51 +0900 Subject: [PATCH 027/275] Fix #4226: apidoc: Generate new style makefile (make-mode) --- CHANGES | 1 + sphinx/ext/apidoc.py | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index e1f3db3ac..046ba5740 100644 --- a/CHANGES +++ b/CHANGES @@ -11,6 +11,7 @@ Incompatible changes package when ``--implicit-namespaces`` option given, not subdirectories of given directory. * #3929: apidoc: Move sphinx.apidoc to sphinx.ext.apidoc +* #4226: apidoc: Generate new style makefile (make-mode) Deprecated ---------- diff --git a/sphinx/ext/apidoc.py b/sphinx/ext/apidoc.py index cb020aba2..6edab379b 100644 --- a/sphinx/ext/apidoc.py +++ b/sphinx/ext/apidoc.py @@ -413,6 +413,7 @@ def main(argv=sys.argv[1:]): ext_todo = True, makefile = True, batchfile = True, + make_mode = True, mastertocmaxdepth = args.maxdepth, mastertoctree = text, language = 'en', From 3cef4b6e7cdbfccad05de0b9ad00b1c0bb30fc1f Mon Sep 17 00:00:00 2001 From: Aaron Carlisle Date: Thu, 16 Nov 2017 14:17:28 -0500 Subject: [PATCH 028/275] Themes: Add language to javascript vars list --- sphinx/themes/basic/layout.html | 1 + 1 file changed, 1 insertion(+) diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html index b337a977e..af91e42f2 100644 --- a/sphinx/themes/basic/layout.html +++ b/sphinx/themes/basic/layout.html @@ -91,6 +91,7 @@ var DOCUMENTATION_OPTIONS = { URL_ROOT: '{{ url_root }}', VERSION: '{{ release|e }}', + LANGUAGE: '{{ language }}', COLLAPSE_INDEX: false, FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}', HAS_SOURCE: {{ has_source|lower }}, From 466241d43ada9c4d5317be86604446e8d6d8ffe6 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Sat, 25 Nov 2017 14:37:27 +0100 Subject: [PATCH 029/275] C++, small cleanup after PR #4189 --- CHANGES | 3 ++- doc/domains.rst | 8 +++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index b5ff95063..39b9c5903 100644 --- a/CHANGES +++ b/CHANGES @@ -75,7 +75,8 @@ Features removed * ``sphinx.util.nodes.process_only_nodes()`` * LaTeX environment ``notice``, use ``sphinxadmonition`` instead * LaTeX ``\sphinxstylethead``, use ``\sphinxstyletheadfamily`` -* C++, support of function concepts +* C++, support of function concepts. Thanks to mickk-on-cpp. + Bugs fixed ---------- diff --git a/doc/domains.rst b/doc/domains.rst index e6a860bcd..5bed02cf4 100644 --- a/doc/domains.rst +++ b/doc/domains.rst @@ -722,7 +722,8 @@ a visibility statement (``public``, ``private`` or ``protected``). .. rst:directive:: .. cpp:concept:: template-parameter-list name .. warning:: The support for concepts is experimental. It is based on the - Concepts Technical Specification, and the features may change as the TS evolves. + current draft standard and the Concepts Technical Specification. + The features may change as they evolve. Describe a concept. It must have exactly 1 template parameter list. The name may be a nested name. Example:: @@ -774,8 +775,9 @@ Some directives support options: Constrained Templates ~~~~~~~~~~~~~~~~~~~~~ -.. warning:: The support for constrained templates is experimental. It is based on the - Concepts Technical Specification, and the features may change as the TS evolves. +.. warning:: The support for concepts is experimental. It is based on the + current draft standard and the Concepts Technical Specification. + The features may change as they evolve. .. note:: Sphinx does not currently support ``requires`` clauses. From 0aa9d4c87e2c1691735b1a6ee00961c39066b718 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Sun, 26 Nov 2017 12:45:27 +0100 Subject: [PATCH 030/275] C++, parse more types of integer literals Fixes case 0 of sphinx-doc/sphinx#4114 --- sphinx/domains/cpp.py | 18 +++++++++++++----- tests/test_domain_cpp.py | 17 ++++++++++++++--- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index a1b0a71c3..65376f24a 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -290,7 +290,11 @@ logger = logging.getLogger(__name__) """ # TODO: support hex, oct, etc. work -_integer_literal_re = re.compile(r'-?[1-9][0-9]*') +_integer_literal_re = re.compile(r'[1-9][0-9]*') +_octal_literal_re = re.compile(r'0[0-7]*') +_hex_literal_re = re.compile(r'0[xX][0-7a-fA-F][0-7a-fA-F]*') +_binary_literal_re = re.compile(r'0[bB][01][01]*') +_integer_suffix_re = re.compile(r'') _float_literal_re = re.compile(r'[+-]?[0-9]*\.[0-9]+') _identifier_re = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*)\b') _whitespace_re = re.compile(r'(?u)\s+') @@ -3781,10 +3785,14 @@ class DefinitionParser(object): return ASTBooleanLiteral(True) if self.skip_word('false'): return ASTBooleanLiteral(False) - if self.match(_float_literal_re): - return ASTNumberLiteral(self.matched_text) - if self.match(_integer_literal_re): - return ASTNumberLiteral(self.matched_text) + for regex in [_float_literal_re, _binary_literal_re, _hex_literal_re, + _integer_literal_re, _octal_literal_re]: + pos = self.pos + if self.match(regex): + while self.current_char in 'uUlLfF': + self.pos += 1 + return ASTNumberLiteral(self.definition[pos:self.pos]) + string = self._parse_string() if string is not None: return ASTStringLiteral(string) diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py index 63682237f..22cdce60f 100644 --- a/tests/test_domain_cpp.py +++ b/tests/test_domain_cpp.py @@ -111,9 +111,20 @@ def test_expressions(): exprCheck('nullptr', 'LDnE') exprCheck('true', 'L1E') exprCheck('false', 'L0E') - exprCheck('5', 'L5E') - exprCheck('5.0', 'L5.0E') - exprCheck('"abc\\"cba"', 'LA8_KcE') + ints = ['5', '0', '075', '0xF', '0XF', '0b1', '0B1'] + unsignedSuffix = ['', 'u', 'U'] + longSuffix = ['', 'l', 'L', 'll', 'LL'] + for i in ints: + for u in unsignedSuffix: + for l in longSuffix: + expr = i + u + l; + exprCheck(expr, 'L' + expr + 'E') + expr = i + l + u; + exprCheck(expr, 'L' + expr + 'E') + for suffix in ['', 'f', 'F', 'l', 'L']: + expr = '5.0' + suffix + exprCheck(expr, 'L' + expr + 'E') + exprCheck('"abc\\"cba"', 'LA8_KcE') # string # TODO: test the rest exprCheck('(... + Ns)', '(... + Ns)') exprCheck('(5)', 'L5E') From 94934b2bdfd6fca9d505577aa6314f522be148f6 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Sun, 26 Nov 2017 15:36:35 +0100 Subject: [PATCH 031/275] C++, reintroduce expression fallback parser Part of fixing sphinx-doc/sphinx#4114. This reverts commit b55526f4e87ecfdd5c43cbe4e0dab847ebb0c7c9. --- sphinx/domains/cpp.py | 77 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 6 deletions(-) diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 65376f24a..ed15f1272 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -1073,6 +1073,20 @@ class ASTPostfixExpr(ASTBase): p.describe_signature(signode, mode, env, symbol) +class ASTFallbackExpr(ASTBase): + def __init__(self, expr): + self.expr = expr + + def __unicode__(self): + return self.expr + + def get_id(self, version): + return text_type(self.expr) + + def describe_signature(self, signode, mode, env, symbol): + signode += nodes.Text(self.expr) + + ################################################################################ # The Rest ################################################################################ @@ -4084,6 +4098,43 @@ class DefinitionParser(object): # TODO: actually parse the second production return self._parse_assignment_expression(inTemplate=inTemplate) + def _parse_expression_fallback(self, end, parser): + # type: (List[unicode]) -> unicode + # Stupidly "parse" an expression. + # 'end' should be a list of characters which ends the expression. + + # first try to use the provided parser + prevPos = self.pos + try: + return parser() + except DefinitionError as e: + self.warn("Parsing of expression failed. Using fallback parser." + " Error was:\n%s" % e.description) + self.pos = prevPos + # and then the fallback scanning + assert end is not None + self.skip_ws() + startPos = self.pos + if self.match(_string_re): + value = self.matched_text + else: + # TODO: add handling of more bracket-like things, and quote handling + brackets = {'(': ')', '[': ']', '<': '>'} # type: Dict[unicode, unicode] + symbols = [] # type: List[unicode] + while not self.eof: + if (len(symbols) == 0 and self.current_char in end): + break + if self.current_char in brackets.keys(): + symbols.append(brackets[self.current_char]) + elif len(symbols) > 0 and self.current_char == symbols[-1]: + symbols.pop() + self.pos += 1 + if len(end) > 0 and self.eof: + self.fail("Could not find end of expression starting at %d." + % startPos) + value = self.definition[startPos:self.pos].strip() + return ASTFallbackExpr(value.strip()) + def _parse_operator(self): # type: () -> Any self.skip_ws() @@ -4144,7 +4195,9 @@ class DefinitionParser(object): prevErrors.append((e, "If type argument")) self.pos = pos try: - value = self._parse_constant_expression(inTemplate=True) + def parser(): + return self._parse_constant_expression(inTemplate=True) + value = self._parse_expression_fallback([',', '>'], parser) self.skip_ws() if self.skip_string('>'): parsedEnd = True @@ -4486,7 +4539,10 @@ class DefinitionParser(object): if self.skip_string(']'): arrayOps.append(ASTArray(None)) continue - value = self._parse_expression(inTemplate=False) + + def parser(): + return self._parse_expression(inTemplate=False) + value = self._parse_expression_fallback([']'], parser) if not self.skip_string(']'): self.fail("Expected ']' in end of array operator.") arrayOps.append(ASTArray(value)) @@ -4606,11 +4662,17 @@ class DefinitionParser(object): return None else: if outer == 'member': - value = self._parse_assignment_expression(inTemplate=False) + def parser(): + return self._parse_assignment_expression(inTemplate=False) + value = self._parse_expression_fallback([], parser) elif outer == 'templateParam': - value = self._parse_assignment_expression(inTemplate=True) + def parser(): + return self._parse_assignment_expression(inTemplate=True) + value = self._parse_expression_fallback([',', '>'], parser) elif outer is None: # function parameter - value = self._parse_assignment_expression(inTemplate=False) + def parser(): + return self._parse_assignment_expression(inTemplate=False) + value = self._parse_expression_fallback([',', ')'], parser) else: self.fail("Internal error, initializer for outer '%s' not " "implemented." % outer) @@ -4772,7 +4834,10 @@ class DefinitionParser(object): init = None if self.skip_string('='): self.skip_ws() - initVal = self._parse_constant_expression(inTemplate=False) + + def parser(): + return self._parse_constant_expression(inTemplate=False) + initVal = self._parse_expression_fallback([], parser) init = ASTInitializer(initVal) return ASTEnumerator(name, init) From 6e721e98fefff7264af3707c6479bfbaa43ce168 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Sun, 26 Nov 2017 20:32:24 +0100 Subject: [PATCH 032/275] C++, parse more unary expressions Last part, fixes sphinx-doc/sphinx#4114 --- sphinx/domains/cpp.py | 115 +++++++++++++++++++++++++++++++++++++++ tests/test_domain_cpp.py | 5 ++ 2 files changed, 120 insertions(+) diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index ed15f1272..dca18ddb3 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -948,6 +948,85 @@ class ASTUnaryOpExpr(ASTBase): self.expr.describe_signature(signode, mode, env, symbol) +class ASTSizeofParamPack(ASTBase): + def __init__(self, identifier): + self.identifier = identifier + + def __unicode__(self): + return "sizeof...(" + text_type(self.identifier) + ")" + + def get_id(self, version): + return 'sZ' + self.identifier.get_id(version) + + def describe_signature(self, signode, mode, env, symbol): + signode.append(nodes.Text('sizeof...(')) + self.identifier.describe_signature(signode, mode, env, symbol, "") + signode.append(nodes.Text(')')) + + +class ASTSizeofType(ASTBase): + def __init__(self, typ): + self.typ = typ + + def __unicode__(self): + return "sizeof(" + text_type(self.typ) + ")" + + def get_id(self, version): + return 'st' + self.typ.get_id(version) + + def describe_signature(self, signode, mode, env, symbol): + signode.append(nodes.Text('sizeof(')) + self.typ.describe_signature(signode, mode, env, symbol) + signode.append(nodes.Text(')')) + + +class ASTSizeofExpr(ASTBase): + def __init__(self, expr): + self.expr = expr + + def __unicode__(self): + return "sizeof " + text_type(self.expr) + + def get_id(self, version): + return 'sz' + self.expr.get_id(version) + + def describe_signature(self, signode, mode, env, symbol): + signode.append(nodes.Text('sizeof ')) + self.expr.describe_signature(signode, mode, env, symbol) + + +class ASTAlignofExpr(ASTBase): + def __init__(self, typ): + self.typ = typ + + def __unicode__(self): + return "alignof(" + text_type(self.typ) + ")" + + def get_id(self, version): + return 'at' + self.typ.get_id(version) + + def describe_signature(self, signode, mode, env, symbol): + signode.append(nodes.Text('alignof(')) + self.typ.describe_signature(signode, mode, env, symbol) + signode.append(nodes.Text(')')) + + +class ASTNoexceptExpr(ASTBase): + def __init__(self, expr): + self.expr = expr + + def __unicode__(self): + return "noexcept(" + text_type(self.expr) + ")" + + def get_id(self, version): + return 'nx' + self.expr.get_id(version) + + def describe_signature(self, signode, mode, env, symbol): + signode.append(nodes.Text('noexcept(')) + self.expr.describe_signature(signode, mode, env, symbol) + signode.append(nodes.Text(')')) + + class ASTPostfixCallExpr(ASTBase): def __init__(self, exprs): self.exprs = exprs @@ -3962,6 +4041,7 @@ class DefinitionParser(object): # | "++" cast # | "--" cast # | unary-operator cast -> (* | & | + | - | ! | ~) cast + # The rest: # | "sizeof" unary # | "sizeof" "(" type-id ")" # | "sizeof" "..." "(" identifier ")" @@ -3975,6 +4055,41 @@ class DefinitionParser(object): if self.skip_string(op): expr = self._parse_cast_expression() return ASTUnaryOpExpr(op, expr) + if self.skip_word_and_ws('sizeof'): + if self.skip_string_and_ws('...'): + if not self.skip_string_and_ws('('): + self.fail("Expecting '(' after 'sizeof...'.") + if not self.match(_identifier_re): + self.fail("Expecting identifier for 'sizeof...'.") + ident = ASTIdentifier(self.matched_text) + self.skip_ws() + if not self.skip_string(")"): + self.fail("Expecting ')' to end 'sizeof...'.") + return ASTSizeofParamPack(ident) + if self.skip_string_and_ws('('): + typ = self._parse_type(named=False) + self.skip_ws() + if not self.skip_string(')'): + self.fail("Expecting ')' to end 'sizeof'.") + return ASTSizeofType(typ) + expr = self._parse_unary_expression() + return ASTSizeofExpr(expr) + if self.skip_word_and_ws('alignof'): + if not self.skip_string_and_ws('('): + self.fail("Expecting '(' after 'alignof'.") + typ = self._parse_type(named=False) + self.skip_ws() + if not self.skip_string(')'): + self.fail("Expecting ')' to end 'alignof'.") + return ASTAlignofExpr(typ) + if self.skip_word_and_ws('noexcept'): + if not self.skip_string_and_ws('('): + self.fail("Expecting '(' after 'noexcept'.") + expr = self._parse_expression(inTemplate=False) + self.skip_ws() + if not self.skip_string(')'): + self.fail("Expecting ')' to end 'noexcept'.") + return ASTNoexceptExpr(expr) # TODO: the rest return self._parse_postfix_expression() diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py index 22cdce60f..3fdb1ae23 100644 --- a/tests/test_domain_cpp.py +++ b/tests/test_domain_cpp.py @@ -146,6 +146,11 @@ def test_expressions(): exprCheck('-5', 'ngL5E') exprCheck('!5', 'ntL5E') exprCheck('~5', 'coL5E') + exprCheck('sizeof...(a)', 'sZ1a') + exprCheck('sizeof(T)', 'st1T') + exprCheck('sizeof -42', 'szngL42E') + exprCheck('alignof(T)', 'at1T') + exprCheck('noexcept(-42)', 'nxngL42E') # cast exprCheck('(int)2', 'cviL2E') # binary op From e7ba2abfb2416115fb5ed96eee1f3b27cd263c6f Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Sun, 26 Nov 2017 20:40:04 +0100 Subject: [PATCH 033/275] Fix type annotation error --- sphinx/domains/cpp.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index dca18ddb3..914b79668 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -4214,7 +4214,6 @@ class DefinitionParser(object): return self._parse_assignment_expression(inTemplate=inTemplate) def _parse_expression_fallback(self, end, parser): - # type: (List[unicode]) -> unicode # Stupidly "parse" an expression. # 'end' should be a list of characters which ends the expression. From d6ec677c6161f3fad1d1848f36feb5f35058e914 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Sun, 26 Nov 2017 21:41:15 +0100 Subject: [PATCH 034/275] C++, parse decltype() Fixes sphinx-doc/sphinx#4094 --- sphinx/domains/cpp.py | 25 +++++++++++++++++++++++-- tests/test_domain_cpp.py | 7 +++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 914b79668..4e9eaeec4 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -1931,6 +1931,24 @@ class ASTTrailingTypeSpecDecltypeAuto(ASTBase): signode.append(nodes.Text(text_type(self))) +class ASTTrailingTypeSpecDecltype(ASTBase): + def __init__(self, expr): + self.expr = expr + + def __unicode__(self): + return u'decltype(' + text_type(self.expr) + ')' + + def get_id(self, version): + if version == 1: + raise NoOldIdError() + return 'DT' + self.expr.get_id(version) + "E" + + def describe_signature(self, signode, mode, env, symbol): + signode.append(nodes.Text('decltype(')) + self.expr.describe_signature(signode, mode, env, symbol) + signode.append(nodes.Text(')')) + + class ASTFunctionParameter(ASTBase): def __init__(self, arg, ellipsis=False): # type: (Any, bool) -> None @@ -4413,8 +4431,11 @@ class DefinitionParser(object): if not self.skip_string(')'): self.fail("Expected ')' after 'decltype(auto'.") return ASTTrailingTypeSpecDecltypeAuto() - self.fail('"decltype()" in trailing_type_spec not implemented') - # return ASTTrailingTypeSpecDecltype() + expr = self._parse_expression(inTemplate=False) + self.skip_ws() + if not self.skip_string(')'): + self.fail("Expected ')' after 'decltype('.") + return ASTTrailingTypeSpecDecltype(expr) # prefixed prefix = None diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py index 3fdb1ae23..8c838fcf8 100644 --- a/tests/test_domain_cpp.py +++ b/tests/test_domain_cpp.py @@ -235,6 +235,7 @@ def test_type_definitions(): check("type", "bool ::B::b", {1:"B::b", 2:"N1B1bE"}) check('type', 'A = B', {2:'1A'}) + check('type', 'A = decltype(b)', {2:'1A'}) # from breathe#267 (named function parameters for function pointers check('type', 'void (*gpio_callback_t)(struct device *port, uint32_t pin)', @@ -389,6 +390,8 @@ def test_function_definitions(): check('function', 'extern int f()', {1:'f', 2:'1fv'}) + check('function', 'decltype(auto) f()', {1: 'f', 2:"1fv"}) + # TODO: make tests for functions in a template, e.g., Test # such that the id generation for function type types is correct. @@ -466,6 +469,10 @@ def test_class_definitions(): check('class', 'A : B, C...', {1:'A', 2:'1A'}) check('class', 'A : B..., C', {1:'A', 2:'1A'}) + # from #4094 + check('class', 'template> has_var', {2:'I00E7has_var'}) + check('class', 'template has_var>', {2:'I0E7has_varI1TNSt6void_tIDTadN1T3varEEEEE'}) + def test_enum_definitions(): check('enum', 'A', {2:"1A"}) From 56b520958f554be5a8e04d57c477bc520e2d4de6 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Sun, 26 Nov 2017 22:37:26 +0100 Subject: [PATCH 035/275] C++: properly link class reference to class from inside constructor Fixes sphinx-doc/sphinx#4099 --- CHANGES | 1 + sphinx/domains/cpp.py | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 75911ab8c..ff312f1d0 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,7 @@ Bugs fixed * #4231: html: Apply fixFirefoxAnchorBug only under Firefox * #4221: napoleon depends on autodoc, but users need to load it manually * #2298: automodule fails to document a class attribute +* #4099: C++: properly link class reference to class from inside constructor Testing -------- diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index b81f6531e..23c398e13 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -3144,8 +3144,8 @@ class Symbol(object): return None return s - def find_name(self, nestedName, templateDecls, templateShorthand, matchSelf): - # type: (Any, Any, Any, bool) -> Symbol + def find_name(self, nestedName, templateDecls, typ, templateShorthand, matchSelf): + # type: (Any, Any, Any, Any, bool) -> Symbol # templateShorthand: missing template parameter lists for templates is ok # TODO: unify this with the _add_symbols @@ -3163,7 +3163,14 @@ class Symbol(object): while parentSymbol.parent: if parentSymbol.find_identifier(firstName.identifier, matchSelf=matchSelf): - break + # if we are in the scope of a constructor but wants to reference the class + # we need to walk one extra up + if (len(names) == 1 and typ == 'class' and matchSelf and + parentSymbol.parent and parentSymbol.parent.identifier and + parentSymbol.parent.identifier == firstName.identifier): + pass + else: + break parentSymbol = parentSymbol.parent iTemplateDecl = 0 @@ -4945,7 +4952,7 @@ class CPPDomain(Domain): templateDecls = ast.templatePrefix.templates else: templateDecls = [] - s = parentSymbol.find_name(name, templateDecls, + s = parentSymbol.find_name(name, templateDecls, typ, templateShorthand=True, matchSelf=True) if s is None or s.declaration is None: From 9158a5be1b0af4bd515e7d3c9b56d2151933e8e3 Mon Sep 17 00:00:00 2001 From: Matthew Fernandez Date: Sun, 5 Nov 2017 13:58:27 -0800 Subject: [PATCH 036/275] remove todo_emit_warnings override from a test that doesn't need it --- tests/test_ext_todo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_ext_todo.py b/tests/test_ext_todo.py index 4f01a07ab..6a4789928 100644 --- a/tests/test_ext_todo.py +++ b/tests/test_ext_todo.py @@ -86,7 +86,7 @@ def test_todo_not_included(app, status, warning): assert set(todo[1].astext() for todo in todos) == set(['todo in foo', 'todo in bar']) @pytest.mark.sphinx('latex', testroot='ext-todo', freshenv=True, - confoverrides={'todo_include_todos': True, 'todo_emit_warnings': True}) + confoverrides={'todo_include_todos': True}) def test_todo_valid_link(app, status, warning): """ Test that the inserted "original entry" links for todo items have a target From fd94702eedca9ce443f96fda1a9969ed54e81c54 Mon Sep 17 00:00:00 2001 From: Matthew Fernandez Date: Sun, 5 Nov 2017 14:01:55 -0800 Subject: [PATCH 037/275] fix #4214: Two todolist directives break sphinx-1.6.5 --- CHANGES | 1 + sphinx/ext/todo.py | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index ff312f1d0..28df20245 100644 --- a/CHANGES +++ b/CHANGES @@ -23,6 +23,7 @@ Bugs fixed * #4221: napoleon depends on autodoc, but users need to load it manually * #2298: automodule fails to document a class attribute * #4099: C++: properly link class reference to class from inside constructor +* #4214: Two todolist directives break sphinx-1.6.5 Testing -------- diff --git a/sphinx/ext/todo.py b/sphinx/ext/todo.py index a58422793..badfbc35f 100644 --- a/sphinx/ext/todo.py +++ b/sphinx/ext/todo.py @@ -178,7 +178,8 @@ def process_todo_nodes(app, doctree, fromdocname): todo_entry = todo_info['todo'] # Remove targetref from the (copied) node to avoid emitting a # duplicate label of the original entry when we walk this node. - del todo_entry['targetref'] + if 'targetref' in todo_entry: + del todo_entry['targetref'] # (Recursively) resolve references in the todo content env.resolve_references(todo_entry, todo_info['docname'], From 1b664248f4ed5e00f89574bd6568e86b29a9df0f Mon Sep 17 00:00:00 2001 From: Matthew Fernandez Date: Sun, 5 Nov 2017 13:48:43 -0800 Subject: [PATCH 038/275] update todo extension test to test multiple todolists This tests for regression of previous bug #4214: Two todolist directives break sphinx-1.6.5. --- tests/roots/test-ext-todo/index.rst | 2 ++ tests/test_ext_todo.py | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/roots/test-ext-todo/index.rst b/tests/roots/test-ext-todo/index.rst index 6b95f73fd..781473d6a 100644 --- a/tests/roots/test-ext-todo/index.rst +++ b/tests/roots/test-ext-todo/index.rst @@ -7,3 +7,5 @@ test for sphinx.ext.todo bar .. todolist:: + +.. todolist:: diff --git a/tests/test_ext_todo.py b/tests/test_ext_todo.py index 6a4789928..cee59fe9d 100644 --- a/tests/test_ext_todo.py +++ b/tests/test_ext_todo.py @@ -99,11 +99,13 @@ def test_todo_valid_link(app, status, warning): content = (app.outdir / 'TodoTests.tex').text() - # Look for the link to foo. We could equally well look for the link to bar. + # Look for the link to foo. Note that there are two of them because the + # source document uses todolist twice. We could equally well look for links + # to bar. link = r'\{\\hyperref\[\\detokenize\{(.*?foo.*?)}]\{\\sphinxcrossref{' \ r'\\sphinxstyleemphasis{original entry}}}}' m = re.findall(link, content) - assert len(m) == 1 + assert len(m) == 2 target = m[0] # Look for the targets of this link. From eff13bc4c457c0a9809952c751d62435803e79b9 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Mon, 27 Nov 2017 07:51:30 +0100 Subject: [PATCH 039/275] C++, fix bug in new sizeof... expression parsing See sphinx-doc/sphinx#4114 --- sphinx/domains/cpp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 4e9eaeec4..37adb1525 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -960,7 +960,7 @@ class ASTSizeofParamPack(ASTBase): def describe_signature(self, signode, mode, env, symbol): signode.append(nodes.Text('sizeof...(')) - self.identifier.describe_signature(signode, mode, env, symbol, "") + self.identifier.describe_signature(signode, mode, env, symbol=symbol, prefix="") signode.append(nodes.Text(')')) From 10ec24b80db30dd9f24ad821d9195a47e03d1e91 Mon Sep 17 00:00:00 2001 From: jfbu Date: Wed, 29 Nov 2017 17:07:10 +0100 Subject: [PATCH 040/275] Fix #4267 by passing `warn` option to package textcomp. This silences its silly build-breaking errors in case some font substitution proved necessary for the characters it supports. --- sphinx/texinputs/sphinx.sty | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index a28220cbc..232a53b2f 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -6,7 +6,7 @@ % \NeedsTeXFormat{LaTeX2e}[1995/12/01] -\ProvidesPackage{sphinx}[2017/07/24 v1.6.4 LaTeX package (Sphinx markup)] +\ProvidesPackage{sphinx}[2017/11/29 v1.6.6 LaTeX package (Sphinx markup)] % provides \ltx@ifundefined % (many packages load ltxcmds: graphicx does for pdftex and lualatex but @@ -39,7 +39,7 @@ \@ifclassloaded{memoir}{}{\RequirePackage{fancyhdr}} % for \text macro and \iffirstchoice@ conditional even if amsmath not loaded \RequirePackage{amstext} -\RequirePackage{textcomp} +\RequirePackage[warn]{textcomp} \RequirePackage{titlesec} \@ifpackagelater{titlesec}{2016/03/15}% {\@ifpackagelater{titlesec}{2016/03/21}% From 0ff217e1b277db4d93a0f25e03ec5add0d570586 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Thu, 30 Nov 2017 23:06:30 +0100 Subject: [PATCH 041/275] C++, fix hyperlinking of nested names --- CHANGES | 1 + sphinx/domains/cpp.py | 112 ++++++++++++++++++++++++++++----------- tests/test_domain_cpp.py | 4 ++ 3 files changed, 87 insertions(+), 30 deletions(-) diff --git a/CHANGES b/CHANGES index 39b9c5903..86366f215 100644 --- a/CHANGES +++ b/CHANGES @@ -83,6 +83,7 @@ Bugs fixed * #3882: Update the order of files for HTMLHelp and QTHelp * #3962: sphinx-apidoc does not recognize implicit namespace packages correctly +* C++: also hyperlink types in the name of declarations with qualified names. Testing -------- diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 37adb1525..81fee9e62 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -555,12 +555,12 @@ class DefinitionError(UnicodeMixin, Exception): class _DuplicateSymbolError(UnicodeMixin, Exception): - def __init__(self, symbol, candSymbol): - # type: (Symbol, Symbol) -> None + def __init__(self, symbol, declaration): + # type: (Symbol, Any) -> None assert symbol - assert candSymbol + assert declaration self.symbol = symbol - self.candSymbol = candSymbol + self.declaration = declaration def __unicode__(self): # type: () -> unicode @@ -1286,6 +1286,10 @@ class ASTTemplateParamType(ASTBase): id = self.get_identifier() return ASTNestedName([ASTNestedNameElement(id, None)], rooted=False) + @property + def isPack(self): + return self.data.parameterPack + def get_identifier(self): # type: () -> unicode return self.data.get_identifier() @@ -1447,6 +1451,16 @@ class ASTTemplateIntroductionParameter(ASTBase): self.identifier = identifier self.parameterPack = parameterPack + @property + def name(self): + # type: () -> ASTNestedName + id = self.get_identifier() + return ASTNestedName([ASTNestedNameElement(id, None)], rooted=False) + + @property + def isPack(self): + return self.parameterPack + def get_identifier(self): # type: () -> unicode return self.identifier @@ -1819,36 +1833,42 @@ class ASTNestedName(ASTBase): # type: (addnodes.desc_signature, unicode, BuildEnvironment, Symbol) -> None _verify_description_mode(mode) # just print the name part, with template args, not template params - if mode == 'lastIsName': - addname = [] # type: List[unicode] - if self.rooted: - addname.append('') - for n in self.names[:-1]: - addname.append(text_type(n)) - addname = '::'.join(addname) # type: ignore - if len(self.names) > 1: - addname += '::' - signode += addnodes.desc_addname(addname, addname) - self.names[-1].describe_signature(signode, mode, env, '', symbol) - elif mode == 'noneIsName': + if mode == 'noneIsName': signode += nodes.Text(text_type(self)) elif mode == 'param': name = text_type(self) signode += nodes.emphasis(name, name) - elif mode == 'markType': - # each element should be a pending xref targeting the complete + elif mode == 'markType' or mode == 'lastIsName': + # Each element should be a pending xref targeting the complete # prefix. however, only the identifier part should be a link, such # that template args can be a link as well. + # For 'lastIsName' we should also prepend template parameter lists. + templateParams = [] # type: List[Any] + if mode == 'lastIsName': + assert symbol is not None + if symbol.declaration.templatePrefix is not None: + templateParams = symbol.declaration.templatePrefix.templates + iTemplateParams = 0 + templateParamsPrefix = u'' prefix = '' # type: unicode first = True - for name in self.names: + names = self.names[:-1] if mode == 'lastIsName' else self.names + for name in names: if not first: signode += nodes.Text('::') prefix += '::' first = False if name != '': - name.describe_signature(signode, mode, env, prefix, symbol) # type: ignore + if name.templateArgs and iTemplateParams < len(templateParams): # type: ignore + templateParamsPrefix += text_type(templateParams[iTemplateParams]) + iTemplateParams += 1 + name.describe_signature(signode, 'markType', # type: ignore + env, templateParamsPrefix + prefix, symbol) prefix += text_type(name) + if mode == 'lastIsName': + if len(self.names) > 1: + signode += addnodes.desc_addname('::', '::') + self.names[-1].describe_signature(signode, mode, env, '', symbol) else: raise Exception('Unknown description mode: %s' % mode) @@ -3131,15 +3151,15 @@ class ASTDeclaration(ASTBase): def describe_signature(self, signode, mode, env, options): # type: (addnodes.desc_signature, unicode, BuildEnvironment, Dict) -> None _verify_description_mode(mode) + assert self.symbol # The caller of the domain added a desc_signature node. # Always enable multiline: signode['is_multiline'] = True # Put each line in a desc_signature_line node. mainDeclNode = addnodes.desc_signature_line() mainDeclNode.sphinx_cpp_tagname = 'declarator' - mainDeclNode['add_permalink'] = True + mainDeclNode['add_permalink'] = not self.symbol.isRedeclaration - assert self.symbol if self.templatePrefix: self.templatePrefix.describe_signature(signode, mode, env, symbol=self.symbol, @@ -3206,6 +3226,7 @@ class Symbol(object): self.templateArgs = templateArgs # identifier self.declaration = declaration self.docname = docname + self.isRedeclaration = False self._assert_invariants() self.children = [] # type: List[Any] @@ -3294,6 +3315,31 @@ class Symbol(object): # type: (Any, Any, Any, Any, Any, bool) -> Symbol assert (identifier is None) != (operator is None) + def isSpecialization(): + # the names of the template parameters must be given exactly as args + # and params that are packs must in the args be the name expanded + if len(templateParams.params) != len(templateArgs.args): + return True + for i in range(len(templateParams.params)): + param = templateParams.params[i] + arg = templateArgs.args[i] + # TODO: doing this by string manipulation is probably not the most efficient + paramName = text_type(param.name) + argTxt = text_type(arg) + isArgPackExpansion = argTxt.endswith('...') + if param.isPack != isArgPackExpansion: + return True + argName = argTxt[:-3] if isArgPackExpansion else argTxt + if paramName != argName: + return True + return False + if templateParams is not None and templateArgs is not None: + # If both are given, but it's not a specialization, then do lookup as if + # there is no argument list. + # For example: template int A::var; + if not isSpecialization(): + templateArgs = None + def matches(s): if s.identifier != identifier: return False @@ -3405,23 +3451,27 @@ class Symbol(object): # .. class:: Test symbol._fill_empty(declaration, docname) return symbol - # It may simply be a functin overload, so let's compare ids. + # It may simply be a function overload, so let's compare ids. + isRedeclaration = True candSymbol = Symbol(parent=parentSymbol, identifier=identifier, templateParams=templateParams, templateArgs=templateArgs, declaration=declaration, docname=docname) - newId = declaration.get_newest_id() - oldId = symbol.declaration.get_newest_id() - if newId != oldId: - # we already inserted the symbol, so return the new one - symbol = candSymbol - else: + if declaration.objectType == "function": + newId = declaration.get_newest_id() + oldId = symbol.declaration.get_newest_id() + if newId != oldId: + # we already inserted the symbol, so return the new one + symbol = candSymbol + isRedeclaration = False + if isRedeclaration: # Redeclaration of the same symbol. # Let the new one be there, but raise an error to the client # so it can use the real symbol as subscope. # This will probably result in a duplicate id warning. - raise _DuplicateSymbolError(symbol, candSymbol) + candSymbol.isRedeclaration = True + raise _DuplicateSymbolError(symbol, declaration) else: symbol = Symbol(parent=parentSymbol, identifier=identifier, templateParams=templateParams, @@ -5397,6 +5447,7 @@ class CPPObject(ObjectDescription): # Assume we are actually in the old symbol, # instead of the newly created duplicate. self.env.temp_data['cpp:last_symbol'] = e.symbol + self.warn("Duplicate declaration.") if ast.objectType == 'enumerator': self._add_enumerator_to_parent(ast) @@ -5738,6 +5789,7 @@ class CPPDomain(Domain): def _resolve_xref_inner(self, env, fromdocname, builder, typ, target, node, contnode, emitWarnings=True): # type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node, bool) -> nodes.Node # NOQA + class Warner(object): def warn(self, msg): if emitWarnings: diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py index 8c838fcf8..4183fa471 100644 --- a/tests/test_domain_cpp.py +++ b/tests/test_domain_cpp.py @@ -508,6 +508,10 @@ def test_templates(): check('class', "template A", {2:"I0E1A"}) check('class', "template typename T> A", {2:"II0E0E1A"}) + check('class', "template typename> A", {2: "II0E0E1A"}) + check('class', "template typename ...T> A", {2:"II0EDpE1A"}) + check('class', "template typename...> A", {2: "II0EDpE1A"}) + check('class', "template A", {2:"I_iE1A"}) check('class', "template A", {2:"I_iE1A"}) check('class', "template A", {2:"I_DpiE1A"}) From 88d7dc1bd33a2ee91c9fa7d4237603bf33b597aa Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Wed, 11 Oct 2017 16:54:45 +0100 Subject: [PATCH 042/275] quickstart: Simplify --(no-)option handling The standard pattern for doing this is to use a common 'dest'. Signed-off-by: Stephen Finucane --- sphinx/cmd/quickstart.py | 35 ++++++++++++++--------------------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/sphinx/cmd/quickstart.py b/sphinx/cmd/quickstart.py index ee35b5cc1..533555373 100644 --- a/sphinx/cmd/quickstart.py +++ b/sphinx/cmd/quickstart.py @@ -378,17 +378,14 @@ imgmath has been deselected.''') do_prompt(d, 'ext_githubpages', 'githubpages: create .nojekyll file ' 'to publish the document on GitHub pages (y/n)', 'n', boolean) - if 'no_makefile' in d: - d['makefile'] = False - elif 'makefile' not in d: + if 'makefile' not in d: print(''' A Makefile and a Windows command file can be generated for you so that you only have to run e.g. `make html' instead of invoking sphinx-build directly.''') do_prompt(d, 'makefile', 'Create Makefile? (y/n)', 'y', boolean) - if 'no_batchfile' in d: - d['batchfile'] = False - elif 'batchfile' not in d: + + if 'batchfile' not in d: do_prompt(d, 'batchfile', 'Create Windows command file? (y/n)', 'y', boolean) print() @@ -593,22 +590,22 @@ Makefile to be used with sphinx-build. group.add_argument('--extensions', metavar='EXTENSIONS', dest='extensions', action='append', help='enable extensions') - # TODO(stephenfin): Consider using mutually exclusive groups here group = parser.add_argument_group('Makefile and Batchfile creation') - group.add_argument('--makefile', action='store_true', default=False, + group.add_argument('--makefile', action='store_true', dest='makefile', help='create makefile') - group.add_argument('--no-makefile', action='store_true', default=False, - help='not create makefile') - group.add_argument('--batchfile', action='store_true', default=False, + group.add_argument('--no-makefile', action='store_false', dest='makefile', + help='do not create makefile') + group.add_argument('--batchfile', action='store_true', dest='batchfile', help='create batchfile') - group.add_argument('--no-batchfile', action='store_true', default=False, - help='not create batchfile') - group.add_argument('-M', '--no-use-make-mode', action='store_false', - dest='make_mode', default=False, - help='not use make-mode for Makefile/make.bat') + group.add_argument('--no-batchfile', action='store_false', + dest='batchfile', + help='do not create batchfile') group.add_argument('-m', '--use-make-mode', action='store_true', - dest='make_mode', default=True, + dest='make_mode', help='use make-mode for Makefile/make.bat') + group.add_argument('-M', '--no-use-make-mode', action='store_false', + dest='make_mode', + help='do not use make-mode for Makefile/make.bat') group = parser.add_argument_group('Project templating') group.add_argument('-t', '--templatedir', metavar='TEMPLATEDIR', @@ -652,10 +649,6 @@ def main(argv=sys.argv[1:]): d2.update(dict(("ext_" + ext, False) for ext in EXTENSIONS)) d2.update(d) d = d2 - if 'no_makefile' in d: - d['makefile'] = False - if 'no_batchfile' in d: - d['batchfile'] = False if not valid_dir(d): print() From 4c0f657ee6423d102a8fb3f2e05ca44257874416 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 12 Oct 2017 14:36:19 +0100 Subject: [PATCH 043/275] quickstart: Rework 'do_prompt' function The 'd' and 'key' values are used on a single line. Move these outside the function to allow us to do other things with this function. Signed-off-by: Stephen Finucane --- sphinx/cmd/quickstart.py | 92 +++++++++++++++++++++------------------- tests/test_quickstart.py | 63 +++++++++++---------------- 2 files changed, 72 insertions(+), 83 deletions(-) diff --git a/sphinx/cmd/quickstart.py b/sphinx/cmd/quickstart.py index 533555373..830e38fb3 100644 --- a/sphinx/cmd/quickstart.py +++ b/sphinx/cmd/quickstart.py @@ -159,8 +159,8 @@ def term_decode(text): return text.decode('latin1') -def do_prompt(d, key, text, default=None, validator=nonempty): - # type: (Dict, unicode, unicode, unicode, Callable[[unicode], Any]) -> None +def do_prompt(text, default=None, validator=nonempty): + # type: (unicode, unicode, Callable[[unicode], Any]) -> Union[unicode, bool] while True: if default is not None: prompt = PROMPT_PREFIX + '%s [%s]: ' % (text, default) # type: unicode @@ -191,7 +191,7 @@ def do_prompt(d, key, text, default=None, validator=nonempty): print(red('* ' + str(err))) continue break - d[key] = x + return x def convert_python_source(source, rex=re.compile(r"[uU]('.*?')")): @@ -251,7 +251,7 @@ Selected root path: %s''' % d['path'])) else: print(''' Enter the root path for documentation.''') - do_prompt(d, 'path', 'Root path for the documentation', '.', is_path) + d['path'] = do_prompt('Root path for the documentation', '.', is_path) while path.isfile(path.join(d['path'], 'conf.py')) or \ path.isfile(path.join(d['path'], 'source', 'conf.py')): @@ -260,8 +260,8 @@ Enter the root path for documentation.''') 'selected root path.')) print('sphinx-quickstart will not overwrite existing Sphinx projects.') print() - do_prompt(d, 'path', 'Please enter a new root path (or just Enter ' - 'to exit)', '', is_path) + d['path'] = do_prompt('Please enter a new root path (or just Enter ' + 'to exit)', '', is_path) if not d['path']: sys.exit(1) @@ -270,22 +270,22 @@ Enter the root path for documentation.''') You have two options for placing the build directory for Sphinx output. Either, you use a directory "_build" within the root path, or you separate "source" and "build" directories within the root path.''') - do_prompt(d, 'sep', 'Separate source and build directories (y/n)', 'n', - boolean) + d['sep'] = do_prompt('Separate source and build directories (y/n)', + 'n', boolean) if 'dot' not in d: print(''' Inside the root directory, two more directories will be created; "_templates" for custom HTML templates and "_static" for custom stylesheets and other static files. You can enter another prefix (such as ".") to replace the underscore.''') - do_prompt(d, 'dot', 'Name prefix for templates and static dir', '_', ok) + d['dot'] = do_prompt('Name prefix for templates and static dir', '_', ok) if 'project' not in d: print(''' The project name will occur in several places in the built documentation.''') - do_prompt(d, 'project', 'Project name') + d['project'] = do_prompt('Project name') if 'author' not in d: - do_prompt(d, 'author', 'Author name(s)') + d['author'] = do_prompt('Author name(s)') if 'version' not in d: print(''' @@ -294,9 +294,9 @@ software. Each version can have multiple releases. For example, for Python the version is something like 2.5 or 3.0, while the release is something like 2.5.1 or 3.0a1. If you don't need this dual structure, just set both to the same value.''') - do_prompt(d, 'version', 'Project version', '', allow_empty) + d['version'] = do_prompt('Project version', '', allow_empty) if 'release' not in d: - do_prompt(d, 'release', 'Project release', d['version'], allow_empty) + d['release'] = do_prompt('Project release', d['version'], allow_empty) if 'language' not in d: print(''' @@ -306,7 +306,7 @@ translate text that it generates into that language. For a list of supported codes, see http://sphinx-doc.org/config.html#confval-language.''') - do_prompt(d, 'language', 'Project language', 'en') + d['language'] = do_prompt('Project language', 'en') if d['language'] == 'en': d['language'] = None @@ -314,7 +314,7 @@ http://sphinx-doc.org/config.html#confval-language.''') print(''' The file name suffix for source files. Commonly, this is either ".txt" or ".rst". Only files with this suffix are considered documents.''') - do_prompt(d, 'suffix', 'Source file suffix', '.rst', suffix) + d['suffix'] = do_prompt('Source file suffix', '.rst', suffix) if 'master' not in d: print(''' @@ -322,8 +322,8 @@ One document is special in that it is considered the top node of the "contents tree", that is, it is the root of the hierarchical structure of the documents. Normally, this is "index", but if your "index" document is a custom template, you can also set this to another filename.''') - do_prompt(d, 'master', 'Name of your master document (without suffix)', - 'index') + d['master'] = do_prompt('Name of your master document (without suffix)', + 'index') while path.isfile(path.join(d['path'], d['master'] + d['suffix'])) or \ path.isfile(path.join(d['path'], 'source', d['master'] + d['suffix'])): @@ -332,62 +332,66 @@ document is a custom template, you can also set this to another filename.''') 'selected root path.' % (d['master'] + d['suffix']))) print('sphinx-quickstart will not overwrite the existing file.') print() - do_prompt(d, 'master', 'Please enter a new file name, or rename the ' - 'existing file and press Enter', d['master']) + d['master'] = do_prompt('Please enter a new file name, or rename the ' + 'existing file and press Enter', d['master']) if 'epub' not in d: print(''' Sphinx can also add configuration for epub output:''') - do_prompt(d, 'epub', 'Do you want to use the epub builder (y/n)', - 'n', boolean) + d['epub'] = do_prompt('Do you want to use the epub builder (y/n)', + 'n', boolean) if 'ext_autodoc' not in d: print(''' Please indicate if you want to use one of the following Sphinx extensions:''') - do_prompt(d, 'ext_autodoc', 'autodoc: automatically insert docstrings ' - 'from modules (y/n)', 'n', boolean) + d['ext_autodoc'] = do_prompt('autodoc: automatically insert docstrings ' + 'from modules (y/n)', 'n', boolean) if 'ext_doctest' not in d: - do_prompt(d, 'ext_doctest', 'doctest: automatically test code snippets ' - 'in doctest blocks (y/n)', 'n', boolean) + d['ext_doctest'] = do_prompt('doctest: automatically test code snippets ' + 'in doctest blocks (y/n)', 'n', boolean) if 'ext_intersphinx' not in d: - do_prompt(d, 'ext_intersphinx', 'intersphinx: link between Sphinx ' - 'documentation of different projects (y/n)', 'n', boolean) + d['ext_intersphinx'] = do_prompt('intersphinx: link between Sphinx ' + 'documentation of different projects (y/n)', + 'n', boolean) if 'ext_todo' not in d: - do_prompt(d, 'ext_todo', 'todo: write "todo" entries ' - 'that can be shown or hidden on build (y/n)', 'n', boolean) + d['ext_todo'] = do_prompt('todo: write "todo" entries that can be ' + 'shown or hidden on build (y/n)', 'n', boolean) if 'ext_coverage' not in d: - do_prompt(d, 'ext_coverage', 'coverage: checks for documentation ' - 'coverage (y/n)', 'n', boolean) + d['ext_coverage'] = do_prompt('coverage: checks for documentation ' + 'coverage (y/n)', 'n', boolean) if 'ext_imgmath' not in d: - do_prompt(d, 'ext_imgmath', 'imgmath: include math, rendered ' - 'as PNG or SVG images (y/n)', 'n', boolean) + d['ext_imgmath'] = do_prompt('imgmath: include math, rendered as PNG ' + 'or SVG images (y/n)', 'n', boolean) if 'ext_mathjax' not in d: - do_prompt(d, 'ext_mathjax', 'mathjax: include math, rendered in the ' - 'browser by MathJax (y/n)', 'n', boolean) + d['ext_mathjax'] = do_prompt('mathjax: include math, rendered in the ' + 'browser by MathJax (y/n)', 'n', boolean) if d['ext_imgmath'] and d['ext_mathjax']: print('''Note: imgmath and mathjax cannot be enabled at the same time. imgmath has been deselected.''') d['ext_imgmath'] = False if 'ext_ifconfig' not in d: - do_prompt(d, 'ext_ifconfig', 'ifconfig: conditional inclusion of ' - 'content based on config values (y/n)', 'n', boolean) + d['ext_ifconfig'] = do_prompt('ifconfig: conditional inclusion of ' + 'content based on config values (y/n)', + 'n', boolean) if 'ext_viewcode' not in d: - do_prompt(d, 'ext_viewcode', 'viewcode: include links to the source ' - 'code of documented Python objects (y/n)', 'n', boolean) + d['ext_viewcode'] = do_prompt('viewcode: include links to the source ' + 'code of documented Python objects (y/n)', + 'n', boolean) if 'ext_githubpages' not in d: - do_prompt(d, 'ext_githubpages', 'githubpages: create .nojekyll file ' - 'to publish the document on GitHub pages (y/n)', 'n', boolean) + d['ext_githubpages'] = do_prompt('githubpages: create .nojekyll file ' + 'to publish the document on GitHub ' + 'pages (y/n)', 'n', boolean) if 'makefile' not in d: print(''' A Makefile and a Windows command file can be generated for you so that you only have to run e.g. `make html' instead of invoking sphinx-build directly.''') - do_prompt(d, 'makefile', 'Create Makefile? (y/n)', 'y', boolean) + d['makefile'] = do_prompt('Create Makefile? (y/n)', 'y', boolean) if 'batchfile' not in d: - do_prompt(d, 'batchfile', 'Create Windows command file? (y/n)', - 'y', boolean) + d['batchfile'] = do_prompt('Create Windows command file? (y/n)', + 'y', boolean) print() diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py index 46ed3a0c1..81d16eae1 100644 --- a/tests/test_quickstart.py +++ b/tests/test_quickstart.py @@ -61,27 +61,7 @@ def teardown_module(): coloron() -def test_quickstart_inputstrip(): - d = {} - answers = { - 'Q1': 'Y', - 'Q2': ' Yes ', - 'Q3': 'N', - 'Q4': 'N ', - } - qs.term_input = mock_input(answers) - qs.do_prompt(d, 'k1', 'Q1') - assert d['k1'] == 'Y' - qs.do_prompt(d, 'k2', 'Q2') - assert d['k2'] == 'Yes' - qs.do_prompt(d, 'k3', 'Q3') - assert d['k3'] == 'N' - qs.do_prompt(d, 'k4', 'Q4') - assert d['k4'] == 'N' - - def test_do_prompt(): - d = {} answers = { 'Q2': 'v2', 'Q3': 'v3', @@ -90,24 +70,29 @@ def test_do_prompt(): 'Q6': 'foo', } qs.term_input = mock_input(answers) - try: - qs.do_prompt(d, 'k1', 'Q1') - except AssertionError: - assert 'k1' not in d - else: - assert False, 'AssertionError not raised' - qs.do_prompt(d, 'k1', 'Q1', default='v1') - assert d['k1'] == 'v1' - qs.do_prompt(d, 'k3', 'Q3', default='v3_default') - assert d['k3'] == 'v3' - qs.do_prompt(d, 'k2', 'Q2') - assert d['k2'] == 'v2' - qs.do_prompt(d, 'k4', 'Q4', validator=qs.boolean) - assert d['k4'] is True - qs.do_prompt(d, 'k5', 'Q5', validator=qs.boolean) - assert d['k5'] is False + + assert qs.do_prompt('Q1', default='v1') == 'v1' + assert qs.do_prompt('Q3', default='v3_default') == 'v3' + assert qs.do_prompt('Q2') == 'v2' + assert qs.do_prompt('Q4', validator=qs.boolean) is True + assert qs.do_prompt('Q5', validator=qs.boolean) is False with pytest.raises(AssertionError): - qs.do_prompt(d, 'k6', 'Q6', validator=qs.boolean) + qs.do_prompt('Q6', validator=qs.boolean) + + +def test_do_prompt_inputstrip(): + answers = { + 'Q1': 'Y', + 'Q2': ' Yes ', + 'Q3': 'N', + 'Q4': 'N ', + } + qs.term_input = mock_input(answers) + + assert qs.do_prompt('Q1') == 'Y' + assert qs.do_prompt('Q2') == 'Yes' + assert qs.do_prompt('Q3') == 'N' + assert qs.do_prompt('Q4') == 'N' def test_do_prompt_with_nonascii(): @@ -117,12 +102,12 @@ def test_do_prompt_with_nonascii(): } qs.term_input = mock_input(answers) try: - qs.do_prompt(d, 'k1', 'Q1', default=u'\u65e5\u672c') + result = qs.do_prompt('Q1', default=u'\u65e5\u672c') except UnicodeEncodeError: raise pytest.skip.Exception( 'non-ASCII console input not supported on this encoding: %s', qs.TERM_ENCODING) - assert d['k1'] == u'\u30c9\u30a4\u30c4' + assert result == u'\u30c9\u30a4\u30c4' def test_quickstart_defaults(tempdir): From d46273ca4a73d48dff60a1e95fbeb84b73516c8f Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sat, 21 Oct 2017 13:48:27 +0100 Subject: [PATCH 044/275] quickstart: Rework how we collect extensions This is a little more flexible than the existing set up and makes maximum use of argparse capabilities. This has the side-effect of no longer including configuration for the 'sphinx.ext.todo' extension when said extension is not enabled. Signed-off-by: Stephen Finucane --- sphinx/cmd/quickstart.py | 99 ++++++++++----------------- sphinx/ext/apidoc.py | 14 ++-- sphinx/templates/quickstart/conf.py_t | 31 ++++++--- tests/test_quickstart.py | 1 - 4 files changed, 67 insertions(+), 78 deletions(-) diff --git a/sphinx/cmd/quickstart.py b/sphinx/cmd/quickstart.py index 830e38fb3..46d42f10b 100644 --- a/sphinx/cmd/quickstart.py +++ b/sphinx/cmd/quickstart.py @@ -16,6 +16,7 @@ import os import re import sys import time +from collections import OrderedDict from io import open from os import path @@ -48,7 +49,22 @@ if False: TERM_ENCODING = getattr(sys.stdin, 'encoding', None) -DEFAULT_VALUE = { +EXTENSIONS = OrderedDict([ + ('autodoc', 'automatically insert docstrings from modules'), + ('doctest', 'automatically test code snippets in doctest blocks'), + ('intersphinx', 'link between Sphinx documentation of different projects'), + ('todo', 'write "todo" entries that can be shown or hidden on build'), + ('coverage', 'checks for documentation coverage'), + ('imgmath', 'include math, rendered as PNG or SVG images'), + ('mathjax', 'include math, rendered in the browser by MathJax'), + ('ifconfig', 'conditional inclusion of content based on config values'), + ('viewcode', + 'include links to the source code of documented Python objects'), + ('githubpages', + 'create .nojekyll file to publish the document on GitHub pages'), +]) + +DEFAULTS = { 'path': '.', 'sep': False, 'dot': '_', @@ -56,16 +72,10 @@ DEFAULT_VALUE = { 'suffix': '.rst', 'master': 'index', 'epub': False, - 'ext_autodoc': False, - 'ext_doctest': False, - 'ext_todo': False, 'makefile': True, 'batchfile': True, } -EXTENSIONS = ('autodoc', 'doctest', 'intersphinx', 'todo', 'coverage', - 'imgmath', 'mathjax', 'ifconfig', 'viewcode', 'githubpages') - PROMPT_PREFIX = '> ' @@ -235,7 +245,7 @@ def ask_user(d): * suffix: source file suffix * master: master document name * epub: use epub (bool) - * ext_*: extensions to use (bools) + * extensions: extensions to use (list) * makefile: make Makefile * batchfile: make command file """ @@ -341,46 +351,20 @@ Sphinx can also add configuration for epub output:''') d['epub'] = do_prompt('Do you want to use the epub builder (y/n)', 'n', boolean) - if 'ext_autodoc' not in d: - print(''' -Please indicate if you want to use one of the following Sphinx extensions:''') - d['ext_autodoc'] = do_prompt('autodoc: automatically insert docstrings ' - 'from modules (y/n)', 'n', boolean) - if 'ext_doctest' not in d: - d['ext_doctest'] = do_prompt('doctest: automatically test code snippets ' - 'in doctest blocks (y/n)', 'n', boolean) - if 'ext_intersphinx' not in d: - d['ext_intersphinx'] = do_prompt('intersphinx: link between Sphinx ' - 'documentation of different projects (y/n)', - 'n', boolean) - if 'ext_todo' not in d: - d['ext_todo'] = do_prompt('todo: write "todo" entries that can be ' - 'shown or hidden on build (y/n)', 'n', boolean) - if 'ext_coverage' not in d: - d['ext_coverage'] = do_prompt('coverage: checks for documentation ' - 'coverage (y/n)', 'n', boolean) - if 'ext_imgmath' not in d: - d['ext_imgmath'] = do_prompt('imgmath: include math, rendered as PNG ' - 'or SVG images (y/n)', 'n', boolean) - if 'ext_mathjax' not in d: - d['ext_mathjax'] = do_prompt('mathjax: include math, rendered in the ' - 'browser by MathJax (y/n)', 'n', boolean) - if d['ext_imgmath'] and d['ext_mathjax']: - print('''Note: imgmath and mathjax cannot be enabled at the same time. -imgmath has been deselected.''') - d['ext_imgmath'] = False - if 'ext_ifconfig' not in d: - d['ext_ifconfig'] = do_prompt('ifconfig: conditional inclusion of ' - 'content based on config values (y/n)', - 'n', boolean) - if 'ext_viewcode' not in d: - d['ext_viewcode'] = do_prompt('viewcode: include links to the source ' - 'code of documented Python objects (y/n)', - 'n', boolean) - if 'ext_githubpages' not in d: - d['ext_githubpages'] = do_prompt('githubpages: create .nojekyll file ' - 'to publish the document on GitHub ' - 'pages (y/n)', 'n', boolean) + if 'extensions' not in d: + print('Indicate which of the following Sphinx extensions should be ' + 'enabled:') + d['extensions'] = [] + for name, description in EXTENSIONS.items(): + if do_prompt('%s: %s (y/n)' % (name, description), 'n', boolean): + d['extensions'].append('sphinx.ext.%s' % name) + + # Handle conflicting options + if set(['sphinx.ext.imgmath', 'sphinx.ext.mathjax']).issubset( + d['extensions']): + print('Note: imgmath and mathjax cannot be enabled at the same ' + 'time. imgmath has been deselected.') + d['extensions'].remove('sphinx.ext.imgmath') if 'makefile' not in d: print(''' @@ -401,7 +385,6 @@ def generate(d, overwrite=True, silent=False, templatedir=None): template = QuickstartRenderer(templatedir=templatedir) texescape.init() - indent = ' ' * 4 if 'mastertoctree' not in d: d['mastertoctree'] = '' @@ -415,10 +398,6 @@ def generate(d, overwrite=True, silent=False, templatedir=None): d['now'] = time.asctime() d['project_underline'] = column_width(d['project']) * '=' d.setdefault('extensions', []) - for name in EXTENSIONS: - if d.get('ext_' + name): - d['extensions'].append('sphinx.ext.' + name) - d['extensions'] = (',\n' + indent).join(repr(name) for name in d['extensions']) d['copyright'] = time.strftime('%Y') + ', ' + d['author'] d['author_texescaped'] = text_type(d['author']).\ translate(texescape.tex_escape_map) @@ -588,11 +567,11 @@ Makefile to be used with sphinx-build. group = parser.add_argument_group('Extension options') for ext in EXTENSIONS: - group.add_argument('--ext-' + ext, action='store_true', - dest='ext_' + ext, default=False, + group.add_argument('--ext-%s' % ext, action='append_const', + const='sphinx.ext.%s' % ext, dest='extensions', help='enable %s extension' % ext) group.add_argument('--extensions', metavar='EXTENSIONS', dest='extensions', - action='append', help='enable extensions') + action='append', help='enable arbitrary extensions') group = parser.add_argument_group('Makefile and Batchfile creation') group.add_argument('--makefile', action='store_true', dest='makefile', @@ -649,8 +628,7 @@ def main(argv=sys.argv[1:]): # quiet mode with all required params satisfied, use default d.setdefault('version', '') d.setdefault('release', d['version']) - d2 = DEFAULT_VALUE.copy() - d2.update(dict(("ext_" + ext, False) for ext in EXTENSIONS)) + d2 = DEFAULTS.copy() d2.update(d) d = d2 @@ -673,13 +651,12 @@ def main(argv=sys.argv[1:]): if isinstance(value, binary_type): d[key] = term_decode(value) - # parse extensions list + # handle use of CSV-style extension values d.setdefault('extensions', []) for ext in d['extensions'][:]: if ',' in ext: d['extensions'].remove(ext) - for modname in ext.split(','): - d['extensions'].append(modname) + d['extensions'].extend(ext.split(',')) for variable in d.get('variables', []): try: diff --git a/sphinx/ext/apidoc.py b/sphinx/ext/apidoc.py index 6edab379b..0bdeb9865 100644 --- a/sphinx/ext/apidoc.py +++ b/sphinx/ext/apidoc.py @@ -358,8 +358,8 @@ Note: By default this script will not overwrite already created files.""") group = parser.add_argument_group('extension options') for ext in EXTENSIONS: - group.add_argument('--ext-' + ext, action='store_true', - dest='ext_' + ext, default=False, + group.add_argument('--ext-%s' % ext, action='append_const', + const='sphinx.ext.%s' % ext, dest='extensions', help='enable %s extension' % ext) return parser @@ -408,9 +408,8 @@ def main(argv=sys.argv[1:]): suffix = '.' + args.suffix, master = 'index', epub = True, - ext_autodoc = True, - ext_viewcode = True, - ext_todo = True, + extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', + 'sphinx.ext.todo'], makefile = True, batchfile = True, make_mode = True, @@ -420,9 +419,8 @@ def main(argv=sys.argv[1:]): module_path = rootpath, append_syspath = args.append_syspath, ) - enabled_exts = {'ext_' + ext: getattr(args, 'ext_' + ext) - for ext in EXTENSIONS if getattr(args, 'ext_' + ext)} - d.update(enabled_exts) + if args.extensions: + d['extensions'].extend(args.extensions) if isinstance(args.header, binary_type): d['project'] = d['project'].decode('utf-8') diff --git a/sphinx/templates/quickstart/conf.py_t b/sphinx/templates/quickstart/conf.py_t index 4e828f330..c42861c28 100644 --- a/sphinx/templates/quickstart/conf.py_t +++ b/sphinx/templates/quickstart/conf.py_t @@ -42,7 +42,11 @@ sys.path.insert(0, u'{{ module_path }}') # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = [{{ extensions }}] +extensions = [ +{%- for ext in extensions %} + '{{ ext }}', +{%- endfor %} +] # Add any paths that contain templates here, relative to this directory. templates_path = ['{{ dot }}templates'] @@ -85,9 +89,6 @@ exclude_patterns = [{{ exclude_patterns }}] # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' -# If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = {{ ext_todo }} - # -- Options for HTML output ---------------------------------------------- @@ -173,8 +174,8 @@ texinfo_documents = [ author, '{{ project_fn }}', 'One line description of project.', 'Miscellaneous'), ] +{%- if epub %} -{% if epub %} # -- Options for Epub output ---------------------------------------------- @@ -195,9 +196,23 @@ epub_copyright = copyright # A list of files that should not be packed into the epub file. epub_exclude_files = ['search.html'] -{% endif %} +{%- endif %} +{%- if extensions %} + + +# -- Extension configuration ---------------------------------------------- +{%- endif %} +{%- if 'sphinx.ext.intersphinx' in extensions %} + +# -- Options for intersphinx extension ------------------------------------ -{% if ext_intersphinx %} # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'https://docs.python.org/': None} -{% endif %} +{%- endif %} +{%- if 'sphinx.ext.todo' in extensions %} + +# -- Options for todo extension ------------------------------------------- + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True +{%- endif %} diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py index 81d16eae1..f69a0a58e 100644 --- a/tests/test_quickstart.py +++ b/tests/test_quickstart.py @@ -134,7 +134,6 @@ def test_quickstart_defaults(tempdir): assert ns['copyright'] == '%s, Georg Brandl' % time.strftime('%Y') assert ns['version'] == '0.1' assert ns['release'] == '0.1' - assert ns['todo_include_todos'] is False assert ns['html_static_path'] == ['_static'] assert ns['latex_documents'] == [ ('index', 'SphinxTest.tex', 'Sphinx Test Documentation', From 77ff7d7e90f2b50b00c39f8acfd93b4d9aacdcf8 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 9 Nov 2017 18:07:58 +1100 Subject: [PATCH 045/275] sphinx-build: Use 'ArgumentParser.error' This simplifies a common pattern used here. This does result in a change in the output code from 1 to 2 for some cases, but this shouldn't be an issue as we already emit 2 for any parser issues. Signed-off-by: Stephen Finucane --- sphinx/cmdline.py | 56 ++++++++++++++++++----------------------------- 1 file changed, 21 insertions(+), 35 deletions(-) diff --git a/sphinx/cmdline.py b/sphinx/cmdline.py index 11f1861d8..f18bbb286 100644 --- a/sphinx/cmdline.py +++ b/sphinx/cmdline.py @@ -182,11 +182,7 @@ def main(argv=sys.argv[1:]): # type: ignore # type: (List[unicode]) -> int parser = get_parser() - # parse options - try: - args = parser.parse_args(argv) - except SystemExit as err: - return err.code + args = parser.parse_args(argv) # get paths (first and second positional argument) try: @@ -194,34 +190,28 @@ def main(argv=sys.argv[1:]): # type: ignore confdir = abspath(args.confdir or srcdir) if args.noconfig: confdir = None + if not path.isdir(srcdir): - print('Error: Cannot find source directory `%s\'.' % srcdir, - file=sys.stderr) - return 1 + parser.error('cannot find source directory (%s)' % srcdir) if not args.noconfig and not path.isfile(path.join(confdir, 'conf.py')): - print('Error: Config directory doesn\'t contain a conf.py file.', - file=sys.stderr) - return 1 + parser.error("config directory doesn't contain a conf.py file " + "(%s)" % confdir) + outdir = abspath(args.outputdir) if srcdir == outdir: - print('Error: source directory and destination directory are same.', - file=sys.stderr) - return 1 + parser.error('source directory and destination directory are same') except UnicodeError: - print( - 'Error: Multibyte filename not supported on this filesystem ' - 'encoding (%r).' % fs_encoding, file=sys.stderr) - return 1 + parser.error('multibyte filename not supported on this filesystem ' + 'encoding (%r)' % fs_encoding) # handle remaining filename arguments filenames = args.filenames - errored = False + missing_files = [] for filename in filenames: if not path.isfile(filename): - print('Error: Cannot find file %r.' % filename, file=sys.stderr) - errored = True - if errored: - return 1 + missing_files.append(filename) + if missing_files: + parser.error('cannot find files %r' % missing_files) # likely encoding used for command-line arguments try: @@ -231,8 +221,7 @@ def main(argv=sys.argv[1:]): # type: ignore likely_encoding = None if args.force_all and filenames: - print('Error: Cannot combine -a option and filenames.', file=sys.stderr) - return 1 + parser.error('cannot combine -a option and filenames') if args.color == 'no' or (args.color == 'auto' and not color_terminal()): nocolor() @@ -245,15 +234,16 @@ def main(argv=sys.argv[1:]): # type: ignore if args.quiet: status = None + if args.really_quiet: status = warning = None + if warning and args.warnfile: try: warnfp = open(args.warnfile, 'w') except Exception as exc: - print('Error: Cannot open warning file %r: %s' % - (args.warnfile, exc), file=sys.stderr) - sys.exit(1) + parser.error('cannot open warning file %r: %s' % ( + args.warnfile, exc)) warning = Tee(warning, warnfp) # type: ignore error = warning @@ -262,9 +252,7 @@ def main(argv=sys.argv[1:]): # type: ignore try: key, val = val.split('=', 1) except ValueError: - print('Error: -D option argument must be in the form name=value.', - file=sys.stderr) - return 1 + parser.error('-D option argument must be in the form name=value') if likely_encoding and isinstance(val, binary_type): try: val = val.decode(likely_encoding) @@ -276,9 +264,7 @@ def main(argv=sys.argv[1:]): # type: ignore try: key, val = val.split('=') except ValueError: - print('Error: -A option argument must be in the form name=value.', - file=sys.stderr) - return 1 + parser.error('-A option argument must be in the form name=value') try: val = int(val) except ValueError: @@ -302,4 +288,4 @@ def main(argv=sys.argv[1:]): # type: ignore return app.statuscode except (Exception, KeyboardInterrupt) as exc: handle_exception(app, args, exc, error) - return 1 + return 2 From f3b440777bb75496e73c1869011aca3d1d1d1ac2 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Mon, 4 Dec 2017 09:44:29 +0100 Subject: [PATCH 046/275] C++, support explicit member instantiations See michaeljones/breathe#325 --- CHANGES | 1 + sphinx/domains/cpp.py | 65 +++++++++++++++++++++++++--------------- tests/test_domain_cpp.py | 7 +++++ 3 files changed, 49 insertions(+), 24 deletions(-) diff --git a/CHANGES b/CHANGES index 86366f215..234a9bdca 100644 --- a/CHANGES +++ b/CHANGES @@ -26,6 +26,7 @@ Features added * #2406: C++, add proper parsing of expressions, including linking of identifiers. * C++, add a ``cpp:expr`` role for inserting inline C++ expressions or types. * #4094: C++, allow empty template argument lists. +* C++, support explicit member instantiations with shorthand ``template`` prefix. * #3638: Allow to change a label of reference to equation using ``math_eqref_format`` diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 81fee9e62..7fa27d4af 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -960,7 +960,8 @@ class ASTSizeofParamPack(ASTBase): def describe_signature(self, signode, mode, env, symbol): signode.append(nodes.Text('sizeof...(')) - self.identifier.describe_signature(signode, mode, env, symbol=symbol, prefix="") + self.identifier.describe_signature(signode, mode, env, + symbol=symbol, prefix="", templateArgs="") signode.append(nodes.Text(')')) @@ -1195,11 +1196,11 @@ class ASTIdentifier(ASTBase): # type: () -> unicode return self.identifier - def describe_signature(self, signode, mode, env, prefix, symbol): - # type: (addnodes.desc_signature, unicode, BuildEnvironment, unicode, Symbol) -> None + def describe_signature(self, signode, mode, env, prefix, templateArgs, symbol): + # type: (Any, unicode, BuildEnvironment, unicode, unicode, Symbol) -> None _verify_description_mode(mode) if mode == 'markType': - targetText = prefix + self.identifier + targetText = prefix + self.identifier + templateArgs pnode = addnodes.pending_xref('', refdomain='cpp', reftype='identifier', reftarget=targetText, modname=None, @@ -1268,7 +1269,7 @@ class ASTTemplateKeyParamPackIdDefault(ASTBase): if self.identifier: if not self.parameterPack: signode += nodes.Text(' ') - self.identifier.describe_signature(signode, mode, env, '', symbol) + self.identifier.describe_signature(signode, mode, env, '', '', symbol) if self.default: signode += nodes.Text(' = ') self.default.describe_signature(signode, 'markType', env, symbol) @@ -1500,7 +1501,7 @@ class ASTTemplateIntroductionParameter(ASTBase): # type: (addnodes.desc_signature, unicode, BuildEnvironment, Symbol) -> None if self.parameterPack: signode += nodes.Text('...') - self.identifier.describe_signature(signode, mode, env, '', symbol) + self.identifier.describe_signature(signode, mode, env, '', '', symbol) class ASTTemplateIntroduction(ASTBase): @@ -1558,8 +1559,7 @@ class ASTTemplateIntroduction(ASTBase): class ASTTemplateDeclarationPrefix(ASTBase): def __init__(self, templates): # type: (List[Any]) -> None - assert templates is not None - assert len(templates) > 0 + # template is None means it's an explicit instantiation of a variable self.templates = templates def get_id(self, version): @@ -1775,8 +1775,9 @@ class ASTNestedNameElement(ASTBase): def describe_signature(self, signode, mode, env, prefix, symbol): # type: (addnodes.desc_signature, unicode, BuildEnvironment, unicode, Symbol) -> None - self.identifier.describe_signature(signode, mode, env, prefix, symbol) - if self.templateArgs: + tArgs = text_type(self.templateArgs) if self.templateArgs is not None else '' + self.identifier.describe_signature(signode, mode, env, prefix, tArgs, symbol) + if self.templateArgs is not None: self.templateArgs.describe_signature(signode, mode, env, symbol) @@ -1859,7 +1860,8 @@ class ASTNestedName(ASTBase): prefix += '::' first = False if name != '': - if name.templateArgs and iTemplateParams < len(templateParams): # type: ignore + if (name.templateArgs and # type: ignore + iTemplateParams < len(templateParams)): templateParamsPrefix += text_type(templateParams[iTemplateParams]) iTemplateParams += 1 name.describe_signature(signode, 'markType', # type: ignore @@ -3594,7 +3596,6 @@ class Symbol(object): matchSelf=matchSelf): break parentSymbol = parentSymbol.parent - iTemplateDecl = 0 for iName in range(len(names)): name = names[iName] @@ -3614,15 +3615,19 @@ class Symbol(object): assert iTemplateDecl == len(templateDecls) templateParams = None symbol = parentSymbol._find_named_symbol(identifier, - templateParams, - templateArgs, + templateParams, templateArgs, operator, templateShorthand=templateShorthand, matchSelf=matchSelf) - if symbol: + if symbol is not None: return symbol - else: - return None + # try without template params and args + symbol = parentSymbol._find_named_symbol(identifier, + None, None, + operator, + templateShorthand=templateShorthand, + matchSelf=matchSelf) + return symbol else: # there shouldn't be anything inside an operator assert not name.is_operator() @@ -5144,7 +5149,13 @@ class DefinitionParser(object): # the saved position is only used to provide a better error message pos = self.pos if self.skip_word("template"): - params = self._parse_template_parameter_list() # type: Any + try: + params = self._parse_template_parameter_list() # type: Any + except DefinitionError as e: + if objectType == 'member' and len(templates) == 0: + return ASTTemplateDeclarationPrefix(None) + else: + raise e else: params = self._parse_template_introduction() if not params: @@ -5161,20 +5172,25 @@ class DefinitionParser(object): return ASTTemplateDeclarationPrefix(templates) def _check_template_consistency(self, nestedName, templatePrefix, - fullSpecShorthand): - # type: (Any, Any, bool) -> ASTTemplateDeclarationPrefix + fullSpecShorthand, isMember=False): + # type: (Any, Any, Any, bool) -> ASTTemplateDeclarationPrefix numArgs = nestedName.num_templates() + isMemberInstantiation = False if not templatePrefix: numParams = 0 else: - numParams = len(templatePrefix.templates) + if isMember and templatePrefix.templates is None: + numParams = 0 + isMemberInstantiation = True + else: + numParams = len(templatePrefix.templates) if numArgs + 1 < numParams: self.fail("Too few template argument lists comapred to parameter" " lists. Argument lists: %d, Parameter lists: %d." % (numArgs, numParams)) if numArgs > numParams: numExtra = numArgs - numParams - if not fullSpecShorthand: + if not fullSpecShorthand and not isMemberInstantiation: msg = "Too many template argument lists compared to parameter" \ " lists. Argument lists: %d, Parameter lists: %d," \ " Extra empty parameters lists prepended: %d." \ @@ -5188,7 +5204,7 @@ class DefinitionParser(object): newTemplates = [] for i in range(numExtra): newTemplates.append(ASTTemplateParams([])) - if templatePrefix: + if templatePrefix and not isMemberInstantiation: newTemplates.extend(templatePrefix.templates) templatePrefix = ASTTemplateDeclarationPrefix(newTemplates) return templatePrefix @@ -5243,7 +5259,8 @@ class DefinitionParser(object): assert False templatePrefix = self._check_template_consistency(declaration.name, templatePrefix, - fullSpecShorthand=False) + fullSpecShorthand=False, + isMember=objectType == 'member') return ASTDeclaration(objectType, visibility, templatePrefix, declaration) diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py index 4183fa471..f3f0037f5 100644 --- a/tests/test_domain_cpp.py +++ b/tests/test_domain_cpp.py @@ -561,6 +561,13 @@ def test_templates(): check('concept', 'template Numerics = (... && Numeric)', {2:'IDpE8Numerics'}) + # explicit specializations of members + check('member', 'template<> int A::a', {2:'IEN1AIiE1aE'}) + check('member', 'template int A::a', {2: 'IEN1AIiE1aE'}, + output='template<> int A::a') # same as above + check('member', 'template<> template<> int A::B::b', {2:'IEIEN1AIiE1BIiE1bE'}) + check('member', 'template int A::B::b', {2: 'IEIEN1AIiE1BIiE1bE'}, + output='template<> template<> int A::B::b') # same as above def test_template_args(): From 6cb517dc2d857c3f3a1484ec0fc621ae43cfa453 Mon Sep 17 00:00:00 2001 From: jfbu Date: Mon, 20 Nov 2017 18:15:03 +0100 Subject: [PATCH 047/275] Fix #4249 by overriding Pygments latex formatter error highlighting --- sphinx/texinputs/sphinx.sty | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index a28220cbc..f6653e1a7 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -208,6 +208,17 @@ % stylesheet for highlighting with pygments \RequirePackage{sphinxhighlight} +% fix baseline increase from Pygments latex formatter in case of error tokens +% and keep \fboxsep's scope local via added braces +\def\PYG@tok@err{% + \def\PYG@bc##1{{\setlength{\fboxsep}{-\fboxrule}% + \fcolorbox[rgb]{1.00,0.00,0.00}{1,1,1}{\strut ##1}}}% +} +\def\PYG@tok@cs{% + \def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}% + \def\PYG@bc##1{{\setlength{\fboxsep}{0pt}% + \colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}% +}% %% OPTIONS From 21d1025739b55d2fe169e47de815deab8190bef5 Mon Sep 17 00:00:00 2001 From: jfbu Date: Wed, 6 Dec 2017 18:43:37 +0100 Subject: [PATCH 048/275] Update CHANGES for PR #4268 modified: CHANGES --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index ff312f1d0..ae1eb6142 100644 --- a/CHANGES +++ b/CHANGES @@ -23,6 +23,7 @@ Bugs fixed * #4221: napoleon depends on autodoc, but users need to load it manually * #2298: automodule fails to document a class attribute * #4099: C++: properly link class reference to class from inside constructor +* #4267: PDF build broken by № (Unicode U+2116) character Testing -------- From 90ee039e349080fb86037aae4d59153cc7f03f4f Mon Sep 17 00:00:00 2001 From: jfbu Date: Wed, 6 Dec 2017 19:02:11 +0100 Subject: [PATCH 049/275] =?UTF-8?q?Avoid=20=E2=84=96=20in=20CHANGES,=20as?= =?UTF-8?q?=20PDF=20built=20with=20language=3D"ja"=20does=20not=20render?= =?UTF-8?q?=20it?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index ae1eb6142..1e6613b75 100644 --- a/CHANGES +++ b/CHANGES @@ -23,7 +23,7 @@ Bugs fixed * #4221: napoleon depends on autodoc, but users need to load it manually * #2298: automodule fails to document a class attribute * #4099: C++: properly link class reference to class from inside constructor -* #4267: PDF build broken by № (Unicode U+2116) character +* #4267: PDF build broken by Unicode U+2116 NUMERO SIGN character Testing -------- From 70f8d4ddfcd7ee0a1873ed5a9fbde283a74f818c Mon Sep 17 00:00:00 2001 From: jfbu Date: Sun, 10 Dec 2017 12:16:35 +0100 Subject: [PATCH 050/275] Support ``:emphasize-lines:`` in PDF output (closes #1238) --- doc/latex.rst | 5 +++++ doc/markup/code.rst | 3 +++ sphinx/texinputs/sphinx.sty | 18 +++++++++++++++++- sphinx/writers/latex.py | 3 +++ tests/roots/test-directive-code/emphasize.rst | 7 +++++++ .../expects/longtable_having_verbatim.tex | 1 + .../expects/table_having_verbatim.tex | 1 + tests/test_directive_code.py | 8 ++++++++ tests/test_markup.py | 3 ++- 9 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 tests/roots/test-directive-code/emphasize.rst diff --git a/doc/latex.rst b/doc/latex.rst index 0cd91fa97..5c140d295 100644 --- a/doc/latex.rst +++ b/doc/latex.rst @@ -256,6 +256,11 @@ The available styling options ``VerbatimBorderColor`` default ``{rgb}{0,0,0}``. The frame color, defaults to black. +``VerbatimHighlightColor`` + default ``{rgb}{0.878,1,1}``. The color for highlighted lines. + + .. versionadded:: 1.6.6 + ``verbatimsep`` default ``\fboxsep``. The separation between code lines and the frame. diff --git a/doc/markup/code.rst b/doc/markup/code.rst index cb3e55bdc..9cb57129f 100644 --- a/doc/markup/code.rst +++ b/doc/markup/code.rst @@ -223,6 +223,9 @@ Includes .. versionchanged:: 1.6 With both ``start-after`` and ``lines`` in use, the first line as per ``start-after`` is considered to be with line number ``1`` for ``lines``. + .. versionchanged:: 1.6.6 + LaTeX supports the ``emphasize-lines`` option. + Caption and name ^^^^^^^^^^^^^^^^ diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 232a53b2f..b8412627b 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -159,6 +159,7 @@ % For highlighted code. \RequirePackage{fancyvrb} \fvset{fontsize=\small} +\define@key{FV}{hllines}{\def\sphinx@verbatim@checkifhl##1{\in@{, ##1,}{#1}}} % For hyperlinked footnotes in tables; also for gathering footnotes from % topic and warning blocks. Also to allow code-blocks in footnotes. \RequirePackage{footnotehyper-sphinx} @@ -299,6 +300,8 @@ \sphinxDeclareColorOption{OuterLinkColor}{{rgb}{0.216,0.439,0.388}} \sphinxDeclareColorOption{VerbatimColor}{{rgb}{1,1,1}} \sphinxDeclareColorOption{VerbatimBorderColor}{{rgb}{0,0,0}} +% also no prefix for this one, for consistency (sigh). Color as in minted! +\sphinxDeclareColorOption{VerbatimHighlightColor}{{rgb}{0.878,1,1}} % now the colours defined with "sphinx" prefix in their names \newcommand*{\sphinxDeclareSphinxColorOption}[2]{% % set the initial default @@ -886,11 +889,24 @@ \expandafter\def\expandafter\FV@SetupFont\expandafter {\FV@SetupFont\sbox\sphinxcontinuationbox {\spx@opt@verbatimcontinued}% \sbox\sphinxvisiblespacebox {\spx@opt@verbatimvisiblespace}}% - \def\FancyVerbFormatLine ##1{\hsize\linewidth + \def\FancyVerbFormatLine ##1{% + \expandafter\sphinx@verbatim@checkifhl + \expandafter{\the\value{FancyVerbLine}}% + \edef\sphinx@restorefboxsep{\fboxsep\the\fboxsep\relax}% + \toks@{% + \hsize\linewidth \vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@ \doublehyphendemerits\z@\finalhyphendemerits\z@ \strut ##1\strut}% }% + \ifin@ + \fboxsep0pt + \colorbox{VerbatimHighlightColor}{\sphinx@restorefboxsep\the\toks@}% + \sphinx@restorefboxsep + \else + \the\toks@ + \fi + }% \let\FV@Space\spx@verbatim@space % Allow breaks at special characters using \PYG... macros. \sphinxbreaksatspecials diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index df39c84fd..005f93a3d 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -2270,6 +2270,8 @@ class LaTeXTranslator(nodes.NodeVisitor): lang = self.hlsettingstack[-1][0] linenos = code.count('\n') >= self.hlsettingstack[-1][1] - 1 highlight_args = node.get('highlight_args', {}) + hllines = '\\fvset{hllines={, %s,}}%%' %\ + str(highlight_args.get('hl_lines', []))[1:-1] if 'language' in node: # code-block directives lang = node['language'] @@ -2308,6 +2310,7 @@ class LaTeXTranslator(nodes.NodeVisitor): hlcode += '\\end{sphinxVerbatimintable}' else: hlcode += '\\end{sphinxVerbatim}' + self.body.append('\n' + hllines) self.body.append('\n' + hlcode + '\n') if ids: self.body.append('\\let\\sphinxLiteralBlockLabel\\empty\n') diff --git a/tests/roots/test-directive-code/emphasize.rst b/tests/roots/test-directive-code/emphasize.rst new file mode 100644 index 000000000..95db574ce --- /dev/null +++ b/tests/roots/test-directive-code/emphasize.rst @@ -0,0 +1,7 @@ +Literal Includes with Highlighted Lines +======================================= + +.. literalinclude:: target.py + :language: python + :emphasize-lines: 5-6, 13-15, 24- + diff --git a/tests/roots/test-latex-table/expects/longtable_having_verbatim.tex b/tests/roots/test-latex-table/expects/longtable_having_verbatim.tex index 979385785..7b4fb6964 100644 --- a/tests/roots/test-latex-table/expects/longtable_having_verbatim.tex +++ b/tests/roots/test-latex-table/expects/longtable_having_verbatim.tex @@ -27,6 +27,7 @@ header2 \endlastfoot +\fvset{hllines={, ,}}% \begin{sphinxVerbatimintable}[commandchars=\\\{\}] \PYG{n}{hello} \PYG{n}{world} \end{sphinxVerbatimintable} diff --git a/tests/roots/test-latex-table/expects/table_having_verbatim.tex b/tests/roots/test-latex-table/expects/table_having_verbatim.tex index d8231817a..4a49e4cbb 100644 --- a/tests/roots/test-latex-table/expects/table_having_verbatim.tex +++ b/tests/roots/test-latex-table/expects/table_having_verbatim.tex @@ -10,6 +10,7 @@ header1 header2 \unskip}\relax \\ \hline +\fvset{hllines={, ,}}% \begin{sphinxVerbatimintable}[commandchars=\\\{\}] \PYG{n}{hello} \PYG{n}{world} \end{sphinxVerbatimintable} diff --git a/tests/test_directive_code.py b/tests/test_directive_code.py index 548a5d72c..e3069061b 100644 --- a/tests/test_directive_code.py +++ b/tests/test_directive_code.py @@ -349,6 +349,14 @@ def test_code_block_namedlink_latex(app, status, warning): assert link2 in latex +@pytest.mark.sphinx('latex', testroot='directive-code') +def test_code_block_emphasize_latex(app, status, warning): + app.builder.build(['emphasize']) + latex = (app.outdir / 'Python.tex').text(encoding='utf-8').replace('\r\n', '\n') + includes = '\\fvset{hllines={, 5, 6, 13, 14, 15, 24, 25, 26, 27,}}%\n' + assert includes in latex + + @pytest.mark.sphinx('xml', testroot='directive-code') def test_literal_include(app, status, warning): app.builder.build(['index']) diff --git a/tests/test_markup.py b/tests/test_markup.py index dfa4d74cf..9c41845fc 100644 --- a/tests/test_markup.py +++ b/tests/test_markup.py @@ -211,7 +211,8 @@ def get_verifier(verify, verify_re): 'verify', u'::\n\n @Γ\\∞${}', None, - (u'\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]\n' + (u'\\fvset{hllines={, ,}}%\n' + u'\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]\n' u'@\\(\\Gamma\\)\\PYGZbs{}\\(\\infty\\)\\PYGZdl{}\\PYGZob{}\\PYGZcb{}\n' u'\\end{sphinxVerbatim}'), ), From 8f2883761646fb1135349d72401dcec1c3f45a18 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 10 Dec 2017 21:08:52 +0900 Subject: [PATCH 051/275] Update CHANGES for PR #4274 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index 234a9bdca..de81172e5 100644 --- a/CHANGES +++ b/CHANGES @@ -12,6 +12,7 @@ Incompatible changes given directory. * #3929: apidoc: Move sphinx.apidoc to sphinx.ext.apidoc * #4226: apidoc: Generate new style makefile (make-mode) +* #4274: sphinx-build returns 2 as an exit code on argument error Deprecated ---------- From 38b5dff20690b17bd30825694b43a7f05706d44e Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 10 Dec 2017 21:10:56 +0900 Subject: [PATCH 052/275] Fix #4279: Sphinx crashes with pickling error when run with multiple processes and remote image --- CHANGES | 2 ++ sphinx/util/logging.py | 27 ++++++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index 1e6613b75..f2facb019 100644 --- a/CHANGES +++ b/CHANGES @@ -24,6 +24,8 @@ Bugs fixed * #2298: automodule fails to document a class attribute * #4099: C++: properly link class reference to class from inside constructor * #4267: PDF build broken by Unicode U+2116 NUMERO SIGN character +* #4279: Sphinx crashes with pickling error when run with multiple processes and + remote image Testing -------- diff --git a/sphinx/util/logging.py b/sphinx/util/logging.py index 41dc6022f..13a4cfe69 100644 --- a/sphinx/util/logging.py +++ b/sphinx/util/logging.py @@ -82,6 +82,10 @@ def convert_serializable(records): r.msg = r.getMessage() r.args = () + location = getattr(r, 'location', None) + if isinstance(location, nodes.Node): + r.location = get_node_location(location) + class SphinxWarningLogRecord(logging.LogRecord): """Log record class supporting location""" @@ -415,21 +419,26 @@ class WarningLogRecordTranslator(logging.Filter): else: record.location = None elif isinstance(location, nodes.Node): - (source, line) = get_source_line(location) - if source and line: - record.location = "%s:%s" % (source, line) - elif source: - record.location = "%s:" % source - elif line: - record.location = ":%s" % line - else: - record.location = None + record.location = get_node_location(location) elif location and ':' not in location: record.location = '%s' % self.app.env.doc2path(location) return True +def get_node_location(node): + # type: (nodes.Node) -> str + (source, line) = get_source_line(node) + if source and line: + return "%s:%s" % (source, line) + elif source: + return "%s:" % source + elif line: + return ":%s" % line + else: + return None + + class ColorizeFormatter(logging.Formatter): def format(self, record): # type: (logging.LogRecord) -> str From 8ac042a0f81a8aa5ea0a844ae229b43b16e9224c Mon Sep 17 00:00:00 2001 From: jfbu Date: Sun, 10 Dec 2017 15:45:57 +0100 Subject: [PATCH 053/275] Add emphasize-lines PDF support also under verbatimwrapslines=false --- sphinx/texinputs/sphinx.sty | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index b8412627b..7c2641b81 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -889,30 +889,31 @@ \expandafter\def\expandafter\FV@SetupFont\expandafter {\FV@SetupFont\sbox\sphinxcontinuationbox {\spx@opt@verbatimcontinued}% \sbox\sphinxvisiblespacebox {\spx@opt@verbatimvisiblespace}}% - \def\FancyVerbFormatLine ##1{% - \expandafter\sphinx@verbatim@checkifhl - \expandafter{\the\value{FancyVerbLine}}% - \edef\sphinx@restorefboxsep{\fboxsep\the\fboxsep\relax}% - \toks@{% - \hsize\linewidth + \def\sphinx@FancyVerbFormatLine ##1{\hsize\linewidth \vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@ \doublehyphendemerits\z@\finalhyphendemerits\z@ \strut ##1\strut}% }% - \ifin@ - \fboxsep0pt - \colorbox{VerbatimHighlightColor}{\sphinx@restorefboxsep\the\toks@}% - \sphinx@restorefboxsep - \else - \the\toks@ - \fi - }% \let\FV@Space\spx@verbatim@space % Allow breaks at special characters using \PYG... macros. \sphinxbreaksatspecials % Breaks at punctuation characters . , ; ? ! and / (needs catcode activation) \def\FancyVerbCodes{\sphinxbreaksviaactive}% - \fi % end of conditional code for wrapping long code lines + \else % end of conditional code for wrapping long code lines + \let\sphinx@FancyVerbFormatLine\FancyVerbFormatLine + \fi + \renewcommand\FancyVerbFormatLine[1]{% + \expandafter\sphinx@verbatim@checkifhl + \expandafter{\the\value{FancyVerbLine}}% + \ifin@ + \edef\sphinx@restorefboxsep{\fboxsep\the\fboxsep\relax}% + \fboxsep\z@ + \colorbox{VerbatimHighlightColor}% + {\sphinx@restorefboxsep\sphinx@FancyVerbFormatLine{##1}}% + \else + \sphinx@FancyVerbFormatLine{##1}% + \fi + }% % go around fancyvrb's check of \@currenvir \let\VerbatimEnvironment\sphinxVerbatimEnvironment % go around fancyvrb's check of current list depth From 347f15ca2805781662eb19d82999c84ef3a11eb8 Mon Sep 17 00:00:00 2001 From: jfbu Date: Sun, 10 Dec 2017 16:18:08 +0100 Subject: [PATCH 054/275] Make PDF support for emphasize-lines work with lineno-start like html --- sphinx/texinputs/sphinx.sty | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 7c2641b81..6a86cc433 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -904,7 +904,7 @@ \fi \renewcommand\FancyVerbFormatLine[1]{% \expandafter\sphinx@verbatim@checkifhl - \expandafter{\the\value{FancyVerbLine}}% + \expandafter{\the\numexpr\value{FancyVerbLine}-\spx@verbatim@linedelta}% \ifin@ \edef\sphinx@restorefboxsep{\fboxsep\the\fboxsep\relax}% \fboxsep\z@ @@ -914,6 +914,10 @@ \sphinx@FancyVerbFormatLine{##1}% \fi }% + % hook into this macro to recover the line numbering offset (default zero) + \expandafter\def\expandafter\FancyVerbCodes\expandafter{\FancyVerbCodes + \FV@SetLineNo + \edef\spx@verbatim@linedelta{\the\value{FancyVerbLine}}}% % go around fancyvrb's check of \@currenvir \let\VerbatimEnvironment\sphinxVerbatimEnvironment % go around fancyvrb's check of current list depth From c220ae3ecbc0b5d2fe007fb03d88b6e6719e9dfe Mon Sep 17 00:00:00 2001 From: jfbu Date: Sun, 10 Dec 2017 16:18:52 +0100 Subject: [PATCH 055/275] Update docs relative to emphasize-lines --- doc/markup/code.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/markup/code.rst b/doc/markup/code.rst index 9cb57129f..12eaa9b7d 100644 --- a/doc/markup/code.rst +++ b/doc/markup/code.rst @@ -121,6 +121,8 @@ emphasize particular lines:: .. versionchanged:: 1.3 ``lineno-start`` has been added. +.. versionchanged:: 1.6.6 + LaTeX supports the ``emphasize-lines`` option. Includes ^^^^^^^^ @@ -188,8 +190,8 @@ Includes ``lines``, the first allowed line having by convention the line number ``1``. When lines have been selected in any of the ways described above, the - line numbers in ``emphasize-lines`` also refer to the selection, with the - first selected line having number ``1``. + line numbers in ``emphasize-lines`` refer to those selected lines, counted + consecutively starting at ``1``. When specifying particular parts of a file to display, it can be useful to display the original line numbers. This can be done using the @@ -223,8 +225,6 @@ Includes .. versionchanged:: 1.6 With both ``start-after`` and ``lines`` in use, the first line as per ``start-after`` is considered to be with line number ``1`` for ``lines``. - .. versionchanged:: 1.6.6 - LaTeX supports the ``emphasize-lines`` option. Caption and name From 3bbfbadce539fd748525affe9b8eec31dc4f79b3 Mon Sep 17 00:00:00 2001 From: jfbu Date: Sun, 10 Dec 2017 16:51:10 +0100 Subject: [PATCH 056/275] Add a note for future maintenance by TeX hackers --- doc/markup/code.rst | 1 - sphinx/texinputs/sphinx.sty | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/markup/code.rst b/doc/markup/code.rst index 12eaa9b7d..0021af501 100644 --- a/doc/markup/code.rst +++ b/doc/markup/code.rst @@ -226,7 +226,6 @@ Includes With both ``start-after`` and ``lines`` in use, the first line as per ``start-after`` is considered to be with line number ``1`` for ``lines``. - Caption and name ^^^^^^^^^^^^^^^^ diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 6a86cc433..30308ede2 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -898,9 +898,12 @@ % Allow breaks at special characters using \PYG... macros. \sphinxbreaksatspecials % Breaks at punctuation characters . , ; ? ! and / (needs catcode activation) + % Hacker note: mark-up should not use codes=... option of Verbatim, but + % codes*=..., and \fvset{codes=...} if added by raw latex will be overwritten \def\FancyVerbCodes{\sphinxbreaksviaactive}% \else % end of conditional code for wrapping long code lines \let\sphinx@FancyVerbFormatLine\FancyVerbFormatLine + \let\FancyVerbCodes\@empty % only for clarity \fi \renewcommand\FancyVerbFormatLine[1]{% \expandafter\sphinx@verbatim@checkifhl From e583e5b0f3a761d3025fe0a247332ca2681e19f6 Mon Sep 17 00:00:00 2001 From: jfbu Date: Sun, 10 Dec 2017 17:11:55 +0100 Subject: [PATCH 057/275] Fix highlighting in PDF if wrapping of long code lines was _not_ enabled --- sphinx/texinputs/sphinx.sty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 30308ede2..4c9a6385f 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -902,7 +902,7 @@ % codes*=..., and \fvset{codes=...} if added by raw latex will be overwritten \def\FancyVerbCodes{\sphinxbreaksviaactive}% \else % end of conditional code for wrapping long code lines - \let\sphinx@FancyVerbFormatLine\FancyVerbFormatLine + \def\sphinx@FancyVerbFormatLine ##1{\hb@xt@\linewidth{\strut ##1\hss}}% \let\FancyVerbCodes\@empty % only for clarity \fi \renewcommand\FancyVerbFormatLine[1]{% From 34634d6225a5d6d5ff4e6ffe2677973d7fc6375c Mon Sep 17 00:00:00 2001 From: jfbu Date: Sun, 10 Dec 2017 23:31:44 +0100 Subject: [PATCH 058/275] Update CHANGES for PR #4250 --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 1e6613b75..780040c2a 100644 --- a/CHANGES +++ b/CHANGES @@ -24,6 +24,8 @@ Bugs fixed * #2298: automodule fails to document a class attribute * #4099: C++: properly link class reference to class from inside constructor * #4267: PDF build broken by Unicode U+2116 NUMERO SIGN character +* #4249: PDF output: Pygments error highlighting increases line spacing in + code blocks Testing -------- From 314f5291d4902b8a59afe602dc209132ddd74b3b Mon Sep 17 00:00:00 2001 From: jfbu Date: Mon, 11 Dec 2017 19:22:57 +0100 Subject: [PATCH 059/275] Replace two self.body.append by one in latex writer --- sphinx/writers/latex.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 005f93a3d..2c2b62659 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -2310,8 +2310,7 @@ class LaTeXTranslator(nodes.NodeVisitor): hlcode += '\\end{sphinxVerbatimintable}' else: hlcode += '\\end{sphinxVerbatim}' - self.body.append('\n' + hllines) - self.body.append('\n' + hlcode + '\n') + self.body.append('\n' + hllines + '\n' + hlcode + '\n') if ids: self.body.append('\\let\\sphinxLiteralBlockLabel\\empty\n') raise nodes.SkipNode From 2bbb699b01257615855f05ad2d7864354ce3da09 Mon Sep 17 00:00:00 2001 From: jfbu Date: Mon, 11 Dec 2017 21:15:58 +0100 Subject: [PATCH 060/275] Move some LaTeX macros for easier customizability if needed --- sphinx/texinputs/sphinx.sty | 67 ++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 4c9a6385f..cbd2b82e4 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -840,6 +840,32 @@ % needed to create wrapper environments of fancyvrb's Verbatim \newcommand*{\sphinxVerbatimEnvironment}{\gdef\FV@EnvironName{sphinxVerbatim}} +% serves to implement line highlighting and line wrapping +\newcommand\sphinxFancyVerbFormatLine[1]{% + \expandafter\sphinx@verbatim@checkifhl + \expandafter{\the\numexpr\value{FancyVerbLine}-\spx@verbatim@linedelta}% + \ifin@ + \edef\sphinx@restorefboxsep{\fboxsep\the\fboxsep\relax}% + \fboxsep\z@ + \colorbox{VerbatimHighlightColor}% + {\sphinx@restorefboxsep\sphinx@FancyVerbFormatLine{#1}}% + \else + \sphinx@FancyVerbFormatLine{#1}% + \fi +}% +\def\sphinx@FancyVerbFormatLine@wrap #1% +{\hsize\linewidth + \vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@ + \doublehyphendemerits\z@\finalhyphendemerits\z@ + \strut #1\strut}% +}% +\def\sphinx@FancyVerbFormatLine@nowrap #1{\hb@xt@\linewidth{\strut #1\hss}}% +\def\sphinx@FancyVerbCodesHook + {\FV@SetLineNo\edef\spx@verbatim@linedelta{\the\value{FancyVerbLine}}}% +\g@addto@macro\FV@SetupFont{% + \sbox\sphinxcontinuationbox {\spx@opt@verbatimcontinued}% + \sbox\sphinxvisiblespacebox {\spx@opt@verbatimvisiblespace}% +}% % Sphinx <1.5 optional argument was in fact mandatory. It is now really % optional and handled by original Verbatim. \newenvironment{sphinxVerbatim}{% @@ -886,41 +912,20 @@ % to achieve this without extensive rewrite of fancyvrb. % - The (not used in sphinx) obeytabs option to Verbatim is % broken by this change (showtabs and tabspace work). - \expandafter\def\expandafter\FV@SetupFont\expandafter - {\FV@SetupFont\sbox\sphinxcontinuationbox {\spx@opt@verbatimcontinued}% - \sbox\sphinxvisiblespacebox {\spx@opt@verbatimvisiblespace}}% - \def\sphinx@FancyVerbFormatLine ##1{\hsize\linewidth - \vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@ - \doublehyphendemerits\z@\finalhyphendemerits\z@ - \strut ##1\strut}% - }% - \let\FV@Space\spx@verbatim@space + \let\sphinx@FancyVerbFormatLine\sphinx@FancyVerbFormatLine@wrap + \let\FV@Space\spx@verbatim@space % Allow breaks at special characters using \PYG... macros. - \sphinxbreaksatspecials + \sphinxbreaksatspecials % Breaks at punctuation characters . , ; ? ! and / (needs catcode activation) - % Hacker note: mark-up should not use codes=... option of Verbatim, but - % codes*=..., and \fvset{codes=...} if added by raw latex will be overwritten - \def\FancyVerbCodes{\sphinxbreaksviaactive}% + \expandafter\def\expandafter\sphinx@FancyVerbCodesHook\expandafter + {\sphinx@FancyVerbCodesHook\sphinxbreaksviaactive}% \else % end of conditional code for wrapping long code lines - \def\sphinx@FancyVerbFormatLine ##1{\hb@xt@\linewidth{\strut ##1\hss}}% - \let\FancyVerbCodes\@empty % only for clarity + \let\sphinx@FancyVerbFormatLine\sphinx@FancyVerbFormatLine@nowrap \fi - \renewcommand\FancyVerbFormatLine[1]{% - \expandafter\sphinx@verbatim@checkifhl - \expandafter{\the\numexpr\value{FancyVerbLine}-\spx@verbatim@linedelta}% - \ifin@ - \edef\sphinx@restorefboxsep{\fboxsep\the\fboxsep\relax}% - \fboxsep\z@ - \colorbox{VerbatimHighlightColor}% - {\sphinx@restorefboxsep\sphinx@FancyVerbFormatLine{##1}}% - \else - \sphinx@FancyVerbFormatLine{##1}% - \fi - }% - % hook into this macro to recover the line numbering offset (default zero) - \expandafter\def\expandafter\FancyVerbCodes\expandafter{\FancyVerbCodes - \FV@SetLineNo - \edef\spx@verbatim@linedelta{\the\value{FancyVerbLine}}}% + \let\FancyVerbFormatLine\sphinxFancyVerbFormatLine + % hook into \FancyVerbCodes to recover at first code line the numbering offset + \expandafter\def\expandafter\FancyVerbCodes\expandafter + {\FancyVerbCodes\sphinx@FancyVerbCodesHook}% % go around fancyvrb's check of \@currenvir \let\VerbatimEnvironment\sphinxVerbatimEnvironment % go around fancyvrb's check of current list depth From f95464baf3b761b7fb437d7c5719ae62e6aba59a Mon Sep 17 00:00:00 2001 From: jfbu Date: Mon, 11 Dec 2017 22:10:53 +0100 Subject: [PATCH 061/275] Update CHANGES for PR #4285 --- CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index 780040c2a..74bbe17be 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,8 @@ Features added -------------- * #4181: autodoc: Sort dictionary keys when possible +* ``VerbatimHighlightColor`` is a new + :ref:`LaTeX 'sphinxsetup' ` key (refs: #4285) Bugs fixed ---------- @@ -26,6 +28,7 @@ Bugs fixed * #4267: PDF build broken by Unicode U+2116 NUMERO SIGN character * #4249: PDF output: Pygments error highlighting increases line spacing in code blocks +* #1238: Support ``:emphasize-lines:`` in PDF output Testing -------- From 1502fbda61240aae8ee799dc67c0536e0a210327 Mon Sep 17 00:00:00 2001 From: Dmitry Shachnev Date: Tue, 12 Dec 2017 00:12:45 +0300 Subject: [PATCH 062/275] Fix for reproducibility of htmlhelp and qthelp builds Make sure the generated list of files is sorted. This is similar to what was applied to EPub builder in 0b7c73a981. --- sphinx/builders/htmlhelp.py | 2 +- sphinx/builders/qthelp.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sphinx/builders/htmlhelp.py b/sphinx/builders/htmlhelp.py index 764b01aae..c2e3bbe2c 100644 --- a/sphinx/builders/htmlhelp.py +++ b/sphinx/builders/htmlhelp.py @@ -246,7 +246,7 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder): olen = len(outdir) for root, dirs, files in os.walk(outdir): staticdir = root.startswith(path.join(outdir, '_static')) - for fn in files: + for fn in sorted(files): if (staticdir and not fn.endswith('.js')) or \ fn.endswith('.html'): print(path.join(root, fn)[olen:].replace(os.sep, '\\'), diff --git a/sphinx/builders/qthelp.py b/sphinx/builders/qthelp.py index b1c94c548..14979fe4b 100644 --- a/sphinx/builders/qthelp.py +++ b/sphinx/builders/qthelp.py @@ -188,7 +188,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder): for root, dirs, files in os.walk(outdir): resourcedir = root.startswith(staticdir) or \ root.startswith(imagesdir) - for fn in files: + for fn in sorted(files): if (resourcedir and not fn.endswith('.js')) or \ fn.endswith('.html'): filename = path.join(root, fn)[olen:] From 43e6f1aa963cb85a1d65ea40a183598a05e1142b Mon Sep 17 00:00:00 2001 From: jfbu Date: Mon, 11 Dec 2017 23:09:19 +0100 Subject: [PATCH 063/275] Fix VerbatimHighlightColor key declared non-sphinx-prefixed colour name --- doc/latex.rst | 10 +++++----- sphinx/texinputs/sphinx.sty | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/latex.rst b/doc/latex.rst index 5c140d295..58833a829 100644 --- a/doc/latex.rst +++ b/doc/latex.rst @@ -261,6 +261,11 @@ The available styling options .. versionadded:: 1.6.6 +.. note:: + + Starting with this colour key, and for all others coming next, the actual + names declared to "color" or "xcolor" are prefixed with "sphinx". + ``verbatimsep`` default ``\fboxsep``. The separation between code lines and the frame. @@ -282,11 +287,6 @@ The available styling options default ``{rgb}{0,0,0}`` (black). The colour for the two horizontal rules used by Sphinx in LaTeX for styling a :dudir:`note` type admonition. -.. note:: - - The actual colour names declared to "color" or "xcolor" are prefixed with - "sphinx". - ``noteborder``, ``hintborder``, ``importantborder``, ``tipborder`` default ``0.5pt``. The width of the two horizontal rules. diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 8db09d4a2..49da59363 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -311,8 +311,6 @@ \sphinxDeclareColorOption{OuterLinkColor}{{rgb}{0.216,0.439,0.388}} \sphinxDeclareColorOption{VerbatimColor}{{rgb}{1,1,1}} \sphinxDeclareColorOption{VerbatimBorderColor}{{rgb}{0,0,0}} -% also no prefix for this one, for consistency (sigh). Color as in minted! -\sphinxDeclareColorOption{VerbatimHighlightColor}{{rgb}{0.878,1,1}} % now the colours defined with "sphinx" prefix in their names \newcommand*{\sphinxDeclareSphinxColorOption}[2]{% % set the initial default @@ -320,6 +318,8 @@ % set the key handler. The "value" ##1 must be acceptable by \definecolor. \define@key{sphinx}{#1}{\definecolor{sphinx#1}##1}% }% +% Default color chosen to be as in minted.sty LaTeX package! +\sphinxDeclareSphinxColorOption{VerbatimHighlightColor}{{rgb}{0.878,1,1}} % admonition boxes, "light" style \sphinxDeclareSphinxColorOption{noteBorderColor}{{rgb}{0,0,0}} \sphinxDeclareSphinxColorOption{hintBorderColor}{{rgb}{0,0,0}} @@ -858,7 +858,7 @@ \ifin@ \edef\sphinx@restorefboxsep{\fboxsep\the\fboxsep\relax}% \fboxsep\z@ - \colorbox{VerbatimHighlightColor}% + \colorbox{sphinxVerbatimHighlightColor}% {\sphinx@restorefboxsep\sphinx@FancyVerbFormatLine{#1}}% \else \sphinx@FancyVerbFormatLine{#1}% From a12399dbe429f552ab012099491c577de668a81d Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 7 Dec 2017 23:49:32 +0900 Subject: [PATCH 064/275] Refactor sphinx.io; independ parser generation from reader class --- sphinx/io.py | 41 ++++----------------------------------- sphinx/registry.py | 23 +++++++++++++++++++++- sphinx/transforms/i18n.py | 9 +++------ 3 files changed, 29 insertions(+), 44 deletions(-) diff --git a/sphinx/io.py b/sphinx/io.py index 84e1d7bb3..47e701f35 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -50,37 +50,6 @@ class SphinxBaseReader(standalone.Reader): """ Add our source parsers """ - def __init__(self, app, parsers={}, *args, **kwargs): - # type: (Sphinx, Dict[unicode, Parser], Any, Any) -> None - standalone.Reader.__init__(self, *args, **kwargs) - self.parser_map = {} # type: Dict[unicode, Parser] - for suffix, parser_class in parsers.items(): - if isinstance(parser_class, string_types): - parser_class = import_object(parser_class, 'source parser') # type: ignore - parser = parser_class() - if hasattr(parser, 'set_application'): - parser.set_application(app) - self.parser_map[suffix] = parser - - def read(self, source, parser, settings): - # type: (Input, Parser, Dict) -> nodes.document - self.source = source - - for suffix in self.parser_map: - if source.source_path.endswith(suffix): - self.parser = self.parser_map[suffix] - break - else: - # use special parser for unknown file-extension '*' (if exists) - self.parser = self.parser_map.get('*') - - if not self.parser: - self.parser = parser - self.settings = settings - self.input = self.source.read() - self.parse() - return self.document - def get_transforms(self): # type: () -> List[Transform] return standalone.Reader.get_transforms(self) + self.transforms @@ -114,17 +83,13 @@ class SphinxI18nReader(SphinxBaseReader): This class provides the correct line numbers when reporting. """ + lineno = None # type: int transforms = [ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences, DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, AutoNumbering, SortIds, RemoveTranslatableInline, FilterSystemMessages, RefOnlyBulletListTransform, UnreferencedFootnotesDetector] - def __init__(self, *args, **kwargs): - # type: (Any, Any) -> None - SphinxBaseReader.__init__(self, *args, **kwargs) - self.lineno = None # type: int - def set_lineno_for_reporter(self, lineno): # type: (int) -> None self.lineno = lineno @@ -216,11 +181,13 @@ class SphinxFileInput(FileInput): def read_doc(app, env, filename): # type: (Sphinx, BuildEnvironment, unicode) -> nodes.document """Parse a document and convert to doctree.""" - reader = SphinxStandaloneReader(app, parsers=app.registry.get_source_parsers()) + reader = SphinxStandaloneReader() source = SphinxFileInput(app, env, source=None, source_path=filename, encoding=env.config.source_encoding) + parser = app.registry.create_source_parser(app, filename) pub = Publisher(reader=reader, + parser=parser, writer=SphinxDummyWriter(), source_class=SphinxDummySourceClass, destination=NullOutput()) diff --git a/sphinx/registry.py b/sphinx/registry.py index 0861575db..c8ce4ad5e 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -13,15 +13,17 @@ from __future__ import print_function import traceback from pkg_resources import iter_entry_points -from six import itervalues +from six import iteritems, itervalues, string_types from sphinx.errors import ExtensionError, SphinxError, VersionRequirementError from sphinx.extension import Extension from sphinx.domains import ObjType from sphinx.domains.std import GenericObject, Target from sphinx.locale import __ +from sphinx.parsers import Parser as SphinxParser from sphinx.roles import XRefRole from sphinx.util import logging +from sphinx.util import import_object from sphinx.util.docutils import directive_helper if False: @@ -160,6 +162,25 @@ class SphinxComponentRegistry(object): raise ExtensionError(__('source_parser for %r is already registered') % suffix) self.source_parsers[suffix] = parser + def create_source_parser(self, app, filename): + # type: (Sphinx, unicode) -> Parser + for suffix, parser_class in iteritems(self.source_parsers): + if filename.endswith(suffix): + break + else: + # use special parser for unknown file-extension '*' (if exists) + parser_class = self.source_parsers.get('*') + + if parser_class is None: + raise SphinxError(__('Source parser for %s not registered') % filename) + else: + if isinstance(parser_class, string_types): + parser_class = import_object(parser_class, 'source parser') # type: ignore + parser = parser_class() + if isinstance(parser, SphinxParser): + parser.set_application(app) + return parser + def get_source_parsers(self): # type: () -> Dict[unicode, Parser] return self.source_parsers diff --git a/sphinx/transforms/i18n.py b/sphinx/transforms/i18n.py index 4c1fbc2a7..d08cc81f4 100644 --- a/sphinx/transforms/i18n.py +++ b/sphinx/transforms/i18n.py @@ -50,15 +50,12 @@ def publish_msgstr(app, source, source_path, source_line, config, settings): :rtype: docutils.nodes.document """ from sphinx.io import SphinxI18nReader - reader = SphinxI18nReader( - app=app, - parsers=app.registry.get_source_parsers(), - parser_name='restructuredtext', # default parser - ) + reader = SphinxI18nReader() reader.set_lineno_for_reporter(source_line) + parser = app.registry.create_source_parser(app, '') doc = reader.read( source=StringInput(source=source, source_path=source_path), - parser=reader.parser, + parser=parser, settings=settings, ) try: From a0200ad4995967fc28f0e6ac70d0f15779d0e8bb Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 15 Nov 2017 11:02:36 +0900 Subject: [PATCH 065/275] Refactor sphinx.io; dependent parser detection from SphinxFileInput --- sphinx/io.py | 13 +++---------- sphinx/registry.py | 19 ++++++++++++------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/sphinx/io.py b/sphinx/io.py index 47e701f35..71701e10d 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -140,22 +140,15 @@ class SphinxFileInput(FileInput): def read(self): # type: () -> unicode - def get_parser_type(source_path): - # type: (unicode) -> Tuple[unicode] - for suffix, parser_class in iteritems(self.app.registry.get_source_parsers()): - if source_path.endswith(suffix): - if isinstance(parser_class, string_types): - parser_class = import_object(parser_class, 'source parser') # type: ignore # NOQA - return parser_class.supported - return ('restructuredtext',) - data = FileInput.read(self) if self.app: arg = [data] self.app.emit('source-read', self.env.docname, arg) data = arg[0] + + parser = self.app.registry.get_source_parser(self.source_path) docinfo, data = split_docinfo(data) - if 'restructuredtext' in get_parser_type(self.source_path): + if 'restructuredtext' in parser.supported: if self.env.config.rst_epilog: data = data + '\n' + self.env.config.rst_epilog + '\n' if self.env.config.rst_prolog: diff --git a/sphinx/registry.py b/sphinx/registry.py index c8ce4ad5e..3723bcc29 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -157,13 +157,13 @@ class SphinxComponentRegistry(object): stddomain.object_types[directivename] = ObjType(objname or directivename, rolename) def add_source_parser(self, suffix, parser): - # type: (unicode, Parser) -> None + # type: (unicode, Type[Parser]) -> None if suffix in self.source_parsers: raise ExtensionError(__('source_parser for %r is already registered') % suffix) self.source_parsers[suffix] = parser - def create_source_parser(self, app, filename): - # type: (Sphinx, unicode) -> Parser + def get_source_parser(self, filename): + # type: (unicode) -> Type[Parser] for suffix, parser_class in iteritems(self.source_parsers): if filename.endswith(suffix): break @@ -176,15 +176,20 @@ class SphinxComponentRegistry(object): else: if isinstance(parser_class, string_types): parser_class = import_object(parser_class, 'source parser') # type: ignore - parser = parser_class() - if isinstance(parser, SphinxParser): - parser.set_application(app) - return parser + return parser_class def get_source_parsers(self): # type: () -> Dict[unicode, Parser] return self.source_parsers + def create_source_parser(self, app, filename): + # type: (Sphinx, unicode) -> Parser + parser_class = self.get_source_parser(filename) + parser = parser_class() + if isinstance(parser, SphinxParser): + parser.set_application(app) + return parser + def add_translator(self, name, translator): # type: (unicode, Type[nodes.NodeVisitor]) -> None self.translators[name] = translator From aa4fd0e1b7e3043dee6ad3344c477cc59d41f0e8 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 15 Nov 2017 11:34:52 +0900 Subject: [PATCH 066/275] refactor sphinx.io; SphinxFileInput can expect that app argument is always available --- sphinx/io.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sphinx/io.py b/sphinx/io.py index 71701e10d..c290e7831 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -141,10 +141,11 @@ class SphinxFileInput(FileInput): def read(self): # type: () -> unicode data = FileInput.read(self) - if self.app: - arg = [data] - self.app.emit('source-read', self.env.docname, arg) - data = arg[0] + + # emit source-read event + arg = [data] + self.app.emit('source-read', self.env.docname, arg) + data = arg[0] parser = self.app.registry.get_source_parser(self.source_path) docinfo, data = split_docinfo(data) From 0e86ff2f1133e529d148cea6cc235218d73cc7d4 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 15 Nov 2017 14:48:30 +0900 Subject: [PATCH 067/275] Refactor sphinx.io; separate FileInput class for each file type --- sphinx/application.py | 1 + sphinx/io.py | 41 ++++++++++++++++++++++++++++------------- sphinx/registry.py | 24 ++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index 209c73202..05d302c81 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -83,6 +83,7 @@ builtin_extensions = ( 'sphinx.directives.code', 'sphinx.directives.other', 'sphinx.directives.patches', + 'sphinx.io', 'sphinx.parsers', 'sphinx.roles', 'sphinx.transforms.post_transforms', diff --git a/sphinx/io.py b/sphinx/io.py index c290e7831..418e91b12 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -120,7 +120,9 @@ def SphinxDummySourceClass(source, *args, **kwargs): return source -class SphinxFileInput(FileInput): +class SphinxBaseFileInput(FileInput): + """A base class of SphinxFileInput.""" + def __init__(self, app, env, *args, **kwds): # type: (Sphinx, BuildEnvironment, Any, Any) -> None self.app = app @@ -145,16 +147,7 @@ class SphinxFileInput(FileInput): # emit source-read event arg = [data] self.app.emit('source-read', self.env.docname, arg) - data = arg[0] - - parser = self.app.registry.get_source_parser(self.source_path) - docinfo, data = split_docinfo(data) - if 'restructuredtext' in parser.supported: - if self.env.config.rst_epilog: - data = data + '\n' + self.env.config.rst_epilog + '\n' - if self.env.config.rst_prolog: - data = self.env.config.rst_prolog + '\n' + data - return docinfo + data + return arg[0] def warn_and_replace(self, error): # type: (Any) -> Tuple @@ -172,12 +165,29 @@ class SphinxFileInput(FileInput): return (u'?', error.end) +class SphinxFileInput(SphinxBaseFileInput): + pass + + +class SphinxRSTFileInput(SphinxBaseFileInput): + def read(self): + # type: () -> unicode + data = SphinxBaseFileInput.read(self) + docinfo, data = split_docinfo(data) + if self.env.config.rst_epilog: + data = data + '\n' + self.env.config.rst_epilog + '\n' + if self.env.config.rst_prolog: + data = self.env.config.rst_prolog + '\n' + data + return docinfo + data + + def read_doc(app, env, filename): # type: (Sphinx, BuildEnvironment, unicode) -> nodes.document """Parse a document and convert to doctree.""" + input_class = app.registry.get_source_input(filename) reader = SphinxStandaloneReader() - source = SphinxFileInput(app, env, source=None, source_path=filename, - encoding=env.config.source_encoding) + source = input_class(app, env, source=None, source_path=filename, + encoding=env.config.source_encoding) parser = app.registry.create_source_parser(app, filename) pub = Publisher(reader=reader, @@ -190,3 +200,8 @@ def read_doc(app, env, filename): pub.set_source(source, filename) pub.publish() return pub.document + + +def setup(app): + app.registry.add_source_input('*', SphinxFileInput) + app.registry.add_source_input('restructuredtext', SphinxRSTFileInput) diff --git a/sphinx/registry.py b/sphinx/registry.py index 3723bcc29..b627f23af 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -30,6 +30,7 @@ if False: # For type annotation from typing import Any, Callable, Dict, Iterator, List, Type # NOQA from docutils import nodes # NOQA + from docutils.io import Input # NOQA from docutils.parsers import Parser # NOQA from sphinx.application import Sphinx # NOQA from sphinx.builders import Builder # NOQA @@ -50,6 +51,7 @@ class SphinxComponentRegistry(object): self.builders = {} # type: Dict[unicode, Type[Builder]] self.domains = {} # type: Dict[unicode, Type[Domain]] self.source_parsers = {} # type: Dict[unicode, Parser] + self.source_inputs = {} # type: Dict[unicode, Input] self.translators = {} # type: Dict[unicode, nodes.NodeVisitor] def add_builder(self, builder): @@ -190,6 +192,28 @@ class SphinxComponentRegistry(object): parser.set_application(app) return parser + def add_source_input(self, filetype, input_class): + # type: (unicode, Type[Input]) -> None + if filetype in self.source_inputs: + raise ExtensionError(__('source_input for %r is already registered') % filetype) + self.source_inputs[filetype] = input_class + + def get_source_input(self, filename): + # type: (unicode) -> Type[Input] + parser = self.get_source_parser(filename) + for filetype in parser.supported: + if filetype in self.source_inputs: + input_class = self.source_inputs[filetype] + break + else: + # use special source_input for unknown file-type '*' (if exists) + input_class = self.source_inputs.get('*') + + if input_class is None: + raise SphinxError(__('source_input for %s not registered') % filename) + else: + return input_class + def add_translator(self, name, translator): # type: (unicode, Type[nodes.NodeVisitor]) -> None self.translators[name] = translator From 16c244cd6af79afa85202af1a0f1e325c175994f Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 14 Nov 2017 22:33:56 +0900 Subject: [PATCH 068/275] Add LoggingReporter.from_reporter() constructor --- sphinx/io.py | 4 +--- sphinx/util/docutils.py | 7 +++++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/sphinx/io.py b/sphinx/io.py index 418e91b12..5868bd7b5 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -58,9 +58,7 @@ class SphinxBaseReader(standalone.Reader): # type: () -> nodes.document document = standalone.Reader.new_document(self) reporter = document.reporter - document.reporter = LoggingReporter(reporter.source, reporter.report_level, - reporter.halt_level, reporter.debug_flag, - reporter.error_handler) + document.reporter = LoggingReporter.from_reporter(reporter) return document diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index 92e6c8c22..d24a8f827 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -167,6 +167,13 @@ class WarningStream(object): class LoggingReporter(Reporter): + @classmethod + def from_reporter(cls, reporter): + # type: (Reporter) -> LoggingReporter + """Create an instance of LoggingReporter from other reporter object.""" + return cls(reporter.source, reporter.report_level, reporter.halt_level, + reporter.debug_flag, reporter.error_handler) + def __init__(self, source, report_level, halt_level, debug=False, error_handler='backslashreplace'): # type: (unicode, int, int, bool, unicode) -> None From 773173b11f04f08547999c0799911fc7aa96d0d3 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 14 Nov 2017 22:34:32 +0900 Subject: [PATCH 069/275] Remove LoggingReporter.set_conditions() (unused) --- sphinx/util/docutils.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index d24a8f827..8da89713d 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -181,10 +181,6 @@ class LoggingReporter(Reporter): Reporter.__init__(self, source, report_level, halt_level, stream, debug, error_handler=error_handler) - def set_conditions(self, category, report_level, halt_level, debug=False): - # type: (unicode, int, int, bool) -> None - Reporter.set_conditions(self, category, report_level, halt_level, debug=debug) - def is_html5_writer_available(): # type: () -> bool From 07c5348a56471201b5901881b0d9d83f4823a6fd Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 7 Dec 2017 15:45:29 +0900 Subject: [PATCH 070/275] Add test_io.py --- sphinx/io.py | 55 ++++++++++++++++++--- sphinx/parsers.py | 22 +++++++++ sphinx/util/__init__.py | 10 ---- sphinx/util/docutils.py | 19 ++++++- tests/test_io.py | 107 ++++++++++++++++++++++++++++++++++++++++ tests/test_util.py | 25 +--------- 6 files changed, 195 insertions(+), 43 deletions(-) create mode 100644 tests/test_io.py diff --git a/sphinx/io.py b/sphinx/io.py index 5868bd7b5..056c763b1 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -8,13 +8,15 @@ :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ +import re import codecs from docutils.io import FileInput, NullOutput from docutils.core import Publisher from docutils.readers import standalone +from docutils.statemachine import StringList from docutils.writers import UnfilteredWriter -from six import string_types, text_type, iteritems +from six import text_type from typing import Any, Union # NOQA from sphinx.transforms import ( @@ -28,7 +30,6 @@ from sphinx.transforms.i18n import ( PreserveTranslatableMessages, Locale, RemoveTranslatableInline, ) from sphinx.util import logging -from sphinx.util import import_object, split_docinfo from sphinx.util.docutils import LoggingReporter if False: @@ -42,6 +43,8 @@ if False: from sphinx.builders import Builder # NOQA from sphinx.environment import BuildEnvironment # NOQA +docinfo_re = re.compile(':\\w+:.*?') + logger = logging.getLogger(__name__) @@ -59,6 +62,7 @@ class SphinxBaseReader(standalone.Reader): document = standalone.Reader.new_document(self) reporter = document.reporter document.reporter = LoggingReporter.from_reporter(reporter) + document.reporter.set_source(self.source) return document @@ -168,15 +172,50 @@ class SphinxFileInput(SphinxBaseFileInput): class SphinxRSTFileInput(SphinxBaseFileInput): + def prepend_prolog(self, text, prolog): + # type: (StringList, unicode) -> None + docinfo = self.count_docinfo_lines(text) + if docinfo: + # insert a blank line after docinfo + text.insert(docinfo, '', '', 0) + docinfo += 1 + + # insert prolog (after docinfo if exists) + for lineno, line in enumerate(prolog.splitlines()): + text.insert(docinfo + lineno, line, '', lineno) + + text.insert(docinfo + lineno + 1, '', '', 0) + + def append_epilog(self, text, epilog): + # type: (StringList, unicode) -> None + # append a blank line and rst_epilog + text.append('', '', 0) + for lineno, line in enumerate(epilog.splitlines()): + text.append(line, '', lineno) + def read(self): - # type: () -> unicode + # type: () -> StringList data = SphinxBaseFileInput.read(self) - docinfo, data = split_docinfo(data) - if self.env.config.rst_epilog: - data = data + '\n' + self.env.config.rst_epilog + '\n' + content = StringList() + for lineno, line in enumerate(data.splitlines()): + content.append(line, self.source_path, lineno) + if self.env.config.rst_prolog: - data = self.env.config.rst_prolog + '\n' + data - return docinfo + data + self.prepend_prolog(content, self.env.config.rst_prolog) + if self.env.config.rst_epilog: + self.append_epilog(content, self.env.config.rst_epilog) + + return content + + def count_docinfo_lines(self, content): + # type: (StringList) -> int + if len(content) == 0: + return 0 + else: + for lineno, line in enumerate(content.data): + if not docinfo_re.match(line): + break + return lineno def read_doc(app, env, filename): diff --git a/sphinx/parsers.py b/sphinx/parsers.py index 33556e487..085e45070 100644 --- a/sphinx/parsers.py +++ b/sphinx/parsers.py @@ -11,6 +11,8 @@ import docutils.parsers import docutils.parsers.rst +from docutils.parsers.rst import states +from docutils.statemachine import StringList from docutils.transforms.universal import SmartQuotes from sphinx.transforms import SphinxSmartQuotes @@ -66,6 +68,26 @@ class RSTParser(docutils.parsers.rst.Parser): transforms.append(SphinxSmartQuotes) return transforms + def parse(self, inputstring, document): + # type: (Any, nodes.document) -> None + """Parse text and generate a document tree. + + This derived method accepts StringList as a inputstring parameter. + It enables to handle mixed contents (cf. rst_prolog) correctly. + """ + if isinstance(inputstring, StringList): + self.setup_parse(inputstring, document) + self.statemachine = states.RSTStateMachine( + state_classes=self.state_classes, + initial_state=self.initial_state, + debug=document.reporter.debug_flag) + # Give inputstring directly to statemachine. + self.statemachine.run(inputstring, document, inliner=self.inliner) + self.finish_parse() + else: + # otherwise, inputstring might be a string. It will be handled by superclass. + docutils.parsers.rst.Parser.parse(self, inputstring, document) + def setup(app): # type: (Sphinx) -> Dict[unicode, Any] diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py index 03f8ce6a3..da0f6ac3a 100644 --- a/sphinx/util/__init__.py +++ b/sphinx/util/__init__.py @@ -564,16 +564,6 @@ def encode_uri(uri): return urlunsplit(split) -def split_docinfo(text): - # type: (unicode) -> Sequence[unicode] - docinfo_re = re.compile('\\A((?:\\s*:\\w+:.*?\n(?:[ \\t]+.*?\n)*)+)', re.M) - result = docinfo_re.split(text, 1) # type: ignore - if len(result) == 1: - return '', result[0] - else: - return result[1:] - - def display_chunk(chunk): # type: (Any) -> unicode if isinstance(chunk, (list, tuple)): diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index 8da89713d..d1b7ac431 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -18,8 +18,9 @@ from contextlib import contextmanager import docutils from docutils.languages import get_language -from docutils.utils import Reporter +from docutils.statemachine import ViewList from docutils.parsers.rst import directives, roles, convert_directive_function +from docutils.utils import Reporter from sphinx.errors import ExtensionError from sphinx.locale import __ @@ -33,6 +34,7 @@ if False: from typing import Any, Callable, Iterator, List, Tuple # NOQA from docutils import nodes # NOQA from sphinx.environment import BuildEnvironment # NOQA + from sphinx.io import SphinxFileInput # NOQA __version_info__ = tuple(LooseVersion(docutils.__version__).version) @@ -180,6 +182,21 @@ class LoggingReporter(Reporter): stream = WarningStream() Reporter.__init__(self, source, report_level, halt_level, stream, debug, error_handler=error_handler) + self.source_and_line = None + + def set_source(self, source): + # type: (SphinxFileInput) -> None + self.source_and_line = source + + def system_message(self, *args, **kwargs): + # type: (Any, Any) -> Any + if kwargs.get('line') and isinstance(self.source_and_line, ViewList): + # replace source parameter if source is set + source, lineno = self.source_and_line.info(kwargs.get('line')) + kwargs['source'] = source + kwargs['line'] = lineno + + return Reporter.system_message(self, *args, **kwargs) def is_html5_writer_available(): diff --git a/tests/test_io.py b/tests/test_io.py new file mode 100644 index 000000000..a017a2cc0 --- /dev/null +++ b/tests/test_io.py @@ -0,0 +1,107 @@ +# -*- coding: utf-8 -*- +""" + test_sphinx_io + ~~~~~~~~~~~~~~ + + Tests io modules. + + :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import pytest +from six import StringIO + +from sphinx.io import SphinxRSTFileInput + + +@pytest.mark.sphinx(testroot='basic') +def test_SphinxRSTFileInput(app): + app.env.temp_data['docname'] = 'index' + + # normal case + text = ('hello Sphinx world\n' + 'Sphinx is a document generator') + source = SphinxRSTFileInput(app, app.env, source=StringIO(text), + source_path='dummy.rst', encoding='utf-8') + result = source.read() + assert result.data == ['hello Sphinx world', + 'Sphinx is a document generator'] + assert result.info(0) == ('dummy.rst', 0) + assert result.info(1) == ('dummy.rst', 1) + assert result.info(2) == ('dummy.rst', None) # out of range + + # having rst_prolog ends without CR + app.env.config.rst_prolog = 'this is rst_prolog\nhello reST!' + source = SphinxRSTFileInput(app, app.env, source=StringIO(text), + source_path='dummy.rst', encoding='utf-8') + result = source.read() + assert result.data == ['this is rst_prolog', + 'hello reST!', + '', + 'hello Sphinx world', + 'Sphinx is a document generator'] + assert result.info(0) == ('', 0) + assert result.info(1) == ('', 1) + assert result.info(2) == ('', 0) + assert result.info(3) == ('dummy.rst', 0) + assert result.info(4) == ('dummy.rst', 1) + + # having rst_prolog ends with CR + app.env.config.rst_prolog = 'this is rst_prolog\nhello reST!\n' + source = SphinxRSTFileInput(app, app.env, source=StringIO(text), + source_path='dummy.rst', encoding='utf-8') + result = source.read() + assert result.data == ['this is rst_prolog', + 'hello reST!', + '', + 'hello Sphinx world', + 'Sphinx is a document generator'] + + # having docinfo and rst_prolog + docinfo_text = (':title: test of SphinxFileInput\n' + ':author: Sphinx team\n' + '\n' + 'hello Sphinx world\n' + 'Sphinx is a document generator\n') + app.env.config.rst_prolog = 'this is rst_prolog\nhello reST!' + source = SphinxRSTFileInput(app, app.env, source=StringIO(docinfo_text), + source_path='dummy.rst', encoding='utf-8') + result = source.read() + assert result.data == [':title: test of SphinxFileInput', + ':author: Sphinx team', + '', + 'this is rst_prolog', + 'hello reST!', + '', + '', + 'hello Sphinx world', + 'Sphinx is a document generator'] + assert result.info(0) == ('dummy.rst', 0) + assert result.info(1) == ('dummy.rst', 1) + assert result.info(2) == ('', 0) + assert result.info(3) == ('', 0) + assert result.info(4) == ('', 1) + assert result.info(5) == ('', 0) + assert result.info(6) == ('dummy.rst', 2) + assert result.info(7) == ('dummy.rst', 3) + assert result.info(8) == ('dummy.rst', 4) + assert result.info(9) == ('dummy.rst', None) # out of range + + # having rst_epilog + app.env.config.rst_prolog = None + app.env.config.rst_epilog = 'this is rst_epilog\ngood-bye reST!' + source = SphinxRSTFileInput(app, app.env, source=StringIO(text), + source_path='dummy.rst', encoding='utf-8') + result = source.read() + assert result.data == ['hello Sphinx world', + 'Sphinx is a document generator', + '', + 'this is rst_epilog', + 'good-bye reST!'] + assert result.info(0) == ('dummy.rst', 0) + assert result.info(1) == ('dummy.rst', 1) + assert result.info(2) == ('', 0) + assert result.info(3) == ('', 0) + assert result.info(4) == ('', 1) + assert result.info(5) == ('', None) # out of range diff --git a/tests/test_util.py b/tests/test_util.py index 84ce44007..aae54eaf0 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -14,8 +14,7 @@ from mock import patch from sphinx.util import logging from sphinx.util import ( - display_chunk, encode_uri, parselinenos, split_docinfo, status_iterator, - xmlname_checker + display_chunk, encode_uri, parselinenos, status_iterator, xmlname_checker ) from sphinx.testing.util import strip_escseq @@ -36,28 +35,6 @@ def test_encode_uri(): assert expected, encode_uri(uri) -def test_splitdocinfo(): - source = "Hello world.\n" - docinfo, content = split_docinfo(source) - assert docinfo == '' - assert content == 'Hello world.\n' - - source = ":orphan:\n\nHello world.\n" - docinfo, content = split_docinfo(source) - assert docinfo == ':orphan:\n' - assert content == '\nHello world.\n' - - source = ":author: Georg Brandl\n:title: Manual of Sphinx\n\nHello world.\n" - docinfo, content = split_docinfo(source) - assert docinfo == ':author: Georg Brandl\n:title: Manual of Sphinx\n' - assert content == '\nHello world.\n' - - source = ":multiline: one\n\ttwo\n\tthree\n\nHello world.\n" - docinfo, content = split_docinfo(source) - assert docinfo == ":multiline: one\n\ttwo\n\tthree\n" - assert content == '\nHello world.\n' - - def test_display_chunk(): assert display_chunk('hello') == 'hello' assert display_chunk(['hello']) == 'hello' From faadbef7575d63e617007040a64935e6a5226856 Mon Sep 17 00:00:00 2001 From: jfbu Date: Tue, 12 Dec 2017 10:56:54 +0100 Subject: [PATCH 071/275] Expose some sphinx.sty LaTeX internals for customizability (refs: #4285) --- CHANGES | 1 + doc/latex.rst | 5 +++++ sphinx/texinputs/sphinx.sty | 25 +++++++++++++++---------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index 74bbe17be..748eb2962 100644 --- a/CHANGES +++ b/CHANGES @@ -16,6 +16,7 @@ Features added * #4181: autodoc: Sort dictionary keys when possible * ``VerbatimHighlightColor`` is a new :ref:`LaTeX 'sphinxsetup' ` key (refs: #4285) +* Easier customizability of LaTeX macros involved in rendering of code-blocks Bugs fixed ---------- diff --git a/doc/latex.rst b/doc/latex.rst index 58833a829..2197efcd6 100644 --- a/doc/latex.rst +++ b/doc/latex.rst @@ -448,6 +448,11 @@ Environments .. versionadded:: 1.5 options ``verbatimwithframe``, ``verbatimwrapslines``, ``verbatimsep``, ``verbatimborder``. + .. versionadded:: 1.6.6 + support for ``:emphasize-lines:`` option + .. versionadded:: 1.6.6 + easier customizability of the formatting via exposed to user LaTeX macros + such as ``\sphinxVerbatimHighlightLine``. - the bibliography uses ``sphinxthebibliography`` and the Python Module index as well as the general index both use ``sphinxtheindex``; these environments are wrappers of the ``thebibliography`` and respectively ``theindex`` diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 49da59363..15fe9ee04 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -856,21 +856,26 @@ \expandafter\sphinx@verbatim@checkifhl \expandafter{\the\numexpr\value{FancyVerbLine}-\spx@verbatim@linedelta}% \ifin@ - \edef\sphinx@restorefboxsep{\fboxsep\the\fboxsep\relax}% - \fboxsep\z@ - \colorbox{sphinxVerbatimHighlightColor}% - {\sphinx@restorefboxsep\sphinx@FancyVerbFormatLine{#1}}% + \sphinxVerbatimHighlightLine{#1}% \else - \sphinx@FancyVerbFormatLine{#1}% + \sphinxVerbatimFormatLine{#1}% \fi }% -\def\sphinx@FancyVerbFormatLine@wrap #1% -{\hsize\linewidth +\newcommand\sphinxVerbatimHighlightLine[1]{% + \edef\sphinxrestorefboxsep{\fboxsep\the\fboxsep\relax}% + \fboxsep0pt\relax % cf LaTeX bug graphics/4524 + \colorbox{sphinxVerbatimHighlightColor}% + {\sphinxrestorefboxsep\sphinxVerbatimFormatLine{#1}}% + % no need to restore \fboxsep here, as this ends up in a \hbox from fancyvrb +}% +% \sphinxVerbatimFormatLine will be set locally to one of those two: +\newcommand\sphinxVerbatimFormatLineWrap[1]{% + \hsize\linewidth \vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@ \doublehyphendemerits\z@\finalhyphendemerits\z@ \strut #1\strut}% }% -\def\sphinx@FancyVerbFormatLine@nowrap #1{\hb@xt@\linewidth{\strut #1\hss}}% +\newcommand\sphinxVerbatimFormatLineNoWrap[1]{\hb@xt@\linewidth{\strut #1\hss}}% \def\sphinx@FancyVerbCodesHook {\FV@SetLineNo\edef\spx@verbatim@linedelta{\the\value{FancyVerbLine}}}% \g@addto@macro\FV@SetupFont{% @@ -923,7 +928,7 @@ % to achieve this without extensive rewrite of fancyvrb. % - The (not used in sphinx) obeytabs option to Verbatim is % broken by this change (showtabs and tabspace work). - \let\sphinx@FancyVerbFormatLine\sphinx@FancyVerbFormatLine@wrap + \let\sphinxVerbatimFormatLine\sphinxVerbatimFormatLineWrap \let\FV@Space\spx@verbatim@space % Allow breaks at special characters using \PYG... macros. \sphinxbreaksatspecials @@ -931,7 +936,7 @@ \expandafter\def\expandafter\sphinx@FancyVerbCodesHook\expandafter {\sphinx@FancyVerbCodesHook\sphinxbreaksviaactive}% \else % end of conditional code for wrapping long code lines - \let\sphinx@FancyVerbFormatLine\sphinx@FancyVerbFormatLine@nowrap + \let\sphinxVerbatimFormatLine\sphinxVerbatimFormatLineNoWrap \fi \let\FancyVerbFormatLine\sphinxFancyVerbFormatLine % hook into \FancyVerbCodes to recover at first code line the numbering offset From b5e50d652c351c81fd89afbb82d5a77575685271 Mon Sep 17 00:00:00 2001 From: jfbu Date: Tue, 12 Dec 2017 10:59:25 +0100 Subject: [PATCH 072/275] Update LaTeX style file's version date --- sphinx/texinputs/sphinx.sty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 15fe9ee04..45944885d 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -6,7 +6,7 @@ % \NeedsTeXFormat{LaTeX2e}[1995/12/01] -\ProvidesPackage{sphinx}[2017/11/29 v1.6.6 LaTeX package (Sphinx markup)] +\ProvidesPackage{sphinx}[2017/12/12 v1.6.6 LaTeX package (Sphinx markup)] % provides \ltx@ifundefined % (many packages load ltxcmds: graphicx does for pdftex and lualatex but From 0b0ac8b3bd0c6ff44c2465a7bdfdc67c375fe705 Mon Sep 17 00:00:00 2001 From: jfbu Date: Tue, 12 Dec 2017 11:02:19 +0100 Subject: [PATCH 073/275] Fix merge error --- sphinx/texinputs/sphinx.sty | 1 - 1 file changed, 1 deletion(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 0cf18f1ae..453234fd4 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -7,7 +7,6 @@ \NeedsTeXFormat{LaTeX2e}[1995/12/01] \ProvidesPackage{sphinx}[2017/12/12 v1.7 LaTeX package (Sphinx markup)] -\ProvidesPackage{sphinx}[2017/12/12 v1.6.6 LaTeX package (Sphinx markup)] % provides \ltx@ifundefined % (many packages load ltxcmds: graphicx does for pdftex and lualatex but From d4243a10fef2988d76d308668e4596c0a6873fc2 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 12 Dec 2017 23:28:30 +0900 Subject: [PATCH 074/275] Fix mypy violation --- sphinx/util/logging.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/util/logging.py b/sphinx/util/logging.py index 13a4cfe69..6148a5445 100644 --- a/sphinx/util/logging.py +++ b/sphinx/util/logging.py @@ -84,7 +84,7 @@ def convert_serializable(records): location = getattr(r, 'location', None) if isinstance(location, nodes.Node): - r.location = get_node_location(location) + r.location = get_node_location(location) # type: ignore class SphinxWarningLogRecord(logging.LogRecord): From d9006ef5b287ab459007833f549bc05b19ac7218 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Tue, 12 Dec 2017 09:54:20 +0100 Subject: [PATCH 075/275] C++, make function params linkable --- CHANGES | 3 +- sphinx/domains/cpp.py | 74 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 342aa92d2..caa8b1324 100644 --- a/CHANGES +++ b/CHANGES @@ -26,8 +26,8 @@ Features added * C++, handle ``decltype(auto)``. * #2406: C++, add proper parsing of expressions, including linking of identifiers. * C++, add a ``cpp:expr`` role for inserting inline C++ expressions or types. -* #4094: C++, allow empty template argument lists. * C++, support explicit member instantiations with shorthand ``template`` prefix. +* C++, make function parameters linkable, like template params. * #3638: Allow to change a label of reference to equation using ``math_eqref_format`` @@ -85,6 +85,7 @@ Bugs fixed * #3882: Update the order of files for HTMLHelp and QTHelp * #3962: sphinx-apidoc does not recognize implicit namespace packages correctly +* #4094: C++, allow empty template argument lists. * C++: also hyperlink types in the name of declarations with qualified names. Testing diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 6e08f2742..378c24da1 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -1977,8 +1977,13 @@ class ASTFunctionParameter(ASTBase): self.arg = arg self.ellipsis = ellipsis - def get_id(self, version): - # type: (int) -> unicode + def get_id(self, version, objectType=None, symbol=None): + # type: (int, unicode, Symbol) -> unicode + # this is not part of the normal name mangling in C++ + if symbol: + # the anchor will be our parent + return symbol.parent.declaration.get_id(version, prefixed=None) + # else, do the usual if self.ellipsis: return 'z' else: @@ -2013,6 +2018,11 @@ class ASTParametersQualifiers(ASTBase): self.final = final self.initializer = initializer + @property + def function_params(self): + # type: () -> Any + return self.args + def get_modifiers_id(self, version): # type: (int) -> unicode res = [] @@ -2316,6 +2326,11 @@ class ASTDeclaratorPtr(ASTBase): # type: () -> unicode return self.next.name + @property + def function_params(self): + # type: () -> Any + return self.next.function_params + def require_space_after_declSpecs(self): # type: () -> bool # TODO: if has paramPack, then False ? @@ -2408,6 +2423,11 @@ class ASTDeclaratorRef(ASTBase): # type: () -> unicode return self.next.name + @property + def function_params(self): + # type: () -> Any + return self.next.function_params + def require_space_after_declSpecs(self): # type: () -> bool return self.next.require_space_after_declSpecs() @@ -2459,6 +2479,11 @@ class ASTDeclaratorParamPack(ASTBase): # type: () -> unicode return self.next.name + @property + def function_params(self): + # type: () -> Any + return self.next.function_params + def require_space_after_declSpecs(self): # type: () -> bool return False @@ -2519,6 +2544,11 @@ class ASTDeclaratorMemPtr(ASTBase): # type: () -> unicode return self.next.name + @property + def function_params(self): + # type: () -> Any + return self.next.function_params + def require_space_after_declSpecs(self): # type: () -> bool return True @@ -2611,6 +2641,11 @@ class ASTDeclaratorParen(ASTBase): # type: () -> unicode return self.inner.name + @property + def function_params(self): + # type: () -> Any + return self.inner.function_params + def require_space_after_declSpecs(self): # type: () -> bool return True @@ -2673,6 +2708,11 @@ class ASTDeclaratorNameParamQual(ASTBase): # type: () -> unicode return self.declId + @property + def function_params(self): + # type: () -> Any + return self.paramQual.function_params + def get_modifiers_id(self, version): # only the modifiers for a function, e.g., # type: (int) -> unicode # cv-qualifiers @@ -2769,6 +2809,11 @@ class ASTType(ASTBase): name = self.decl.name return name + @property + def function_params(self): + # type: () -> Any + return self.decl.function_params + def get_id(self, version, objectType=None, symbol=None): # type: (int, unicode, Symbol) -> unicode if version == 1: @@ -3115,6 +3160,13 @@ class ASTDeclaration(ASTBase): # type: () -> unicode return self.declaration.name + @property + def function_params(self): + # type: () -> Any + if self.objectType != 'function': + return None + return self.declaration.function_params + def get_id(self, version, prefixed=True): # type: (int, bool) -> unicode if version == 1: @@ -3242,7 +3294,7 @@ class Symbol(object): for p in self.templateParams.params: if not p.get_identifier(): continue - # only add a declaration if we our selfs from a declaration + # only add a declaration if we our selfs are from a declaration if declaration: decl = ASTDeclaration('templateParam', None, None, p) else: @@ -3250,6 +3302,22 @@ class Symbol(object): nne = ASTNestedNameElement(p.get_identifier(), None) nn = ASTNestedName([nne], rooted=False) self._add_symbols(nn, [], decl, docname) + # add symbols for function parameters, if any + if declaration is not None and declaration.function_params is not None: + for p in declaration.function_params: + if p.arg is None: + continue + nn = p.arg.name + if nn is None: + continue + # (comparing to the template params: we have checked that we are a declaration) + decl = ASTDeclaration('functionParam', None, None, p) + assert not nn.rooted + assert len(nn.names) == 1 + identifier = nn.names[0].identifier + Symbol(parent=self, identifier=identifier, + templateParams=None, templateArgs=None, + declaration=decl, docname=docname) def _fill_empty(self, declaration, docname): # type: (Any, unicode) -> None From 809388d8366c845e921a5b679c8d3e90d545acc9 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Tue, 12 Dec 2017 15:03:41 +0100 Subject: [PATCH 076/275] C++, do not add index entries for decls in concepts --- CHANGES | 3 ++- sphinx/domains/cpp.py | 24 ++++++++++++++++++------ 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/CHANGES b/CHANGES index caa8b1324..77df660ac 100644 --- a/CHANGES +++ b/CHANGES @@ -86,7 +86,8 @@ Bugs fixed * #3882: Update the order of files for HTMLHelp and QTHelp * #3962: sphinx-apidoc does not recognize implicit namespace packages correctly * #4094: C++, allow empty template argument lists. -* C++: also hyperlink types in the name of declarations with qualified names. +* C++, also hyperlink types in the name of declarations with qualified names. +* C++, do not add index entries for declarations inside concepts. Testing -------- diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 378c24da1..c77c38413 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -5474,13 +5474,25 @@ class CPPObject(ObjectDescription): 'report as bug (id=%s).' % (text_type(ast), newestId)) name = text_type(ast.symbol.get_full_nested_name()).lstrip(':') - strippedName = name - for prefix in self.env.config.cpp_index_common_prefix: - if name.startswith(prefix): - strippedName = strippedName[len(prefix):] + # Add index entry, but not if it's a declaration inside a concept + isInConcept = False + s = ast.symbol.parent + while s is not None: + decl = s.declaration + s = s.parent + if decl is None: + continue + if decl.objectType == 'concept': + isInConcept = True break - indexText = self.get_index_text(strippedName) - self.indexnode['entries'].append(('single', indexText, newestId, '', None)) + if not isInConcept: + strippedName = name + for prefix in self.env.config.cpp_index_common_prefix: + if name.startswith(prefix): + strippedName = strippedName[len(prefix):] + break + indexText = self.get_index_text(strippedName) + self.indexnode['entries'].append(('single', indexText, newestId, '', None)) if newestId not in self.state.document.ids: # if the name is not unique, the first one will win From 8de0abd1b669b7ccf70a54187937d34dcfd69c56 Mon Sep 17 00:00:00 2001 From: jfbu Date: Wed, 13 Dec 2017 11:12:18 +0100 Subject: [PATCH 077/275] Make PDF highlighting work as expected also in absence of ``:linenos:`` Method at 347f15ca2 was overly complicated, due to not enough understanding of LaTeX package fancyvrb's innards. --- sphinx/texinputs/sphinx.sty | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 45944885d..2705cfdfe 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -853,8 +853,7 @@ \newcommand*{\sphinxVerbatimEnvironment}{\gdef\FV@EnvironName{sphinxVerbatim}} % serves to implement line highlighting and line wrapping \newcommand\sphinxFancyVerbFormatLine[1]{% - \expandafter\sphinx@verbatim@checkifhl - \expandafter{\the\numexpr\value{FancyVerbLine}-\spx@verbatim@linedelta}% + \expandafter\sphinx@verbatim@checkifhl\expandafter{\the\FV@CodeLineNo}% \ifin@ \sphinxVerbatimHighlightLine{#1}% \else @@ -876,8 +875,6 @@ \strut #1\strut}% }% \newcommand\sphinxVerbatimFormatLineNoWrap[1]{\hb@xt@\linewidth{\strut #1\hss}}% -\def\sphinx@FancyVerbCodesHook - {\FV@SetLineNo\edef\spx@verbatim@linedelta{\the\value{FancyVerbLine}}}% \g@addto@macro\FV@SetupFont{% \sbox\sphinxcontinuationbox {\spx@opt@verbatimcontinued}% \sbox\sphinxvisiblespacebox {\spx@opt@verbatimvisiblespace}% @@ -933,15 +930,11 @@ % Allow breaks at special characters using \PYG... macros. \sphinxbreaksatspecials % Breaks at punctuation characters . , ; ? ! and / (needs catcode activation) - \expandafter\def\expandafter\sphinx@FancyVerbCodesHook\expandafter - {\sphinx@FancyVerbCodesHook\sphinxbreaksviaactive}% + \fvset{codes*=\sphinxbreaksviaactive}% \else % end of conditional code for wrapping long code lines \let\sphinxVerbatimFormatLine\sphinxVerbatimFormatLineNoWrap \fi \let\FancyVerbFormatLine\sphinxFancyVerbFormatLine - % hook into \FancyVerbCodes to recover at first code line the numbering offset - \expandafter\def\expandafter\FancyVerbCodes\expandafter - {\FancyVerbCodes\sphinx@FancyVerbCodesHook}% % go around fancyvrb's check of \@currenvir \let\VerbatimEnvironment\sphinxVerbatimEnvironment % go around fancyvrb's check of current list depth From 6dae5db9af55807de1db4067203e57dabb6ed774 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 13 Dec 2017 20:49:50 +0900 Subject: [PATCH 078/275] Fix SphinxRSTFileInput should expand tabs --- sphinx/io.py | 7 ++++--- tests/test_io.py | 11 +++++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/sphinx/io.py b/sphinx/io.py index 056c763b1..5f34b74dd 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -14,7 +14,7 @@ import codecs from docutils.io import FileInput, NullOutput from docutils.core import Publisher from docutils.readers import standalone -from docutils.statemachine import StringList +from docutils.statemachine import StringList, string2lines from docutils.writers import UnfilteredWriter from six import text_type from typing import Any, Union # NOQA @@ -195,9 +195,10 @@ class SphinxRSTFileInput(SphinxBaseFileInput): def read(self): # type: () -> StringList - data = SphinxBaseFileInput.read(self) + inputstring = SphinxBaseFileInput.read(self) + lines = string2lines(inputstring, convert_whitespace=True) content = StringList() - for lineno, line in enumerate(data.splitlines()): + for lineno, line in enumerate(lines): content.append(line, self.source_path, lineno) if self.env.config.rst_prolog: diff --git a/tests/test_io.py b/tests/test_io.py index a017a2cc0..ecd4a1009 100644 --- a/tests/test_io.py +++ b/tests/test_io.py @@ -105,3 +105,14 @@ def test_SphinxRSTFileInput(app): assert result.info(3) == ('', 0) assert result.info(4) == ('', 1) assert result.info(5) == ('', None) # out of range + + # expandtabs / convert whitespaces + app.env.config.rst_prolog = None + app.env.config.rst_epilog = None + text = ('\thello Sphinx world\n' + '\v\fSphinx is a document generator') + source = SphinxRSTFileInput(app, app.env, source=StringIO(text), + source_path='dummy.rst', encoding='utf-8') + result = source.read() + assert result.data == [' hello Sphinx world', + ' Sphinx is a document generator'] From 974b1be21870344645655c875592d5ec5dde7f31 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Wed, 4 Oct 2017 23:25:19 +0100 Subject: [PATCH 079/275] Fix #1421: Respect the quiet flag in sphinx-quickstart Calling 'sphinx-quickstart --quiet' should not print anything to stdout. Resolve this. Signed-off-by: Stephen Finucane --- sphinx/quickstart.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index 67a59b059..d23dc3b74 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -455,11 +455,13 @@ def generate(d, overwrite=True, silent=False, templatedir=None): def write_file(fpath, content, newline=None): # type: (unicode, unicode, unicode) -> None if overwrite or not path.isfile(fpath): - print('Creating file %s.' % fpath) + if 'quiet' not in d: + print('Creating file %s.' % fpath) with open(fpath, 'wt', encoding='utf-8', newline=newline) as f: f.write(content) else: - print('File %s already exists, skipping.' % fpath) + if 'quiet' not in d: + print('File %s already exists, skipping.' % fpath) conf_path = os.path.join(templatedir, 'conf.py_t') if templatedir else None if not conf_path or not path.isfile(conf_path): From a5ef67b96a7c8aa362b2358766fba9150904e34d Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Wed, 13 Dec 2017 19:57:24 +0000 Subject: [PATCH 080/275] setup: Install mock for Python 3 too 'mock' is part of the standard library in Python 3 since Python 3.3. However, it's found in 'unittest.mock' - not 'mock'. We should install the version for PyPi in all cases to minimize differences between the two. When Python 2.7 support is dropped, we can consider switching to the standard library version. Signed-off-by: Stephen Finucane Fixes #4284 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index a4dd6b078..10a513166 100644 --- a/setup.py +++ b/setup.py @@ -68,13 +68,13 @@ extras_require = { 'whoosh>=2.0', ], 'test': [ + 'mock', 'pytest', 'pytest-cov', 'html5lib', ], 'test:python_version<"3"': [ 'enum34', - 'mock', ], 'test:python_version>="3"': [ 'mypy', From 64bb48ad2d19ec3c8fb636cd79ff0366e89dd097 Mon Sep 17 00:00:00 2001 From: jfbu Date: Wed, 13 Dec 2017 22:29:56 +0100 Subject: [PATCH 081/275] Fix some French English encountered in sphinx.sty's comments ... --- sphinx/texinputs/sphinx.sty | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 2705cfdfe..5ceb05e19 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -376,7 +376,7 @@ \expandafter\let \csname @list\romannumeral\the\count@\expandafter\endcsname \csname @list\romannumeral\the\numexpr\count@-\@ne\endcsname - % work around 2.6--3.2d babel-french issue (fixed in 3.2e; no change needed) + % workaround 2.6--3.2d babel-french issue (fixed in 3.2e; no change needed) \ltx@ifundefined{leftmargin\romannumeral\the\count@} {\expandafter\let \csname leftmargin\romannumeral\the\count@\expandafter\endcsname @@ -935,9 +935,9 @@ \let\sphinxVerbatimFormatLine\sphinxVerbatimFormatLineNoWrap \fi \let\FancyVerbFormatLine\sphinxFancyVerbFormatLine - % go around fancyvrb's check of \@currenvir + % workaround to fancyvrb's check of \@currenvir \let\VerbatimEnvironment\sphinxVerbatimEnvironment - % go around fancyvrb's check of current list depth + % workaround to fancyvrb's check of current list depth \def\@toodeep {\advance\@listdepth\@ne}% % The list environment is needed to control perfectly the vertical space. % Note: \OuterFrameSep used by framed.sty is later set to \topsep hence 0pt. @@ -1024,7 +1024,7 @@ \sphinxunactivateextras}% % now for the modified alltt environment \newenvironment{sphinxalltt} -{% at start of next line to work around Emacs/AUCTeX issue with this file +{% at start of next line to workaround Emacs/AUCTeX issue with this file \begin{alltt}% \ifspx@opt@parsedliteralwraps \sbox\sphinxcontinuationbox {\spx@opt@verbatimcontinued}% @@ -1250,7 +1250,7 @@ \spx@notice@border \dimexpr\csname spx@opt@#1border\endcsname\relax % start specific environment, passing the heading as argument \begin{sphinx#1}{#2}} - % in end part, need to go around a LaTeX's "feature" + % workaround some LaTeX "feature" of \end command {\edef\spx@temp{\noexpand\end{sphinx\spx@noticetype}}\spx@temp} % use of ``notice'' is for backwards compatibility and will be removed in % Sphinx 1.7. From 9b3ef92d7b52f3d2d21f1d1285af56d09dc71d4e Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 17 Jun 2017 22:31:38 +0900 Subject: [PATCH 082/275] autodoc: refactor MockImporter --- sphinx/ext/autodoc/__init__.py | 81 +++++++++++++++++----------------- sphinx/ext/autodoc/importer.py | 16 +++++-- 2 files changed, 53 insertions(+), 44 deletions(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 305242f66..d183331ae 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -24,7 +24,8 @@ from docutils.parsers.rst import Directive from docutils.statemachine import ViewList import sphinx -from sphinx.ext.autodoc.importer import _MockImporter, import_module +from sphinx.ext.autodoc.importer import mock, import_module +from sphinx.ext.autodoc.importer import _MockImporter # to keep compatibility # NOQA from sphinx.ext.autodoc.inspector import format_annotation, formatargspec # to keep compatibility # NOQA from sphinx.util import rpartition, force_decode from sphinx.locale import _ @@ -388,47 +389,45 @@ class Documenter(object): self.modname, '.'.join(self.objpath)) # always enable mock import hook # it will do nothing if autodoc_mock_imports is empty - import_hook = _MockImporter(self.env.config.autodoc_mock_imports) - try: - logger.debug('[autodoc] import %s', self.modname) - obj = import_module(self.modname, self.env.config.autodoc_warningiserror) - parent = None - self.module = obj - logger.debug('[autodoc] => %r', obj) - for part in self.objpath: - parent = obj - logger.debug('[autodoc] getattr(_, %r)', part) - obj = self.get_attr(obj, part) + with mock(self.env.config.autodoc_mock_imports): + try: + logger.debug('[autodoc] import %s', self.modname) + obj = import_module(self.modname, self.env.config.autodoc_warningiserror) + parent = None + self.module = obj logger.debug('[autodoc] => %r', obj) - self.object_name = part - self.parent = parent - self.object = obj - return True - # this used to only catch SyntaxError, ImportError and AttributeError, - # but importing modules with side effects can raise all kinds of errors - except (Exception, SystemExit) as e: - if self.objpath: - errmsg = 'autodoc: failed to import %s %r from module %r' % \ - (self.objtype, '.'.join(self.objpath), self.modname) - else: - errmsg = 'autodoc: failed to import %s %r' % \ - (self.objtype, self.fullname) - if isinstance(e, SystemExit): - errmsg += ('; the module executes module level statement ' + - 'and it might call sys.exit().') - elif isinstance(e, ImportError): - errmsg += '; the following exception was raised:\n%s' % e.args[0] - else: - errmsg += '; the following exception was raised:\n%s' % \ - traceback.format_exc() - if PY2: - errmsg = errmsg.decode('utf-8') # type: ignore - logger.debug(errmsg) - self.directive.warn(errmsg) - self.env.note_reread() - return False - finally: - import_hook.disable() + for part in self.objpath: + parent = obj + logger.debug('[autodoc] getattr(_, %r)', part) + obj = self.get_attr(obj, part) + logger.debug('[autodoc] => %r', obj) + self.object_name = part + self.parent = parent + self.object = obj + return True + # this used to only catch SyntaxError, ImportError and AttributeError, + # but importing modules with side effects can raise all kinds of errors + except (Exception, SystemExit) as e: + if self.objpath: + errmsg = 'autodoc: failed to import %s %r from module %r' % \ + (self.objtype, '.'.join(self.objpath), self.modname) + else: + errmsg = 'autodoc: failed to import %s %r' % \ + (self.objtype, self.fullname) + if isinstance(e, SystemExit): + errmsg += ('; the module executes module level statement ' + + 'and it might call sys.exit().') + elif isinstance(e, ImportError): + errmsg += '; the following exception was raised:\n%s' % e.args[0] + else: + errmsg += '; the following exception was raised:\n%s' % \ + traceback.format_exc() + if PY2: + errmsg = errmsg.decode('utf-8') # type: ignore + logger.debug(errmsg) + self.directive.warn(errmsg) + self.env.note_reread() + return False def get_real_modname(self): # type: () -> str diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py index e024d38f3..be03cba9b 100644 --- a/sphinx/ext/autodoc/importer.py +++ b/sphinx/ext/autodoc/importer.py @@ -10,15 +10,16 @@ """ import sys -import traceback import warnings +import traceback +import contextlib from types import FunctionType, MethodType, ModuleType from sphinx.util import logging if False: # For type annotation - from typing import Any, List, Set # NOQA + from typing import Any, Generator, List, Set # NOQA logger = logging.getLogger(__name__) @@ -77,7 +78,6 @@ class _MockModule(ModuleType): class _MockImporter(object): - def __init__(self, names): # type: (List[str]) -> None self.base_packages = set() # type: Set[str] @@ -120,6 +120,16 @@ class _MockImporter(object): return module +@contextlib.contextmanager +def mock(names): + # type: (List[str]) -> Generator + try: + importer = _MockImporter(names) + yield + finally: + importer.disable() + + def import_module(modname, warningiserror=False): """ Call __import__(modname), convert exceptions to ImportError From fdd87e504cc6e3632776bca771f874fa8ffa9701 Mon Sep 17 00:00:00 2001 From: jfbu Date: Thu, 14 Dec 2017 12:03:42 +0100 Subject: [PATCH 083/275] Docs of make latexpdfja --- doc/man/sphinx-build.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/man/sphinx-build.rst b/doc/man/sphinx-build.rst index 4866282d4..6194d89ff 100644 --- a/doc/man/sphinx-build.rst +++ b/doc/man/sphinx-build.rst @@ -103,7 +103,7 @@ Options **latexpdfja** Build LaTeX files and run them through :program:`platex/dvipdfmx`. - We recommend using ``latexpdf`` instead. + For Japanese documents. **info** Build Texinfo files and run them through :program:`makeinfo`. From e782ee6b630ceb820510a9c6584c5b340dcc9c3a Mon Sep 17 00:00:00 2001 From: jfbu Date: Thu, 14 Dec 2017 12:42:17 +0100 Subject: [PATCH 084/275] Again docs of make latexpdf/latexpdfja --- doc/man/sphinx-build.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/man/sphinx-build.rst b/doc/man/sphinx-build.rst index 6194d89ff..1a97919e9 100644 --- a/doc/man/sphinx-build.rst +++ b/doc/man/sphinx-build.rst @@ -100,16 +100,20 @@ Options **latexpdf** Build LaTeX files and run them through :program:`pdflatex`. + If :confval:`language` is set to ``'ja'``, build LaTeX files and run them + through :program:`platex/dvipdfmx`, rather. **latexpdfja** Build LaTeX files and run them through :program:`platex/dvipdfmx`. - For Japanese documents. + As :progname:`platex` is a TeX-engine designed for use with Japanese + LaTeX document classes, this is a priori not recommended (nor needed, see + previous item.) **info** Build Texinfo files and run them through :program:`makeinfo`. .. important:: - Sphinx only recognizes the ``-M`` option if it is placed first. + Sphinx only recognizes the ``-M`` option if it is placed first. .. versionadded:: 1.2.1 From a1b04e05d78e6b1c713e3ad0c85176e86701b14e Mon Sep 17 00:00:00 2001 From: jfbu Date: Thu, 14 Dec 2017 12:47:11 +0100 Subject: [PATCH 085/275] Remove docs of ``-M latexpdfja`` sphinx-build option Indeed, if latex_engine is not appropriately set, the ``make latexpdf`` then fails because the Makefile in latex build repertory is the one for pdflatex, not platex+dvipdfmx. Besides, if language is 'ja', then latexpdf automatically uses the platex latex_engine, hence the platex/dvipdfmx pipeline, and latexpdfja is not needed. For now, only removing documentation. --- doc/man/sphinx-build.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/doc/man/sphinx-build.rst b/doc/man/sphinx-build.rst index 1a97919e9..498425c4e 100644 --- a/doc/man/sphinx-build.rst +++ b/doc/man/sphinx-build.rst @@ -103,12 +103,6 @@ Options If :confval:`language` is set to ``'ja'``, build LaTeX files and run them through :program:`platex/dvipdfmx`, rather. - **latexpdfja** - Build LaTeX files and run them through :program:`platex/dvipdfmx`. - As :progname:`platex` is a TeX-engine designed for use with Japanese - LaTeX document classes, this is a priori not recommended (nor needed, see - previous item.) - **info** Build Texinfo files and run them through :program:`makeinfo`. From 7e75d46ea1b1b43f65782a482d326090c3992a45 Mon Sep 17 00:00:00 2001 From: jfbu Date: Thu, 14 Dec 2017 12:54:29 +0100 Subject: [PATCH 086/275] Again docs of ``-M latexpdf``! --- doc/man/sphinx-build.rst | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/man/sphinx-build.rst b/doc/man/sphinx-build.rst index 498425c4e..46f213989 100644 --- a/doc/man/sphinx-build.rst +++ b/doc/man/sphinx-build.rst @@ -99,9 +99,10 @@ Options :ref:`builders `, the following build pipelines are available: **latexpdf** - Build LaTeX files and run them through :program:`pdflatex`. - If :confval:`language` is set to ``'ja'``, build LaTeX files and run them - through :program:`platex/dvipdfmx`, rather. + Build LaTeX files and run them through :program:`pdflatex`, or as per + :confval:`latex_engine` setting. + If :confval:`language` is set to ``'ja'``, will use automatically + the :program:`platex/dvipdfmx` latex to PDF pipeline. **info** Build Texinfo files and run them through :program:`makeinfo`. From 0dfa88ec4bd6d6443d6d63b8b1f1d87cdb308191 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 14 Dec 2017 21:15:36 +0900 Subject: [PATCH 087/275] Fix mypy violation --- sphinx/parsers.py | 1 + sphinx/util/docutils.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sphinx/parsers.py b/sphinx/parsers.py index 085e45070..5d19ae67c 100644 --- a/sphinx/parsers.py +++ b/sphinx/parsers.py @@ -20,6 +20,7 @@ from sphinx.transforms import SphinxSmartQuotes if False: # For type annotation from typing import Any, Dict, List, Type # NOQA + from docutils import nodes # NOQA from docutils.transforms import Transform # NOQA from sphinx.application import Sphinx # NOQA diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index d1b7ac431..00ea5919e 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -182,7 +182,7 @@ class LoggingReporter(Reporter): stream = WarningStream() Reporter.__init__(self, source, report_level, halt_level, stream, debug, error_handler=error_handler) - self.source_and_line = None + self.source_and_line = None # type: SphinxFileInput def set_source(self, source): # type: (SphinxFileInput) -> None From 51580fabb4be6d596f10dbc5de4757e99c076628 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 14 Dec 2017 21:15:36 +0900 Subject: [PATCH 088/275] Update docstrings --- sphinx/io.py | 48 +++++++++++++++++++++++++++++++++++++++++------ sphinx/parsers.py | 6 +++--- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/sphinx/io.py b/sphinx/io.py index 5f34b74dd..8a41069db 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -51,14 +51,20 @@ logger = logging.getLogger(__name__) class SphinxBaseReader(standalone.Reader): """ - Add our source parsers + A base class of readers for Sphinx. + + This replaces reporter by Sphinx's on generating document. """ + def get_transforms(self): # type: () -> List[Transform] return standalone.Reader.get_transforms(self) + self.transforms def new_document(self): # type: () -> nodes.document + """Creates a new document object which having a special reporter object good + for logging. + """ document = standalone.Reader.new_document(self) reporter = document.reporter document.reporter = LoggingReporter.from_reporter(reporter) @@ -68,7 +74,7 @@ class SphinxBaseReader(standalone.Reader): class SphinxStandaloneReader(SphinxBaseReader): """ - Add our own transforms. + A basic document reader for Sphinx. """ transforms = [ApplySourceWorkaround, ExtraTranslatableNodes, PreserveTranslatableMessages, Locale, CitationReferences, DefaultSubstitutions, MoveModuleTargets, @@ -79,10 +85,11 @@ class SphinxStandaloneReader(SphinxBaseReader): class SphinxI18nReader(SphinxBaseReader): """ - Replacer for document.reporter.get_source_and_line method. + A document reader for i18n. - reST text lines for translation do not have the original source line number. - This class provides the correct line numbers when reporting. + This returns the source line number of original text as current source line number + to let users know where the error happened. + Because the translated texts are partial and they don't have correct line numbers. """ lineno = None # type: int @@ -94,10 +101,14 @@ class SphinxI18nReader(SphinxBaseReader): def set_lineno_for_reporter(self, lineno): # type: (int) -> None + """Stores the source line number of original text.""" self.lineno = lineno def new_document(self): # type: () -> nodes.document + """Creates a new document object which having a special reporter object for + translation. + """ document = SphinxBaseReader.new_document(self) reporter = document.reporter @@ -110,6 +121,8 @@ class SphinxI18nReader(SphinxBaseReader): class SphinxDummyWriter(UnfilteredWriter): + """Dummy writer module used for generating doctree.""" + supported = ('html',) # needed to keep "meta" nodes def translate(self): @@ -123,7 +136,11 @@ def SphinxDummySourceClass(source, *args, **kwargs): class SphinxBaseFileInput(FileInput): - """A base class of SphinxFileInput.""" + """A base class of SphinxFileInput. + + It supports to replace unknown Unicode characters to '?'. And it also emits + Sphinx events ``source-read`` on reading. + """ def __init__(self, app, env, *args, **kwds): # type: (Sphinx, BuildEnvironment, Any, Any) -> None @@ -144,6 +161,10 @@ class SphinxBaseFileInput(FileInput): def read(self): # type: () -> unicode + """Reads the contents from file. + + After reading, it emits Sphinx event ``source-read``. + """ data = FileInput.read(self) # emit source-read event @@ -168,10 +189,25 @@ class SphinxBaseFileInput(FileInput): class SphinxFileInput(SphinxBaseFileInput): + """A basic FileInput for Sphinx.""" pass class SphinxRSTFileInput(SphinxBaseFileInput): + """A reST FileInput for Sphinx. + + This FileInput automatically prepends and appends text by :confval:`rst_prolog` and + :confval:`rst_epilog`. + + .. important:: + + This FileInput uses an instance of ``StringList`` as a return value of ``read()`` + method to indicate original source filename and line numbers after prepending and + appending. + For that reason, ``sphinx.parsers.RSTParser`` should be used with this to parse + a content correctly. + """ + def prepend_prolog(self, text, prolog): # type: (StringList, unicode) -> None docinfo = self.count_docinfo_lines(text) diff --git a/sphinx/parsers.py b/sphinx/parsers.py index 5d19ae67c..92bea9461 100644 --- a/sphinx/parsers.py +++ b/sphinx/parsers.py @@ -59,7 +59,7 @@ class Parser(docutils.parsers.Parser): class RSTParser(docutils.parsers.rst.Parser): - """A reST parser customized for Sphinx.""" + """A reST parser for Sphinx.""" def get_transforms(self): # type: () -> List[Type[Transform]] @@ -73,8 +73,8 @@ class RSTParser(docutils.parsers.rst.Parser): # type: (Any, nodes.document) -> None """Parse text and generate a document tree. - This derived method accepts StringList as a inputstring parameter. - It enables to handle mixed contents (cf. rst_prolog) correctly. + This accepts StringList as an inputstring parameter. + It enables to handle mixed contents (cf. :confval:`rst_prolog`) correctly. """ if isinstance(inputstring, StringList): self.setup_parse(inputstring, document) From 49e1fbe0df95267f1b1e9e5f606fa8398cfba44b Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 14 Dec 2017 22:09:43 +0900 Subject: [PATCH 089/275] Update CHANGES for PR #4273 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index 0d7a47530..b7a16af4f 100644 --- a/CHANGES +++ b/CHANGES @@ -32,6 +32,7 @@ Bugs fixed * #1238: Support ``:emphasize-lines:`` in PDF output * #4279: Sphinx crashes with pickling error when run with multiple processes and remote image +* #1421: Respect the quiet flag in sphinx-quickstart Testing -------- From b6d6e4cc739a578a309f124791ed286058cdf0d6 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 14 Dec 2017 16:36:10 +0900 Subject: [PATCH 090/275] autodoc: Fix error handling for import_module() --- sphinx/ext/autodoc/__init__.py | 28 ++++++++++++++++++---------- sphinx/ext/autodoc/importer.py | 4 ++-- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index d183331ae..ff161565c 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -405,23 +405,31 @@ class Documenter(object): self.parent = parent self.object = obj return True - # this used to only catch SyntaxError, ImportError and AttributeError, - # but importing modules with side effects can raise all kinds of errors - except (Exception, SystemExit) as e: + except (AttributeError, ImportError) as exc: if self.objpath: errmsg = 'autodoc: failed to import %s %r from module %r' % \ (self.objtype, '.'.join(self.objpath), self.modname) else: errmsg = 'autodoc: failed to import %s %r' % \ (self.objtype, self.fullname) - if isinstance(e, SystemExit): - errmsg += ('; the module executes module level statement ' + - 'and it might call sys.exit().') - elif isinstance(e, ImportError): - errmsg += '; the following exception was raised:\n%s' % e.args[0] + + if isinstance(exc, ImportError): + # import_module() raises ImportError having real exception obj and + # traceback + real_exc, traceback_msg = exc.args + if isinstance(real_exc, SystemExit): + errmsg += ('; the module executes module level statement ' + + 'and it might call sys.exit().') + elif isinstance(real_exc, ImportError): + errmsg += ('; the following exception was raised:\n%s' % + real_exc.args[0]) + else: + errmsg += ('; the following exception was raised:\n%s' % + traceback_msg) else: - errmsg += '; the following exception was raised:\n%s' % \ - traceback.format_exc() + errmsg += ('; the following exception was raised:\n%s' % + traceback.format_exc()) + if PY2: errmsg = errmsg.decode('utf-8') # type: ignore logger.debug(errmsg) diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py index be03cba9b..5c28f490d 100644 --- a/sphinx/ext/autodoc/importer.py +++ b/sphinx/ext/autodoc/importer.py @@ -140,7 +140,7 @@ def import_module(modname, warningiserror=False): with logging.skip_warningiserror(not warningiserror): __import__(modname) return sys.modules[modname] - except BaseException: + except BaseException as exc: # Importing modules may cause any side effects, including # SystemExit, so we need to catch all errors. - raise ImportError(traceback.format_exc()) + raise ImportError(exc, traceback.format_exc()) From ed1f47e1908b322de1ac0348ad42c61366cd131d Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 1 May 2017 13:09:15 +0900 Subject: [PATCH 091/275] Move logs to registry --- sphinx/application.py | 15 --------------- sphinx/registry.py | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index 05d302c81..c184e43c4 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -444,7 +444,6 @@ class Sphinx(object): def add_builder(self, builder): # type: (Type[Builder]) -> None - logger.debug('[app] adding builder: %r', builder) self.registry.add_builder(builder) def add_config_value(self, name, default, rebuild, types=()): @@ -464,7 +463,6 @@ class Sphinx(object): def set_translator(self, name, translator_class): # type: (unicode, Type[nodes.NodeVisitor]) -> None - logger.info(bold(__('Change of translator for the %s builder.') % name)) self.registry.add_translator(name, translator_class) def add_node(self, node, **kwds): @@ -553,39 +551,30 @@ class Sphinx(object): def add_domain(self, domain): # type: (Type[Domain]) -> None - logger.debug('[app] adding domain: %r', domain) self.registry.add_domain(domain) def override_domain(self, domain): # type: (Type[Domain]) -> None - logger.debug('[app] overriding domain: %r', domain) self.registry.override_domain(domain) def add_directive_to_domain(self, domain, name, obj, has_content=None, argument_spec=None, **option_spec): # type: (unicode, unicode, Any, bool, Any, Any) -> None - logger.debug('[app] adding directive to domain: %r', - (domain, name, obj, has_content, argument_spec, option_spec)) self.registry.add_directive_to_domain(domain, name, obj, has_content, argument_spec, **option_spec) def add_role_to_domain(self, domain, name, role): # type: (unicode, unicode, Any) -> None - logger.debug('[app] adding role to domain: %r', (domain, name, role)) self.registry.add_role_to_domain(domain, name, role) def add_index_to_domain(self, domain, index): # type: (unicode, Type[Index]) -> None - logger.debug('[app] adding index to domain: %r', (domain, index)) self.registry.add_index_to_domain(domain, index) def add_object_type(self, directivename, rolename, indextemplate='', parse_node=None, ref_nodeclass=None, objname='', doc_field_types=[]): # type: (unicode, unicode, unicode, Callable, nodes.Node, unicode, List) -> None - logger.debug('[app] adding object type: %r', - (directivename, rolename, indextemplate, parse_node, - ref_nodeclass, objname, doc_field_types)) self.registry.add_object_type(directivename, rolename, indextemplate, parse_node, ref_nodeclass, objname, doc_field_types) @@ -602,9 +591,6 @@ class Sphinx(object): def add_crossref_type(self, directivename, rolename, indextemplate='', ref_nodeclass=None, objname=''): # type: (unicode, unicode, unicode, nodes.Node, unicode) -> None - logger.debug('[app] adding crossref type: %r', - (directivename, rolename, indextemplate, ref_nodeclass, - objname)) self.registry.add_crossref_type(directivename, rolename, indextemplate, ref_nodeclass, objname) @@ -677,7 +663,6 @@ class Sphinx(object): def add_source_parser(self, suffix, parser): # type: (unicode, Parser) -> None - logger.debug('[app] adding search source_parser: %r, %r', suffix, parser) self.registry.add_source_parser(suffix, parser) def add_env_collector(self, collector): diff --git a/sphinx/registry.py b/sphinx/registry.py index b627f23af..6da6dbeaf 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -24,6 +24,7 @@ from sphinx.parsers import Parser as SphinxParser from sphinx.roles import XRefRole from sphinx.util import logging from sphinx.util import import_object +from sphinx.util.console import bold # type: ignore from sphinx.util.docutils import directive_helper if False: @@ -56,6 +57,7 @@ class SphinxComponentRegistry(object): def add_builder(self, builder): # type: (Type[Builder]) -> None + logger.debug('[app] adding builder: %r', builder) if not hasattr(builder, 'name'): raise ExtensionError(__('Builder class %s has no "name" attribute') % builder) if builder.name in self.builders: @@ -87,6 +89,7 @@ class SphinxComponentRegistry(object): def add_domain(self, domain): # type: (Type[Domain]) -> None + logger.debug('[app] adding domain: %r', domain) if domain.name in self.domains: raise ExtensionError(__('domain %s already registered') % domain.name) self.domains[domain.name] = domain @@ -102,6 +105,7 @@ class SphinxComponentRegistry(object): def override_domain(self, domain): # type: (Type[Domain]) -> None + logger.debug('[app] overriding domain: %r', domain) if domain.name not in self.domains: raise ExtensionError(__('domain %s not yet registered') % domain.name) if not issubclass(domain, self.domains[domain.name]): @@ -112,6 +116,8 @@ class SphinxComponentRegistry(object): def add_directive_to_domain(self, domain, name, obj, has_content=None, argument_spec=None, **option_spec): # type: (unicode, unicode, Any, bool, Any, Any) -> None + logger.debug('[app] adding directive to domain: %r', + (domain, name, obj, has_content, argument_spec, option_spec)) if domain not in self.domains: raise ExtensionError(__('domain %s not yet registered') % domain) directive = directive_helper(obj, has_content, argument_spec, **option_spec) @@ -119,12 +125,14 @@ class SphinxComponentRegistry(object): def add_role_to_domain(self, domain, name, role): # type: (unicode, unicode, Any) -> None + logger.debug('[app] adding role to domain: %r', (domain, name, role)) if domain not in self.domains: raise ExtensionError(__('domain %s not yet registered') % domain) self.domains[domain].roles[name] = role def add_index_to_domain(self, domain, index): # type: (unicode, Type[Index]) -> None + logger.debug('[app] adding index to domain: %r', (domain, index)) if domain not in self.domains: raise ExtensionError(__('domain %s not yet registered') % domain) self.domains[domain].indices.append(index) @@ -133,6 +141,10 @@ class SphinxComponentRegistry(object): parse_node=None, ref_nodeclass=None, objname='', doc_field_types=[]): # type: (unicode, unicode, unicode, Callable, nodes.Node, unicode, List) -> None + logger.debug('[app] adding object type: %r', + (directivename, rolename, indextemplate, parse_node, + ref_nodeclass, objname, doc_field_types)) + # create a subclass of GenericObject as the new directive directive = type(directivename, # type: ignore (GenericObject, object), @@ -148,6 +160,9 @@ class SphinxComponentRegistry(object): def add_crossref_type(self, directivename, rolename, indextemplate='', ref_nodeclass=None, objname=''): # type: (unicode, unicode, unicode, nodes.Node, unicode) -> None + logger.debug('[app] adding crossref type: %r', + (directivename, rolename, indextemplate, ref_nodeclass, objname)) + # create a subclass of Target as the new directive directive = type(directivename, # type: ignore (Target, object), @@ -160,6 +175,7 @@ class SphinxComponentRegistry(object): def add_source_parser(self, suffix, parser): # type: (unicode, Type[Parser]) -> None + logger.debug('[app] adding search source_parser: %r, %r', suffix, parser) if suffix in self.source_parsers: raise ExtensionError(__('source_parser for %r is already registered') % suffix) self.source_parsers[suffix] = parser @@ -216,6 +232,7 @@ class SphinxComponentRegistry(object): def add_translator(self, name, translator): # type: (unicode, Type[nodes.NodeVisitor]) -> None + logger.info(bold(__('Change of translator for the %s builder.') % name)) self.translators[name] = translator def get_translator_class(self, builder): From 27ea988f6e5a6637441f418a8f0c5dff5d5397bf Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 1 May 2017 14:09:32 +0900 Subject: [PATCH 092/275] Move Transform manager to registry --- sphinx/application.py | 3 +-- sphinx/io.py | 10 ++++++++-- sphinx/registry.py | 11 +++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index c184e43c4..fc669d798 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -596,8 +596,7 @@ class Sphinx(object): def add_transform(self, transform): # type: (Type[Transform]) -> None - logger.debug('[app] adding transform: %r', transform) - SphinxStandaloneReader.transforms.append(transform) + self.registry.add_transform(transform) def add_post_transform(self, transform): # type: (Type[Transform]) -> None diff --git a/sphinx/io.py b/sphinx/io.py index 8a41069db..4bb554742 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -80,7 +80,13 @@ class SphinxStandaloneReader(SphinxBaseReader): Locale, CitationReferences, DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, AutoNumbering, AutoIndexUpgrader, SortIds, RemoveTranslatableInline, PreserveTranslatableMessages, FilterSystemMessages, - RefOnlyBulletListTransform, UnreferencedFootnotesDetector] + RefOnlyBulletListTransform, UnreferencedFootnotesDetector + ] # type: List[Transform] + + def __init__(self, app, *args, **kwargs): + # type: (Sphinx, Any, Any) -> None + self.transforms = self.transforms + app.registry.get_transforms() + SphinxBaseReader.__init__(self, *args, **kwargs) class SphinxI18nReader(SphinxBaseReader): @@ -259,7 +265,7 @@ def read_doc(app, env, filename): # type: (Sphinx, BuildEnvironment, unicode) -> nodes.document """Parse a document and convert to doctree.""" input_class = app.registry.get_source_input(filename) - reader = SphinxStandaloneReader() + reader = SphinxStandaloneReader(app) source = input_class(app, env, source=None, source_path=filename, encoding=env.config.source_encoding) parser = app.registry.create_source_parser(app, filename) diff --git a/sphinx/registry.py b/sphinx/registry.py index 6da6dbeaf..95320db36 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -33,6 +33,7 @@ if False: from docutils import nodes # NOQA from docutils.io import Input # NOQA from docutils.parsers import Parser # NOQA + from docutils.transform import Transform # NOQA from sphinx.application import Sphinx # NOQA from sphinx.builders import Builder # NOQA from sphinx.domains import Domain, Index # NOQA @@ -54,6 +55,7 @@ class SphinxComponentRegistry(object): self.source_parsers = {} # type: Dict[unicode, Parser] self.source_inputs = {} # type: Dict[unicode, Input] self.translators = {} # type: Dict[unicode, nodes.NodeVisitor] + self.transforms = [] # type: List[Type[Transform]] def add_builder(self, builder): # type: (Type[Builder]) -> None @@ -245,6 +247,15 @@ class SphinxComponentRegistry(object): translator_class = self.get_translator_class(builder) return translator_class(builder, document) + def add_transform(self, transform): + # type: (Type[Transform]) -> None + logger.debug('[app] adding transform: %r', transform) + self.transforms.append(transform) + + def get_transforms(self): + # type: () -> List[Type[Transform]] + return self.transforms + def load_extension(self, app, extname): # type: (Sphinx, unicode) -> None """Load a Sphinx extension.""" From 2a26656ce6e508e080aaa18922f2a75541f1c96c Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 1 May 2017 14:40:02 +0900 Subject: [PATCH 093/275] Move post-transform manager to registry --- sphinx/application.py | 4 +--- sphinx/environment/__init__.py | 2 +- sphinx/registry.py | 10 ++++++++++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index fc669d798..ef20e56d8 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -120,7 +120,6 @@ class Sphinx(object): self.env = None # type: BuildEnvironment self.registry = SphinxComponentRegistry() self.enumerable_nodes = {} # type: Dict[nodes.Node, Tuple[unicode, Callable]] # NOQA - self.post_transforms = [] # type: List[Transform] self.html_themes = {} # type: Dict[unicode, unicode] self.srcdir = srcdir @@ -600,8 +599,7 @@ class Sphinx(object): def add_post_transform(self, transform): # type: (Type[Transform]) -> None - logger.debug('[app] adding post transform: %r', transform) - self.post_transforms.append(transform) + self.registry.add_post_transform(transform) def add_javascript(self, filename): # type: (unicode) -> None diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index 5ebf9d4d5..b4c40b608 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -878,7 +878,7 @@ class BuildEnvironment(object): transformer = SphinxTransformer(doctree) transformer.set_environment(self) - transformer.add_transforms(self.app.post_transforms) + transformer.add_transforms(self.app.registry.get_post_transforms()) transformer.apply_transforms() finally: self.temp_data = backup diff --git a/sphinx/registry.py b/sphinx/registry.py index 95320db36..6f9bbe4d9 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -52,6 +52,7 @@ class SphinxComponentRegistry(object): def __init__(self): self.builders = {} # type: Dict[unicode, Type[Builder]] self.domains = {} # type: Dict[unicode, Type[Domain]] + self.post_transforms = [] # type: List[Type[Transform]] self.source_parsers = {} # type: Dict[unicode, Parser] self.source_inputs = {} # type: Dict[unicode, Input] self.translators = {} # type: Dict[unicode, nodes.NodeVisitor] @@ -256,6 +257,15 @@ class SphinxComponentRegistry(object): # type: () -> List[Type[Transform]] return self.transforms + def add_post_transform(self, transform): + # type: (Type[Transform]) -> None + logger.debug('[app] adding post transform: %r', transform) + self.post_transforms.append(transform) + + def get_post_transforms(self): + # type: () -> List[Type[Transform]] + return self.post_transforms + def load_extension(self, app, extname): # type: (Sphinx, unicode) -> None """Load a Sphinx extension.""" From c09f3e77677625374b7c81131c883ca6a5b7b645 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 1 May 2017 19:41:27 +0900 Subject: [PATCH 094/275] Transplant directives on instantiate domain --- sphinx/domains/__init__.py | 12 ++++++++---- sphinx/registry.py | 26 ++++++++++++++++---------- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index 6edc3cdb0..6af0870de 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -161,6 +161,14 @@ class Domain(object): def __init__(self, env): # type: (BuildEnvironment) -> None self.env = env # type: BuildEnvironment + self._role_cache = {} # type: Dict[unicode, Callable] + self._directive_cache = {} # type: Dict[unicode, Callable] + self._role2type = {} # type: Dict[unicode, List[unicode]] + self._type2role = {} # type: Dict[unicode, unicode] + + # convert class variables to instance one (to enhance through API) + self.directives = dict(self.directives) + if self.name not in env.domaindata: assert isinstance(self.initial_data, dict) new_data = copy.deepcopy(self.initial_data) @@ -170,10 +178,6 @@ class Domain(object): self.data = env.domaindata[self.name] if self.data['version'] != self.data_version: raise IOError('data of %r domain out of date' % self.label) - self._role_cache = {} # type: Dict[unicode, Callable] - self._directive_cache = {} # type: Dict[unicode, Callable] - self._role2type = {} # type: Dict[unicode, List[unicode]] - self._type2role = {} # type: Dict[unicode, unicode] for name, obj in iteritems(self.object_types): for rolename in obj.roles: self._role2type.setdefault(rolename, []).append(name) diff --git a/sphinx/registry.py b/sphinx/registry.py index 6f9bbe4d9..0bbd59756 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -50,13 +50,14 @@ EXTENSION_BLACKLIST = { class SphinxComponentRegistry(object): def __init__(self): - self.builders = {} # type: Dict[unicode, Type[Builder]] - self.domains = {} # type: Dict[unicode, Type[Domain]] - self.post_transforms = [] # type: List[Type[Transform]] - self.source_parsers = {} # type: Dict[unicode, Parser] - self.source_inputs = {} # type: Dict[unicode, Input] - self.translators = {} # type: Dict[unicode, nodes.NodeVisitor] - self.transforms = [] # type: List[Type[Transform]] + self.builders = {} # type: Dict[unicode, Type[Builder]] + self.domains = {} # type: Dict[unicode, Type[Domain]] + self.domain_directives = {} # type: Dict[unicode, Dict[unicode, Any]] + self.post_transforms = [] # type: List[Type[Transform]] + self.source_parsers = {} # type: Dict[unicode, Parser] + self.source_inputs = {} # type: Dict[unicode, Input] + self.translators = {} # type: Dict[unicode, nodes.NodeVisitor] + self.transforms = [] # type: List[Type[Transform]] def add_builder(self, builder): # type: (Type[Builder]) -> None @@ -104,7 +105,12 @@ class SphinxComponentRegistry(object): def create_domains(self, env): # type: (BuildEnvironment) -> Iterator[Domain] for DomainClass in itervalues(self.domains): - yield DomainClass(env) + domain = DomainClass(env) + + # transplant components added by extensions + domain.directives.update(self.domain_directives.get(domain.name, {})) + + yield domain def override_domain(self, domain): # type: (Type[Domain]) -> None @@ -123,8 +129,8 @@ class SphinxComponentRegistry(object): (domain, name, obj, has_content, argument_spec, option_spec)) if domain not in self.domains: raise ExtensionError(__('domain %s not yet registered') % domain) - directive = directive_helper(obj, has_content, argument_spec, **option_spec) - self.domains[domain].directives[name] = directive + directives = self.domain_directives.setdefault(domain, {}) + directives[name] = directive_helper(obj, has_content, argument_spec, **option_spec) def add_role_to_domain(self, domain, name, role): # type: (unicode, unicode, Any) -> None From a2880dffe66aa25d7212002ac395cf9687f65138 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 2 May 2017 12:31:36 +0900 Subject: [PATCH 095/275] Transplant roles on instantiate domain --- sphinx/domains/__init__.py | 1 + sphinx/registry.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index 6af0870de..dbd8c6c33 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -168,6 +168,7 @@ class Domain(object): # convert class variables to instance one (to enhance through API) self.directives = dict(self.directives) + self.roles = dict(self.roles) if self.name not in env.domaindata: assert isinstance(self.initial_data, dict) diff --git a/sphinx/registry.py b/sphinx/registry.py index 0bbd59756..fba90934a 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -53,6 +53,7 @@ class SphinxComponentRegistry(object): self.builders = {} # type: Dict[unicode, Type[Builder]] self.domains = {} # type: Dict[unicode, Type[Domain]] self.domain_directives = {} # type: Dict[unicode, Dict[unicode, Any]] + self.domain_roles = {} # type: Dict[unicode, Dict[unicode, Any]] self.post_transforms = [] # type: List[Type[Transform]] self.source_parsers = {} # type: Dict[unicode, Parser] self.source_inputs = {} # type: Dict[unicode, Input] @@ -109,6 +110,7 @@ class SphinxComponentRegistry(object): # transplant components added by extensions domain.directives.update(self.domain_directives.get(domain.name, {})) + domain.roles.update(self.domain_roles.get(domain.name, {})) yield domain @@ -137,7 +139,8 @@ class SphinxComponentRegistry(object): logger.debug('[app] adding role to domain: %r', (domain, name, role)) if domain not in self.domains: raise ExtensionError(__('domain %s not yet registered') % domain) - self.domains[domain].roles[name] = role + roles = self.domain_roles.setdefault(domain, {}) + roles[name] = role def add_index_to_domain(self, domain, index): # type: (unicode, Type[Index]) -> None From a7d4fd1a503cd7b1bbe3d3c7bf6d41ab86cc936d Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 2 May 2017 12:38:55 +0900 Subject: [PATCH 096/275] Transplant indices on instantiate domain --- sphinx/domains/__init__.py | 1 + sphinx/registry.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index dbd8c6c33..510d997ae 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -169,6 +169,7 @@ class Domain(object): # convert class variables to instance one (to enhance through API) self.directives = dict(self.directives) self.roles = dict(self.roles) + self.indices = list(self.indices) if self.name not in env.domaindata: assert isinstance(self.initial_data, dict) diff --git a/sphinx/registry.py b/sphinx/registry.py index fba90934a..cba2aaeca 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -53,6 +53,7 @@ class SphinxComponentRegistry(object): self.builders = {} # type: Dict[unicode, Type[Builder]] self.domains = {} # type: Dict[unicode, Type[Domain]] self.domain_directives = {} # type: Dict[unicode, Dict[unicode, Any]] + self.domain_indices = {} # type: Dict[unicode, List[Index]] self.domain_roles = {} # type: Dict[unicode, Dict[unicode, Any]] self.post_transforms = [] # type: List[Type[Transform]] self.source_parsers = {} # type: Dict[unicode, Parser] @@ -111,6 +112,7 @@ class SphinxComponentRegistry(object): # transplant components added by extensions domain.directives.update(self.domain_directives.get(domain.name, {})) domain.roles.update(self.domain_roles.get(domain.name, {})) + domain.indices.extend(self.domain_indices.get(domain.name, [])) yield domain @@ -147,7 +149,8 @@ class SphinxComponentRegistry(object): logger.debug('[app] adding index to domain: %r', (domain, index)) if domain not in self.domains: raise ExtensionError(__('domain %s not yet registered') % domain) - self.domains[domain].indices.append(index) + indices = self.domain_indices.setdefault(domain, []) + indices.append(index) def add_object_type(self, directivename, rolename, indextemplate='', parse_node=None, ref_nodeclass=None, objname='', From b2837eee0ccd6020c3c1d6470381f6a07185ca0e Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 2 May 2017 12:45:16 +0900 Subject: [PATCH 097/275] Transplant object_types on instantiate domain --- sphinx/domains/__init__.py | 1 + sphinx/registry.py | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index 510d997ae..ddb6c7c66 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -167,6 +167,7 @@ class Domain(object): self._type2role = {} # type: Dict[unicode, unicode] # convert class variables to instance one (to enhance through API) + self.object_types = dict(self.object_types) self.directives = dict(self.directives) self.roles = dict(self.roles) self.indices = list(self.indices) diff --git a/sphinx/registry.py b/sphinx/registry.py index cba2aaeca..265524b28 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -54,6 +54,7 @@ class SphinxComponentRegistry(object): self.domains = {} # type: Dict[unicode, Type[Domain]] self.domain_directives = {} # type: Dict[unicode, Dict[unicode, Any]] self.domain_indices = {} # type: Dict[unicode, List[Index]] + self.domain_object_types = {} # type: Dict[unicode, Dict[unicode, ObjType]] self.domain_roles = {} # type: Dict[unicode, Dict[unicode, Any]] self.post_transforms = [] # type: List[Type[Transform]] self.source_parsers = {} # type: Dict[unicode, Parser] @@ -110,6 +111,7 @@ class SphinxComponentRegistry(object): domain = DomainClass(env) # transplant components added by extensions + domain.object_types.update(self.domain_object_types.get(domain.name, {})) domain.directives.update(self.domain_directives.get(domain.name, {})) domain.roles.update(self.domain_roles.get(domain.name, {})) domain.indices.extend(self.domain_indices.get(domain.name, [])) @@ -167,10 +169,11 @@ class SphinxComponentRegistry(object): 'parse_node': staticmethod(parse_node), 'doc_field_types': doc_field_types}) - stddomain = self.domains['std'] - stddomain.directives[directivename] = directive - stddomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass) - stddomain.object_types[directivename] = ObjType(objname or directivename, rolename) + self.add_directive_to_domain('std', directivename, directive) + self.add_role_to_domain('std', rolename, XRefRole(innernodeclass=ref_nodeclass)) + + object_types = self.domain_object_types.setdefault('std', {}) + object_types[directivename] = ObjType(objname or directivename, rolename) def add_crossref_type(self, directivename, rolename, indextemplate='', ref_nodeclass=None, objname=''): @@ -183,10 +186,11 @@ class SphinxComponentRegistry(object): (Target, object), {'indextemplate': indextemplate}) - stddomain = self.domains['std'] - stddomain.directives[directivename] = directive - stddomain.roles[rolename] = XRefRole(innernodeclass=ref_nodeclass) - stddomain.object_types[directivename] = ObjType(objname or directivename, rolename) + self.add_directive_to_domain('std', directive) + self.add_role_to_domain('std', XRefRole(innernodeclass=ref_nodeclass)) + + object_types = self.domain_object_types.setdefault('std', {}) + object_types[directivename] = ObjType(objname or directivename, rolename) def add_source_parser(self, suffix, parser): # type: (unicode, Type[Parser]) -> None From 60f3968ef787257283a6af8023ae9890f3ae8384 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 13 Dec 2017 23:48:07 +0900 Subject: [PATCH 098/275] diet test-root: Move ziptheme to test-theming --- .../roots/{test-root => test-theming}/ziptheme.zip | Bin tests/test_theming.py | 7 ++++--- 2 files changed, 4 insertions(+), 3 deletions(-) rename tests/roots/{test-root => test-theming}/ziptheme.zip (100%) diff --git a/tests/roots/test-root/ziptheme.zip b/tests/roots/test-theming/ziptheme.zip similarity index 100% rename from tests/roots/test-root/ziptheme.zip rename to tests/roots/test-theming/ziptheme.zip diff --git a/tests/test_theming.py b/tests/test_theming.py index ef9656bc5..f8cfd395e 100644 --- a/tests/test_theming.py +++ b/tests/test_theming.py @@ -17,6 +17,7 @@ from sphinx.theming import ThemeError @pytest.mark.sphinx( + testroot='theming', confoverrides={'html_theme': 'ziptheme', 'html_theme_options.testopt': 'foo'}) def test_theme_api(app, status, warning): @@ -25,9 +26,9 @@ def test_theme_api(app, status, warning): # test Theme class API assert set(app.html_themes.keys()) == \ set(['basic', 'default', 'scrolls', 'agogo', 'sphinxdoc', 'haiku', - 'traditional', 'testtheme', 'ziptheme', 'epub', 'nature', - 'pyramid', 'bizstyle', 'classic', 'nonav']) - assert app.html_themes['testtheme'] == app.srcdir / 'testtheme' + 'traditional', 'test-theme', 'ziptheme', 'epub', 'nature', + 'pyramid', 'bizstyle', 'classic', 'nonav', 'parent', 'child']) + assert app.html_themes['test-theme'] == app.srcdir / 'test_theme/test-theme' assert app.html_themes['ziptheme'] == app.srcdir / 'ziptheme.zip' # test Theme instance API From a8ab1f164b069528344a880e75550f57ec05a6b5 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 13 Dec 2017 23:48:07 +0900 Subject: [PATCH 099/275] diet test-root: Move testtheme to test-theming --- tests/roots/test-root/conf.py | 3 --- .../test_theme/staticfiles}/layout.html | 0 .../staticfiles}/static/staticimg.png | Bin .../staticfiles}/static/statictmpl.html_t | 0 .../test_theme/staticfiles}/theme.conf | 0 tests/test_build_html.py | 4 ---- tests/test_build_html5.py | 4 ---- tests/test_theming.py | 22 +++++++++++++++--- 8 files changed, 19 insertions(+), 14 deletions(-) rename tests/roots/{test-root/testtheme => test-theming/test_theme/staticfiles}/layout.html (100%) rename tests/roots/{test-root/testtheme => test-theming/test_theme/staticfiles}/static/staticimg.png (100%) rename tests/roots/{test-root/testtheme => test-theming/test_theme/staticfiles}/static/statictmpl.html_t (100%) rename tests/roots/{test-root/testtheme => test-theming/test_theme/staticfiles}/theme.conf (100%) diff --git a/tests/roots/test-root/conf.py b/tests/roots/test-root/conf.py index a23aec482..c25beb9f1 100644 --- a/tests/roots/test-root/conf.py +++ b/tests/roots/test-root/conf.py @@ -29,9 +29,6 @@ numfig = True rst_epilog = '.. |subst| replace:: global substitution' -html_theme = 'testtheme' -html_theme_path = ['.'] -html_theme_options = {'testopt': 'testoverride'} html_sidebars = {'**': 'customsb.html', 'contents': ['contentssb.html', 'localtoc.html', 'globaltoc.html']} diff --git a/tests/roots/test-root/testtheme/layout.html b/tests/roots/test-theming/test_theme/staticfiles/layout.html similarity index 100% rename from tests/roots/test-root/testtheme/layout.html rename to tests/roots/test-theming/test_theme/staticfiles/layout.html diff --git a/tests/roots/test-root/testtheme/static/staticimg.png b/tests/roots/test-theming/test_theme/staticfiles/static/staticimg.png similarity index 100% rename from tests/roots/test-root/testtheme/static/staticimg.png rename to tests/roots/test-theming/test_theme/staticfiles/static/staticimg.png diff --git a/tests/roots/test-root/testtheme/static/statictmpl.html_t b/tests/roots/test-theming/test_theme/staticfiles/static/statictmpl.html_t similarity index 100% rename from tests/roots/test-root/testtheme/static/statictmpl.html_t rename to tests/roots/test-theming/test_theme/staticfiles/static/statictmpl.html_t diff --git a/tests/roots/test-root/testtheme/theme.conf b/tests/roots/test-theming/test_theme/staticfiles/theme.conf similarity index 100% rename from tests/roots/test-root/testtheme/theme.conf rename to tests/roots/test-theming/test_theme/staticfiles/theme.conf diff --git a/tests/test_build_html.py b/tests/test_build_html.py index ceeb5f01c..6fa769b8b 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -377,7 +377,6 @@ def test_static_output(app): 'contents.html': [ (".//meta[@name='hc'][@content='hcval']", ''), (".//meta[@name='hc_co'][@content='hcval_co']", ''), - (".//meta[@name='testopt'][@content='testoverride']", ''), (".//td[@class='label']", r'\[Ref1\]'), (".//td[@class='label']", ''), (".//li[@class='toctree-l1']/a", 'Testing various markup'), @@ -410,9 +409,6 @@ def test_static_output(app): (".//a[@href='http://bugs.python.org/issue1000']", "issue 1000"), (".//a[@href='http://bugs.python.org/issue1042']", "explicit caption"), ], - '_static/statictmpl.html': [ - (".//project", 'Sphinx '), - ], 'genindex.html': [ # index entries (".//a/strong", "Main"), diff --git a/tests/test_build_html5.py b/tests/test_build_html5.py index 7fc91b9ec..4ad282973 100644 --- a/tests/test_build_html5.py +++ b/tests/test_build_html5.py @@ -252,7 +252,6 @@ def cached_etree_parse(): 'contents.html': [ (".//meta[@name='hc'][@content='hcval']", ''), (".//meta[@name='hc_co'][@content='hcval_co']", ''), - (".//meta[@name='testopt'][@content='testoverride']", ''), (".//dt[@class='label']/span[@class='brackets']", r'Ref1'), (".//dt[@class='label']", ''), (".//li[@class='toctree-l1']/a", 'Testing various markup'), @@ -285,9 +284,6 @@ def cached_etree_parse(): (".//a[@href='http://bugs.python.org/issue1000']", "issue 1000"), (".//a[@href='http://bugs.python.org/issue1042']", "explicit caption"), ], - '_static/statictmpl.html': [ - (".//project", 'Sphinx '), - ], 'genindex.html': [ # index entries (".//a/strong", "Main"), diff --git a/tests/test_theming.py b/tests/test_theming.py index f8cfd395e..176c9eebc 100644 --- a/tests/test_theming.py +++ b/tests/test_theming.py @@ -26,10 +26,11 @@ def test_theme_api(app, status, warning): # test Theme class API assert set(app.html_themes.keys()) == \ set(['basic', 'default', 'scrolls', 'agogo', 'sphinxdoc', 'haiku', - 'traditional', 'test-theme', 'ziptheme', 'epub', 'nature', - 'pyramid', 'bizstyle', 'classic', 'nonav', 'parent', 'child']) - assert app.html_themes['test-theme'] == app.srcdir / 'test_theme/test-theme' + 'traditional', 'epub', 'nature', 'pyramid', 'bizstyle', 'classic', 'nonav', + 'test-theme', 'ziptheme', 'staticfiles', 'parent', 'child']) + assert app.html_themes['test-theme'] == app.srcdir / 'test_theme' / 'test-theme' assert app.html_themes['ziptheme'] == app.srcdir / 'ziptheme.zip' + assert app.html_themes['staticfiles'] == app.srcdir / 'test_theme' / 'staticfiles' # test Theme instance API theme = app.builder.theme @@ -94,3 +95,18 @@ def test_double_inheriting_theme(app, status, warning): def test_nested_zipped_theme(app, status, warning): assert app.builder.theme.name == 'child' app.build() # => not raises TemplateNotFound + + +@pytest.mark.sphinx(testroot='theming', + confoverrides={'html_theme': 'staticfiles'}) +def test_staticfiles(app, status, warning): + app.build() + assert (app.outdir / '_static' / 'staticimg.png').exists() + assert (app.outdir / '_static' / 'statictmpl.html').exists() + assert (app.outdir / '_static' / 'statictmpl.html').text() == ( + '\n' + 'Python' + ) + + result = (app.outdir / 'index.html').text() + assert '' in result From a5b64c98af1f898f95484010e0eb67f3ef4d6c3d Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 13 Dec 2017 23:46:57 +0900 Subject: [PATCH 100/275] diet test-root: Remove html_static_path and html_extra_path (duplicated with test-html_assets) --- tests/roots/test-root/_static/README | 1 - tests/roots/test-root/_static/excluded.css | 1 - tests/roots/test-root/_static/subdir/foo.css | 1 - tests/roots/test-root/conf.py | 2 -- tests/roots/test-root/robots.txt | 2 -- tests/roots/test-root/templated.css_t | 2 -- tests/test_build_html.py | 27 -------------------- 7 files changed, 36 deletions(-) delete mode 100644 tests/roots/test-root/_static/README delete mode 100644 tests/roots/test-root/_static/excluded.css delete mode 100644 tests/roots/test-root/_static/subdir/foo.css delete mode 100644 tests/roots/test-root/robots.txt delete mode 100644 tests/roots/test-root/templated.css_t diff --git a/tests/roots/test-root/_static/README b/tests/roots/test-root/_static/README deleted file mode 100644 index 9e1ec3569..000000000 --- a/tests/roots/test-root/_static/README +++ /dev/null @@ -1 +0,0 @@ -This whole directory is there to test html_static_path. diff --git a/tests/roots/test-root/_static/excluded.css b/tests/roots/test-root/_static/excluded.css deleted file mode 100644 index 03c941a44..000000000 --- a/tests/roots/test-root/_static/excluded.css +++ /dev/null @@ -1 +0,0 @@ -/* This file should be excluded from being copied over */ diff --git a/tests/roots/test-root/_static/subdir/foo.css b/tests/roots/test-root/_static/subdir/foo.css deleted file mode 100644 index 9427981d6..000000000 --- a/tests/roots/test-root/_static/subdir/foo.css +++ /dev/null @@ -1 +0,0 @@ -/* Stub file */ diff --git a/tests/roots/test-root/conf.py b/tests/roots/test-root/conf.py index c25beb9f1..bd3cb9a9b 100644 --- a/tests/roots/test-root/conf.py +++ b/tests/roots/test-root/conf.py @@ -33,8 +33,6 @@ html_sidebars = {'**': 'customsb.html', 'contents': ['contentssb.html', 'localtoc.html', 'globaltoc.html']} html_style = 'default.css' -html_static_path = ['_static', 'templated.css_t'] -html_extra_path = ['robots.txt'] html_last_updated_fmt = '%b %d, %Y' html_context = {'hckey': 'hcval', 'hckey_co': 'wrong_hcval_co'} diff --git a/tests/roots/test-root/robots.txt b/tests/roots/test-root/robots.txt deleted file mode 100644 index 1b425ee0f..000000000 --- a/tests/roots/test-root/robots.txt +++ /dev/null @@ -1,2 +0,0 @@ -User-agent: * -Disallow: /cgi-bin/ diff --git a/tests/roots/test-root/templated.css_t b/tests/roots/test-root/templated.css_t deleted file mode 100644 index 72ddb807c..000000000 --- a/tests/roots/test-root/templated.css_t +++ /dev/null @@ -1,2 +0,0 @@ -/* Stub file, templated */ -{{ sphinx_version }} diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 6fa769b8b..c27dad42b 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -126,24 +126,6 @@ def check_xpath(etree, fname, path, check, be_found=True): [node.text for node in nodes])) -def check_static_entries(outdir): - staticdir = outdir / '_static' - assert staticdir.isdir() - # a file from a directory entry in html_static_path - assert (staticdir / 'README').isfile() - # a directory from a directory entry in html_static_path - assert (staticdir / 'subdir' / 'foo.css').isfile() - # a file from a file entry in html_static_path - assert (staticdir / 'templated.css').isfile() - assert (staticdir / 'templated.css').text().splitlines()[1] == __display_version__ - # a file from _static, but matches exclude_patterns - assert not (staticdir / 'excluded.css').exists() - - -def check_extra_entries(outdir): - assert (outdir / 'robots.txt').isfile() - - @pytest.mark.sphinx('html', testroot='warnings') def test_html_warnings(app, warning): app.build() @@ -156,15 +138,6 @@ def test_html_warnings(app, warning): '--- Got:\n' + html_warnings -@pytest.mark.sphinx('html', tags=['testtag'], confoverrides={ - 'html_context.hckey_co': 'hcval_co'}) -@pytest.mark.test_params(shared_result='test_build_html_output') -def test_static_output(app): - app.build() - check_static_entries(app.builder.outdir) - check_extra_entries(app.builder.outdir) - - @pytest.mark.parametrize("fname,expect", flat_dict({ 'images.html': [ (".//img[@src='_images/img.png']", ''), From a3f04c3397726ee688a5ebdebbbd23510f973d7f Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Fri, 15 Dec 2017 02:30:09 +0900 Subject: [PATCH 101/275] Refactor test_build_html: Use basic project instead roots --- tests/test_build_html.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tests/test_build_html.py b/tests/test_build_html.py index c27dad42b..083add9a1 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -1114,16 +1114,22 @@ def test_html_assets(app): assert not (app.outdir / 'subdir' / '.htpasswd').exists() -@pytest.mark.sphinx('html', confoverrides={'html_sourcelink_suffix': ''}) +@pytest.mark.sphinx('html', testroot='basic', confoverrides={'html_sourcelink_suffix': '.txt'}) def test_html_sourcelink_suffix(app): app.builder.build_all() - content_otherext = (app.outdir / 'otherext.html').text() - content_images = (app.outdir / 'images.html').text() + assert (app.outdir / '_sources' / 'index.rst.txt').exists() - assert ' Date: Fri, 15 Dec 2017 02:30:25 +0900 Subject: [PATCH 102/275] test: Add test_html_copy_source --- tests/test_build_html.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 083add9a1..0ccd4da01 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -1114,6 +1114,12 @@ def test_html_assets(app): assert not (app.outdir / 'subdir' / '.htpasswd').exists() +@pytest.mark.sphinx('html', testroot='basic', confoverrides={'html_copy_source': False}) +def test_html_copy_source(app): + app.builder.build_all() + assert not (app.outdir / '_sources' / 'index.rst.txt').exists() + + @pytest.mark.sphinx('html', testroot='basic', confoverrides={'html_sourcelink_suffix': '.txt'}) def test_html_sourcelink_suffix(app): app.builder.build_all() From 451ba5e76a2417c70ae4e2213b78c109d17bca05 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Fri, 15 Dec 2017 21:11:38 +0900 Subject: [PATCH 103/275] Fix ResourceWarning on pycode --- sphinx/pycode/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sphinx/pycode/__init__.py b/sphinx/pycode/__init__.py index 66544f073..20de2a656 100644 --- a/sphinx/pycode/__init__.py +++ b/sphinx/pycode/__init__.py @@ -36,11 +36,11 @@ class ModuleAnalyzer(object): if ('file', filename) in cls.cache: return cls.cache['file', filename] try: - fileobj = open(filename, 'rb') + with open(filename, 'rb') as f: + obj = cls(f, modname, filename) + cls.cache['file', filename] = obj except Exception as err: raise PycodeError('error opening %r' % filename, err) - obj = cls(fileobj, modname, filename) - cls.cache['file', filename] = obj return obj @classmethod From 2a2ed8915a2eaea45f2f65ca08dd563708b5c0a4 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Fri, 15 Dec 2017 21:14:19 +0900 Subject: [PATCH 104/275] diet test-root: Move .mo files to new testroot (for test_html_rebuild_mo) --- .../bom.po | 0 tests/roots/test-builder-gettext-dont-rebuild-mo/bom.rst | 5 +++++ tests/roots/test-builder-gettext-dont-rebuild-mo/conf.py | 7 +++++++ .../roots/test-builder-gettext-dont-rebuild-mo/index.rst | 6 ++++++ tests/roots/test-root/subdir.po | 9 --------- tests/test_intl.py | 4 ++-- 6 files changed, 20 insertions(+), 11 deletions(-) rename tests/roots/{test-root => test-builder-gettext-dont-rebuild-mo}/bom.po (100%) create mode 100644 tests/roots/test-builder-gettext-dont-rebuild-mo/bom.rst create mode 100644 tests/roots/test-builder-gettext-dont-rebuild-mo/conf.py create mode 100644 tests/roots/test-builder-gettext-dont-rebuild-mo/index.rst delete mode 100644 tests/roots/test-root/subdir.po diff --git a/tests/roots/test-root/bom.po b/tests/roots/test-builder-gettext-dont-rebuild-mo/bom.po similarity index 100% rename from tests/roots/test-root/bom.po rename to tests/roots/test-builder-gettext-dont-rebuild-mo/bom.po diff --git a/tests/roots/test-builder-gettext-dont-rebuild-mo/bom.rst b/tests/roots/test-builder-gettext-dont-rebuild-mo/bom.rst new file mode 100644 index 000000000..3fea824f8 --- /dev/null +++ b/tests/roots/test-builder-gettext-dont-rebuild-mo/bom.rst @@ -0,0 +1,5 @@ +File with UTF-8 BOM +=================== + +This file has a UTF-8 "BOM". + diff --git a/tests/roots/test-builder-gettext-dont-rebuild-mo/conf.py b/tests/roots/test-builder-gettext-dont-rebuild-mo/conf.py new file mode 100644 index 000000000..31e7a6ed4 --- /dev/null +++ b/tests/roots/test-builder-gettext-dont-rebuild-mo/conf.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- + +master_doc = 'index' + +latex_documents = [ + (master_doc, 'test.tex', 'The basic Sphinx documentation for testing', 'Sphinx', 'report') +] diff --git a/tests/roots/test-builder-gettext-dont-rebuild-mo/index.rst b/tests/roots/test-builder-gettext-dont-rebuild-mo/index.rst new file mode 100644 index 000000000..7ff38c5a8 --- /dev/null +++ b/tests/roots/test-builder-gettext-dont-rebuild-mo/index.rst @@ -0,0 +1,6 @@ +The basic Sphinx documentation for testing +========================================== + +.. toctree:: + + bom diff --git a/tests/roots/test-root/subdir.po b/tests/roots/test-root/subdir.po deleted file mode 100644 index f515f2207..000000000 --- a/tests/roots/test-root/subdir.po +++ /dev/null @@ -1,9 +0,0 @@ -#, fuzzy -msgid "" -msgstr "" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -msgid "Including in subdir" -msgstr "translation" diff --git a/tests/test_intl.py b/tests/test_intl.py index 8eff52340..6b72438bd 100644 --- a/tests/test_intl.py +++ b/tests/test_intl.py @@ -520,7 +520,7 @@ def test_gettext_buildr_ignores_only_directive(app): @sphinx_intl # use individual shared_result directory to avoid "incompatible doctree" error -@pytest.mark.test_params(shared_result='test_gettext_dont_rebuild_mo') +@pytest.mark.sphinx(testroot='builder-gettext-dont-rebuild-mo') def test_gettext_dont_rebuild_mo(make_app, app_params, build_mo): # --- don't rebuild by .mo mtime def get_number_of_update_targets(app_): @@ -533,7 +533,7 @@ def test_gettext_dont_rebuild_mo(make_app, app_params, build_mo): app0 = make_app('dummy', *args, **kwargs) build_mo(app0.srcdir) app0.build() - assert (app0.srcdir / 'bom.mo') + assert (app0.srcdir / 'xx' / 'LC_MESSAGES' / 'bom.mo').exists() # Since it is after the build, the number of documents to be updated is 0 assert get_number_of_update_targets(app0) == 0 # When rewriting the timestamp of mo file, the number of documents to be From c250c63daaf67e9ca3f24ed9974d17016326de07 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Fri, 15 Dec 2017 21:14:20 +0900 Subject: [PATCH 105/275] test: Skip some builders on test_build_all --- tests/test_build.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_build.py b/tests/test_build.py index 2372b102b..c61fbb5c2 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -59,13 +59,13 @@ def nonascii_srcdir(request, rootdir, sphinx_test_tempdir): return srcdir +# note: this test skips building docs for some builders because they have independent testcase. +# (html, latex, texinfo and manpage) @pytest.mark.parametrize( "buildername", [ - # note: no 'html' - if it's ok with dirhtml it's ok with html - 'dirhtml', 'singlehtml', 'latex', 'texinfo', 'pickle', 'json', 'text', - 'htmlhelp', 'qthelp', 'epub2', 'epub', 'applehelp', 'changes', 'xml', - 'pseudoxml', 'man', 'linkcheck', + 'dirhtml', 'singlehtml', 'pickle', 'json', 'text', 'htmlhelp', 'qthelp', + 'epub2', 'epub', 'applehelp', 'changes', 'xml', 'pseudoxml', 'linkcheck', ], ) @mock.patch('sphinx.builders.linkcheck.requests.head', From fe07365a8cea7186261930f19b7f15735e545c57 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Fri, 15 Dec 2017 22:17:03 +0900 Subject: [PATCH 106/275] Fix mypy violations --- sphinx/application.py | 5 +++-- sphinx/domains/__init__.py | 2 +- sphinx/io.py | 2 +- sphinx/registry.py | 13 +++++++------ 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index ef20e56d8..3edd3fb98 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -33,7 +33,6 @@ from sphinx.deprecation import RemovedInSphinx20Warning from sphinx.environment import BuildEnvironment from sphinx.events import EventManager from sphinx.extension import verify_required_extensions -from sphinx.io import SphinxStandaloneReader from sphinx.locale import __ from sphinx.registry import SphinxComponentRegistry from sphinx.util import pycompat # noqa: F401 @@ -54,7 +53,9 @@ if False: from sphinx.domains import Domain, Index # NOQA from sphinx.environment.collectors import EnvironmentCollector # NOQA from sphinx.extension import Extension # NOQA + from sphinx.roles import XRefRole # NOQA from sphinx.theming import Theme # NOQA + from sphinx.util.typing import RoleFunction # NOQA builtin_extensions = ( 'sphinx.builders.applehelp', @@ -563,7 +564,7 @@ class Sphinx(object): has_content, argument_spec, **option_spec) def add_role_to_domain(self, domain, name, role): - # type: (unicode, unicode, Any) -> None + # type: (unicode, unicode, Union[RoleFunction, XRefRole]) -> None self.registry.add_role_to_domain(domain, name, role) def add_index_to_domain(self, domain, index): diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index ddb6c7c66..1b9a7345a 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -141,7 +141,7 @@ class Domain(object): #: domain label: longer, more descriptive (used in messages) label = '' #: type (usually directive) name -> ObjType instance - object_types = {} # type: Dict[unicode, Any] + object_types = {} # type: Dict[unicode, ObjType] #: directive name -> directive class directives = {} # type: Dict[unicode, Any] #: role name -> role callable diff --git a/sphinx/io.py b/sphinx/io.py index 4bb554742..804932863 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -86,7 +86,7 @@ class SphinxStandaloneReader(SphinxBaseReader): def __init__(self, app, *args, **kwargs): # type: (Sphinx, Any, Any) -> None self.transforms = self.transforms + app.registry.get_transforms() - SphinxBaseReader.__init__(self, *args, **kwargs) + SphinxBaseReader.__init__(self, *args, **kwargs) # type: ignore class SphinxI18nReader(SphinxBaseReader): diff --git a/sphinx/registry.py b/sphinx/registry.py index 265524b28..885c7a256 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -29,7 +29,7 @@ from sphinx.util.docutils import directive_helper if False: # For type annotation - from typing import Any, Callable, Dict, Iterator, List, Type # NOQA + from typing import Any, Callable, Dict, Iterator, List, Type, Union # NOQA from docutils import nodes # NOQA from docutils.io import Input # NOQA from docutils.parsers import Parser # NOQA @@ -38,6 +38,7 @@ if False: from sphinx.builders import Builder # NOQA from sphinx.domains import Domain, Index # NOQA from sphinx.environment import BuildEnvironment # NOQA + from sphinx.util.typing import RoleFunction # NOQA logger = logging.getLogger(__name__) @@ -53,9 +54,9 @@ class SphinxComponentRegistry(object): self.builders = {} # type: Dict[unicode, Type[Builder]] self.domains = {} # type: Dict[unicode, Type[Domain]] self.domain_directives = {} # type: Dict[unicode, Dict[unicode, Any]] - self.domain_indices = {} # type: Dict[unicode, List[Index]] + self.domain_indices = {} # type: Dict[unicode, List[Type[Index]]] self.domain_object_types = {} # type: Dict[unicode, Dict[unicode, ObjType]] - self.domain_roles = {} # type: Dict[unicode, Dict[unicode, Any]] + self.domain_roles = {} # type: Dict[unicode, Dict[unicode, Union[RoleFunction, XRefRole]]] # NOQA self.post_transforms = [] # type: List[Type[Transform]] self.source_parsers = {} # type: Dict[unicode, Parser] self.source_inputs = {} # type: Dict[unicode, Input] @@ -139,7 +140,7 @@ class SphinxComponentRegistry(object): directives[name] = directive_helper(obj, has_content, argument_spec, **option_spec) def add_role_to_domain(self, domain, name, role): - # type: (unicode, unicode, Any) -> None + # type: (unicode, unicode, Union[RoleFunction, XRefRole]) -> None logger.debug('[app] adding role to domain: %r', (domain, name, role)) if domain not in self.domains: raise ExtensionError(__('domain %s not yet registered') % domain) @@ -186,8 +187,8 @@ class SphinxComponentRegistry(object): (Target, object), {'indextemplate': indextemplate}) - self.add_directive_to_domain('std', directive) - self.add_role_to_domain('std', XRefRole(innernodeclass=ref_nodeclass)) + self.add_directive_to_domain('std', directivename, directive) + self.add_role_to_domain('std', rolename, XRefRole(innernodeclass=ref_nodeclass)) object_types = self.domain_object_types.setdefault('std', {}) object_types[directivename] = ObjType(objname or directivename, rolename) From facce1fb020a61637a8d110cf556a08912e64035 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 16 Dec 2017 01:27:18 +0900 Subject: [PATCH 107/275] quickstart: Fix make_mode should be chosen by default --- sphinx/cmd/quickstart.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/cmd/quickstart.py b/sphinx/cmd/quickstart.py index af07d4978..80e9e3dd4 100644 --- a/sphinx/cmd/quickstart.py +++ b/sphinx/cmd/quickstart.py @@ -586,7 +586,7 @@ Makefile to be used with sphinx-build. dest='batchfile', help='do not create batchfile') group.add_argument('-m', '--use-make-mode', action='store_true', - dest='make_mode', + dest='make_mode', default=True, help='use make-mode for Makefile/make.bat') group.add_argument('-M', '--no-use-make-mode', action='store_false', dest='make_mode', From b131c33af5ea49c6416026050725a0121c8991f3 Mon Sep 17 00:00:00 2001 From: jfbu Date: Fri, 15 Dec 2017 22:54:52 +0100 Subject: [PATCH 108/275] Fix markup in doc/ext/math.rst --- doc/ext/math.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/ext/math.rst b/doc/ext/math.rst index 3d25d09ba..ca53f3a8e 100644 --- a/doc/ext/math.rst +++ b/doc/ext/math.rst @@ -78,7 +78,7 @@ or use Python raw strings (``r"raw"``). Normally, equations are not numbered. If you want your equation to get a number, use the ``label`` option. When given, it selects an internal label for the equation, by which it can be cross-referenced, and causes an equation - number to be issued. See :rst:role:`eqref` for an example. The numbering + number to be issued. See :rst:role:`eq` for an example. The numbering style depends on the output format. There is also an option ``nowrap`` that prevents any wrapping of the given From 7cabd6cbb053965e1930b53c27d596fd1a52dd78 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 16 Dec 2017 14:51:55 +0900 Subject: [PATCH 109/275] Fix mypy violations --- sphinx/builders/html.py | 2 +- sphinx/builders/qthelp.py | 2 +- sphinx/config.py | 2 +- sphinx/domains/cpp.py | 2 +- sphinx/environment/collectors/toctree.py | 2 +- sphinx/ext/napoleon/docstring.py | 22 +++++++++++----------- sphinx/pycode/nodes.py | 2 +- sphinx/setup_command.py | 10 +++++----- sphinx/transforms/compact_bullet_list.py | 6 +++++- sphinx/util/__init__.py | 8 +++----- sphinx/util/logging.py | 4 ++-- 11 files changed, 32 insertions(+), 30 deletions(-) diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index ead51a983..e50d2abe4 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -274,7 +274,7 @@ class StandaloneHTMLBuilder(Builder): # type: () -> Iterator[unicode] cfgdict = dict((confval.name, confval.value) for confval in self.config.filter('html')) self.config_hash = get_stable_hash(cfgdict) - self.tags_hash = get_stable_hash(sorted(self.tags)) # type: ignore + self.tags_hash = get_stable_hash(sorted(self.tags)) old_config_hash = old_tags_hash = '' try: with open(path.join(self.outdir, '.buildinfo')) as fp: diff --git a/sphinx/builders/qthelp.py b/sphinx/builders/qthelp.py index 14979fe4b..12a50d140 100644 --- a/sphinx/builders/qthelp.py +++ b/sphinx/builders/qthelp.py @@ -264,7 +264,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder): link = node['refuri'] title = htmlescape(node.astext()).replace('"', '"') item = section_template % {'title': title, 'ref': link} - item = u' ' * 4 * indentlevel + item # type: ignore + item = u' ' * 4 * indentlevel + item parts.append(item.encode('ascii', 'xmlcharrefreplace')) elif isinstance(node, nodes.bullet_list): for subnode in node: diff --git a/sphinx/config.py b/sphinx/config.py index 02ee529a3..cc5f57e8e 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -288,7 +288,7 @@ class Config(object): logger.warning("%s", exc) for name in config: if name in self.values: - self.__dict__[name] = config[name] + self.__dict__[name] = config[name] # type: ignore if isinstance(self.source_suffix, string_types): # type: ignore self.source_suffix = [self.source_suffix] # type: ignore diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 23c398e13..aa97481ab 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -528,7 +528,7 @@ class ASTBase(UnicodeMixin): if type(self) is not type(other): return False try: - for key, value in iteritems(self.__dict__): # type: ignore + for key, value in iteritems(self.__dict__): if value != getattr(other, key): return False except AttributeError: diff --git a/sphinx/environment/collectors/toctree.py b/sphinx/environment/collectors/toctree.py index f19fd5d26..91aa21f2e 100644 --- a/sphinx/environment/collectors/toctree.py +++ b/sphinx/environment/collectors/toctree.py @@ -262,7 +262,7 @@ class TocTreeCollector(EnvironmentCollector): continue - figtype = env.get_domain('std').get_figtype(subnode) # type: ignore + figtype = env.get_domain('std').get_figtype(subnode) if figtype and subnode['ids']: register_fignumber(docname, secnum, figtype, subnode) diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py index c77598ef1..d3a64049b 100644 --- a/sphinx/ext/napoleon/docstring.py +++ b/sphinx/ext/napoleon/docstring.py @@ -194,7 +194,7 @@ class GoogleDocstring(UnicodeMixin): line = self._line_iter.peek() while(not self._is_section_break() and (not line or self._is_indented(line, indent))): - lines.append(next(self._line_iter)) # type: ignore + lines.append(next(self._line_iter)) line = self._line_iter.peek() return lines @@ -204,7 +204,7 @@ class GoogleDocstring(UnicodeMixin): while (self._line_iter.has_next() and self._line_iter.peek() and not self._is_section_header()): - lines.append(next(self._line_iter)) # type: ignore + lines.append(next(self._line_iter)) return lines def _consume_empty(self): @@ -212,13 +212,13 @@ class GoogleDocstring(UnicodeMixin): lines = [] line = self._line_iter.peek() while self._line_iter.has_next() and not line: - lines.append(next(self._line_iter)) # type: ignore + lines.append(next(self._line_iter)) line = self._line_iter.peek() return lines def _consume_field(self, parse_type=True, prefer_type=False): # type: (bool, bool) -> Tuple[unicode, unicode, List[unicode]] - line = next(self._line_iter) # type: ignore + line = next(self._line_iter) before, colon, after = self._partition_field_on_colon(line) _name, _type, _desc = before, '', after # type: unicode, unicode, unicode @@ -250,7 +250,7 @@ class GoogleDocstring(UnicodeMixin): def _consume_inline_attribute(self): # type: () -> Tuple[unicode, List[unicode]] - line = next(self._line_iter) # type: ignore + line = next(self._line_iter) _type, colon, _desc = self._partition_field_on_colon(line) if not colon: _type, _desc = _desc, _type @@ -285,7 +285,7 @@ class GoogleDocstring(UnicodeMixin): def _consume_section_header(self): # type: () -> unicode - section = next(self._line_iter) # type: ignore + section = next(self._line_iter) stripped_section = section.strip(':') if stripped_section.lower() in self._sections: section = stripped_section @@ -295,7 +295,7 @@ class GoogleDocstring(UnicodeMixin): # type: () -> List[unicode] lines = [] while self._line_iter.has_next(): - lines.append(next(self._line_iter)) # type: ignore + lines.append(next(self._line_iter)) return lines def _consume_to_next_section(self): @@ -303,7 +303,7 @@ class GoogleDocstring(UnicodeMixin): self._consume_empty() lines = [] while not self._is_section_break(): - lines.append(next(self._line_iter)) # type: ignore + lines.append(next(self._line_iter)) return lines + self._consume_empty() def _dedent(self, lines, full=False): @@ -886,7 +886,7 @@ class NumpyDocstring(GoogleDocstring): def _consume_field(self, parse_type=True, prefer_type=False): # type: (bool, bool) -> Tuple[unicode, unicode, List[unicode]] - line = next(self._line_iter) # type: ignore + line = next(self._line_iter) if parse_type: _name, _, _type = self._partition_field_on_colon(line) else: @@ -907,10 +907,10 @@ class NumpyDocstring(GoogleDocstring): def _consume_section_header(self): # type: () -> unicode - section = next(self._line_iter) # type: ignore + section = next(self._line_iter) if not _directive_regex.match(section): # Consume the header underline - next(self._line_iter) # type: ignore + next(self._line_iter) return section def _is_section_break(self): diff --git a/sphinx/pycode/nodes.py b/sphinx/pycode/nodes.py index cecde9bd0..ea3b3e9ad 100644 --- a/sphinx/pycode/nodes.py +++ b/sphinx/pycode/nodes.py @@ -208,5 +208,5 @@ class NodeVisitor(object): def generic_visit(self, node): """Called if no explicit visitor function exists for a node.""" if isinstance(node, Node): - for child in node: # type: ignore + for child in node: self.visit(child) diff --git a/sphinx/setup_command.py b/sphinx/setup_command.py index d219a14d9..8c00a2ff8 100644 --- a/sphinx/setup_command.py +++ b/sphinx/setup_command.py @@ -136,8 +136,8 @@ class BuildDoc(Command): # type: () -> None if self.source_dir is None: self.source_dir = self._guess_source_dir() - self.announce('Using source directory %s' % self.source_dir) # type: ignore - self.ensure_dirname('source_dir') # type: ignore + self.announce('Using source directory %s' % self.source_dir) + self.ensure_dirname('source_dir') if self.source_dir is None: self.source_dir = os.curdir self.source_dir = abspath(self.source_dir) @@ -145,10 +145,10 @@ class BuildDoc(Command): self.config_dir = self.source_dir self.config_dir = abspath(self.config_dir) - self.ensure_string_list('builder') # type: ignore + self.ensure_string_list('builder') if self.build_dir is None: - build = self.get_finalized_command('build') # type: ignore - self.build_dir = os.path.join(abspath(build.build_base), 'sphinx') + build = self.get_finalized_command('build') + self.build_dir = os.path.join(abspath(build.build_base), 'sphinx') # type: ignore self.mkpath(self.build_dir) # type: ignore self.build_dir = abspath(self.build_dir) self.doctree_dir = os.path.join(self.build_dir, 'doctrees') diff --git a/sphinx/transforms/compact_bullet_list.py b/sphinx/transforms/compact_bullet_list.py index 006ae7161..8c930c8bc 100644 --- a/sphinx/transforms/compact_bullet_list.py +++ b/sphinx/transforms/compact_bullet_list.py @@ -14,6 +14,10 @@ from docutils import nodes from sphinx import addnodes from sphinx.transforms import SphinxTransform +if False: + # For type annotation + from typing import List # NOQA + class RefOnlyListChecker(nodes.GenericNodeVisitor): """Raise `nodes.NodeFound` if non-simple list item is encountered. @@ -32,7 +36,7 @@ class RefOnlyListChecker(nodes.GenericNodeVisitor): def visit_list_item(self, node): # type: (nodes.Node) -> None - children = [] + children = [] # type: List[nodes.Node] for child in node.children: if not isinstance(child, nodes.Invisible): children.append(child) diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py index 03f8ce6a3..55fb9fcc1 100644 --- a/sphinx/util/__init__.py +++ b/sphinx/util/__init__.py @@ -398,10 +398,8 @@ def parselinenos(spec, total): elif len(begend) == 1: items.append(int(begend[0]) - 1) elif len(begend) == 2: - start = int(begend[0] or 1) # type: ignore - # left half open (cf. -10) - end = int(begend[1] or max(start, total)) # type: ignore - # right half open (cf. 10-) + start = int(begend[0] or 1) # left half open (cf. -10) + end = int(begend[1] or max(start, total)) # right half open (cf. 10-) if start > end: # invalid range (cf. 10-1) raise ValueError items.extend(range(start - 1, end)) @@ -528,7 +526,7 @@ class PeekableIterator(object): def peek(self): # type: () -> Any """Return the next item without changing the state of the iterator.""" - item = next(self) # type: ignore + item = next(self) self.push(item) return item diff --git a/sphinx/util/logging.py b/sphinx/util/logging.py index 6148a5445..00c12ec4f 100644 --- a/sphinx/util/logging.py +++ b/sphinx/util/logging.py @@ -156,8 +156,8 @@ class NewLineStreamHandlerPY2(logging.StreamHandler): # remove return code forcely when nonl=True self.stream = StringIO() super(NewLineStreamHandlerPY2, self).emit(record) - stream.write(self.stream.getvalue()[:-1]) # type: ignore - stream.flush() # type: ignore + stream.write(self.stream.getvalue()[:-1]) + stream.flush() else: super(NewLineStreamHandlerPY2, self).emit(record) finally: From f07b080331f49b2b873995962c06f82ee576229c Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 16 Dec 2017 15:01:23 +0900 Subject: [PATCH 110/275] Fix mypy violations --- sphinx/ext/autodoc/inspector.py | 10 +++++----- sphinx/util/inspect.py | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sphinx/ext/autodoc/inspector.py b/sphinx/ext/autodoc/inspector.py index f1faf2043..5d157c797 100644 --- a/sphinx/ext/autodoc/inspector.py +++ b/sphinx/ext/autodoc/inspector.py @@ -65,7 +65,7 @@ def format_annotation(annotation): elif (hasattr(typing, 'UnionMeta') and isinstance(annotation, typing.UnionMeta) and # type: ignore hasattr(annotation, '__union_params__')): - params = annotation.__union_params__ # type: ignore + params = annotation.__union_params__ if params is not None: param_str = ', '.join(format_annotation(p) for p in params) return '%s[%s]' % (qualified_name, param_str) @@ -74,7 +74,7 @@ def format_annotation(annotation): getattr(annotation, '__args__', None) is not None and hasattr(annotation, '__result__')): # Skipped in the case of plain typing.Callable - args = annotation.__args__ # type: ignore + args = annotation.__args__ if args is None: return qualified_name elif args is Ellipsis: @@ -84,15 +84,15 @@ def format_annotation(annotation): args_str = '[%s]' % ', '.join(formatted_args) return '%s[%s, %s]' % (qualified_name, args_str, - format_annotation(annotation.__result__)) # type: ignore + format_annotation(annotation.__result__)) elif (hasattr(typing, 'TupleMeta') and isinstance(annotation, typing.TupleMeta) and # type: ignore hasattr(annotation, '__tuple_params__') and hasattr(annotation, '__tuple_use_ellipsis__')): - params = annotation.__tuple_params__ # type: ignore + params = annotation.__tuple_params__ if params is not None: param_strings = [format_annotation(p) for p in params] - if annotation.__tuple_use_ellipsis__: # type: ignore + if annotation.__tuple_use_ellipsis__: param_strings.append('...') return '%s[%s]' % (qualified_name, ', '.join(param_strings)) diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index 2d15c2883..da13b8af0 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -434,7 +434,7 @@ class Signature(object): elif (hasattr(typing, 'UnionMeta') and # for py35 or below isinstance(annotation, typing.UnionMeta) and # type: ignore hasattr(annotation, '__union_params__')): - params = annotation.__union_params__ # type: ignore + params = annotation.__union_params__ if params is not None: param_str = ', '.join(self.format_annotation(p) for p in params) return '%s[%s]' % (qualified_name, param_str) @@ -442,7 +442,7 @@ class Signature(object): getattr(annotation, '__args__', None) is not None and hasattr(annotation, '__result__')): # Skipped in the case of plain typing.Callable - args = annotation.__args__ # type: ignore + args = annotation.__args__ if args is None: return qualified_name elif args is Ellipsis: @@ -452,14 +452,14 @@ class Signature(object): args_str = '[%s]' % ', '.join(formatted_args) return '%s[%s, %s]' % (qualified_name, args_str, - self.format_annotation(annotation.__result__)) # type: ignore # NOQA + self.format_annotation(annotation.__result__)) elif (isinstance(annotation, typing.TupleMeta) and # type: ignore hasattr(annotation, '__tuple_params__') and hasattr(annotation, '__tuple_use_ellipsis__')): - params = annotation.__tuple_params__ # type: ignore + params = annotation.__tuple_params__ if params is not None: param_strings = [self.format_annotation(p) for p in params] - if annotation.__tuple_use_ellipsis__: # type: ignore + if annotation.__tuple_use_ellipsis__: param_strings.append('...') return '%s[%s]' % (qualified_name, ', '.join(param_strings)) From 14af6b429ef2355ba0e8342c4af0f9dd9aafab1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20G=C3=B3rny?= Date: Thu, 7 Dec 2017 23:15:05 +0100 Subject: [PATCH 111/275] Use ensuredir() instead of os.makedirs() to fix race conditions Use the ensuredir() function consistently across Sphinx code to avoid race conditions e.g. when multiple Sphinx instances attempt to create the same output directory. The ensuredir() function that was already present in sphinx.util.osutil correctly catches EEXIST exception that occurs if the specified directory already exists (i.e. it was created between the call to os.path.isdir() and os.makedirs() that follows it). While at it, remove redundant os.path.isdir() calls when they only guarded the os.makedirs() call, and replace mkdir_p() which had pretty much the same purpose, except for being prone to race conditions. I did not modify testing-related code as race conditions mostly affect real applications and not the test environment. Fix #4281: Race conditions when creating output directory --- CHANGES | 1 + sphinx/apidoc.py | 7 +++---- sphinx/application.py | 4 ++-- sphinx/builders/__init__.py | 6 ++---- sphinx/quickstart.py | 19 ++++++------------- 5 files changed, 14 insertions(+), 23 deletions(-) diff --git a/CHANGES b/CHANGES index b7a16af4f..1b8289784 100644 --- a/CHANGES +++ b/CHANGES @@ -33,6 +33,7 @@ Bugs fixed * #4279: Sphinx crashes with pickling error when run with multiple processes and remote image * #1421: Respect the quiet flag in sphinx-quickstart +* #4281: Race conditions when creating output directory Testing -------- diff --git a/sphinx/apidoc.py b/sphinx/apidoc.py index 24ed874b0..b764cfc35 100644 --- a/sphinx/apidoc.py +++ b/sphinx/apidoc.py @@ -26,7 +26,7 @@ from fnmatch import fnmatch from sphinx import __display_version__ from sphinx.quickstart import EXTENSIONS from sphinx.util import rst -from sphinx.util.osutil import FileAvoidWrite, walk +from sphinx.util.osutil import FileAvoidWrite, ensuredir, walk if False: # For type annotation @@ -375,9 +375,8 @@ Note: By default this script will not overwrite already created files.""") if not path.isdir(rootpath): print('%s is not a directory.' % rootpath, file=sys.stderr) sys.exit(1) - if not path.isdir(opts.destdir): - if not opts.dryrun: - os.makedirs(opts.destdir) + if not opts.dryrun: + ensuredir(opts.destdir) rootpath = path.abspath(rootpath) excludes = normalize_excludes(rootpath, excludes) modules = recurse_tree(rootpath, excludes, opts) diff --git a/sphinx/application.py b/sphinx/application.py index 0d6d3d0b3..b5705face 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -41,7 +41,7 @@ from sphinx.util import import_object from sphinx.util import logging from sphinx.util import status_iterator, old_status_iterator, display_chunk from sphinx.util.tags import Tags -from sphinx.util.osutil import ENOENT +from sphinx.util.osutil import ENOENT, ensuredir from sphinx.util.console import bold, darkgreen # type: ignore from sphinx.util.docutils import is_html5_writer_available, directive_helper from sphinx.util.i18n import find_catalog_source_files @@ -160,7 +160,7 @@ class Sphinx(object): if not path.isdir(outdir): logger.info('making output directory...') - os.makedirs(outdir) + ensuredir(outdir) # read config self.tags = Tags(tags) diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index 007964e82..a1d5c5d22 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -9,7 +9,6 @@ :license: BSD, see LICENSE for details. """ -import os from os import path import warnings @@ -24,7 +23,7 @@ from docutils import nodes from sphinx.deprecation import RemovedInSphinx20Warning from sphinx.environment.adapters.asset import ImageAdapter from sphinx.util import i18n, path_stabilize, logging, status_iterator -from sphinx.util.osutil import SEP, relative_uri +from sphinx.util.osutil import SEP, ensuredir, relative_uri from sphinx.util.i18n import find_catalog from sphinx.util.console import bold # type: ignore from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, \ @@ -79,8 +78,7 @@ class Builder(object): self.confdir = app.confdir self.outdir = app.outdir self.doctreedir = app.doctreedir - if not path.isdir(self.doctreedir): - os.makedirs(self.doctreedir) + ensuredir(self.doctreedir) self.app = app # type: Sphinx self.env = None # type: BuildEnvironment diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index d23dc3b74..5d8738996 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -35,7 +35,7 @@ from six.moves.urllib.parse import quote as urlquote from docutils.utils import column_width from sphinx import __display_version__, package_dir -from sphinx.util.osutil import make_filename +from sphinx.util.osutil import ensuredir, make_filename from sphinx.util.console import ( # type: ignore purple, bold, red, turquoise, nocolor, color_terminal ) @@ -69,13 +69,6 @@ EXTENSIONS = ('autodoc', 'doctest', 'intersphinx', 'todo', 'coverage', PROMPT_PREFIX = '> ' -def mkdir_p(dir): - # type: (unicode) -> None - if path.isdir(dir): - return - os.makedirs(dir) - - # function to get input from terminal -- overridden by the test suite def term_input(prompt): # type: (unicode) -> unicode @@ -433,11 +426,11 @@ def generate(d, overwrite=True, silent=False, templatedir=None): d[key + '_str'] = d[key].replace('\\', '\\\\').replace("'", "\\'") if not path.isdir(d['path']): - mkdir_p(d['path']) + ensuredir(d['path']) srcdir = d['sep'] and path.join(d['path'], 'source') or d['path'] - mkdir_p(srcdir) + ensuredir(srcdir) if d['sep']: builddir = path.join(d['path'], 'build') d['exclude_patterns'] = '' @@ -448,9 +441,9 @@ def generate(d, overwrite=True, silent=False, templatedir=None): 'Thumbs.db', '.DS_Store', ]) d['exclude_patterns'] = ', '.join(exclude_patterns) - mkdir_p(builddir) - mkdir_p(path.join(srcdir, d['dot'] + 'templates')) - mkdir_p(path.join(srcdir, d['dot'] + 'static')) + ensuredir(builddir) + ensuredir(path.join(srcdir, d['dot'] + 'templates')) + ensuredir(path.join(srcdir, d['dot'] + 'static')) def write_file(fpath, content, newline=None): # type: (unicode, unicode, unicode) -> None From 070fbb97e5a8f41a398ac5de16938f2da5797a5a Mon Sep 17 00:00:00 2001 From: jfbu Date: Sat, 16 Dec 2017 11:05:33 +0100 Subject: [PATCH 112/275] Add markup and clarify numfig_secnum_depth docs --- doc/config.rst | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/doc/config.rst b/doc/config.rst index 7a6d20147..3b490c5d3 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -311,8 +311,8 @@ General configuration .. confval:: numfig If true, figures, tables and code-blocks are automatically numbered if they - have a caption. At same time, the `numref` role is enabled. For now, it - works only with the HTML builder and LaTeX builder. Default is ``False``. + have a caption. The :rst:role:`numref` role is enabled. + Obeyed so far only by HTML and LaTeX builders. Default is ``False``. .. note:: @@ -335,10 +335,12 @@ General configuration .. confval:: numfig_secnum_depth - The scope of figure numbers, that is, the numfig feature numbers figures - in which scope. ``0`` means "whole document". ``1`` means "in a section". - Sphinx numbers like x.1, x.2, x.3... ``2`` means "in a subsection". Sphinx - numbers like x.x.1, x.x.2, x.x.3..., and so on. Default is ``1``. + The scope for numbering: ``0`` means "continuous numbering", + ``1`` means "reset per section" + (i.e. numbers will be x.1, x.2, x.3 ... with x the section number), + ``2`` means "per subsection" + (i.e. numbers will be x.y.1, x.y.2, ...), + and so on. Default is ``1``. .. versionadded:: 1.3 From f780f92d1b0eb1c3f6b37dc1e75e0980d046b134 Mon Sep 17 00:00:00 2001 From: jfbu Date: Sat, 16 Dec 2017 11:32:40 +0100 Subject: [PATCH 113/275] Mention ``:numbered:`` needed in numfig_secnum_depth docs --- doc/config.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/config.rst b/doc/config.rst index 3b490c5d3..fc87c4ddc 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -337,7 +337,9 @@ General configuration The scope for numbering: ``0`` means "continuous numbering", ``1`` means "reset per section" - (i.e. numbers will be x.1, x.2, x.3 ... with x the section number), + (i.e. numbers will be x.1, x.2, x.3 ... with x the section number, + assuming that the :rst:dir:`toctree` directive was used with its option + ``:numbered:``), ``2`` means "per subsection" (i.e. numbers will be x.y.1, x.y.2, ...), and so on. Default is ``1``. From a9602e4597a75889edc91e65f226c72a5ae73d0e Mon Sep 17 00:00:00 2001 From: jfbu Date: Sat, 16 Dec 2017 11:46:33 +0100 Subject: [PATCH 114/275] Improve numref docs --- doc/markup/inline.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/markup/inline.rst b/doc/markup/inline.rst index a59585bab..09ea49003 100644 --- a/doc/markup/inline.rst +++ b/doc/markup/inline.rst @@ -222,15 +222,15 @@ Cross-referencing figures by figure number reST labels are used. When you use this role, it will insert a reference to the figure with link text by its figure number like "Fig. 1.1". - If an explicit link text is given (like usual: ``:numref:`Image of Sphinx (Fig. - %s) ```), the link caption will be the title of the reference. - As a special character, `%s` and `{number}` will be replaced to figure - number. `{name}` will be replaced to figure caption. - If no explicit link text is given, the value of :confval:`numfig_format` is - used to default value of link text. + If an explicit link text is given (as usual: ``:numref:`Image of Sphinx (Fig. + %s) ```), the link caption will serve as title of the reference. + As place holders, `%s` and `{number}` get replaced by the figure + number and `{name}` by the figure caption. + If no explicit link text is given, the :confval:`numfig_format` setting is + used as fall-back default. - If :confval:`numfig` is ``False``, figures are not numbered. - so this role inserts not a reference but labels or link text. + If :confval:`numfig` is ``False``, figures are not numbered, + so this role inserts not a reference but the label or the link text. Cross-referencing other items of interest ----------------------------------------- From ba1368072fdfc143322a38335ebcdd8d83c6f720 Mon Sep 17 00:00:00 2001 From: jfbu Date: Sat, 16 Dec 2017 11:51:00 +0100 Subject: [PATCH 115/275] Typo place holder --> placeholder --- doc/markup/inline.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/markup/inline.rst b/doc/markup/inline.rst index 09ea49003..7ed3e7207 100644 --- a/doc/markup/inline.rst +++ b/doc/markup/inline.rst @@ -224,7 +224,7 @@ Cross-referencing figures by figure number If an explicit link text is given (as usual: ``:numref:`Image of Sphinx (Fig. %s) ```), the link caption will serve as title of the reference. - As place holders, `%s` and `{number}` get replaced by the figure + As placeholders, `%s` and `{number}` get replaced by the figure number and `{name}` by the figure caption. If no explicit link text is given, the :confval:`numfig_format` setting is used as fall-back default. From 04f2929f59b49fefbc6804088089994567b67ad9 Mon Sep 17 00:00:00 2001 From: Oliver Jahn Date: Sat, 16 Dec 2017 10:34:06 -0500 Subject: [PATCH 116/275] mention limitation to html-like targets --- doc/ext/math.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/ext/math.rst b/doc/ext/math.rst index fe7b85c83..0fb3a17cf 100644 --- a/doc/ext/math.rst +++ b/doc/ext/math.rst @@ -46,10 +46,10 @@ or use Python raw strings (``r"raw"``). .. confval:: math_numfig - If ``True``, displayed math equations are numbered across pages using numfig. - The :confval:`numfig` config value must be enabled and - :confval:`numfig_secnum_depth` is respected. The ``:eq:`` role must be used - to refererence these equation numbers, not the ``:numref:`` role. + If ``True``, displayed math equations are numbered across pages in html and + related (epub, ...) output. The :confval:`numfig` config value must be + enabled and :confval:`numfig_secnum_depth` is respected. The ``:eq:`` role + must be used to reference equation numbers, not the ``:numref:`` role. Default is ``False``. :mod:`.mathbase` defines these new markup elements: From 53a84de822c94b14a10cb5f416668b2834983c12 Mon Sep 17 00:00:00 2001 From: Oliver Jahn Date: Sat, 16 Dec 2017 09:37:38 -0500 Subject: [PATCH 117/275] make math_numfig work with singlehtml writer --- sphinx/ext/imgmath.py | 2 +- sphinx/ext/jsmath.py | 2 +- sphinx/ext/mathbase.py | 19 +++++++++++-------- sphinx/ext/mathjax.py | 2 +- sphinx/ext/pngmath.py | 2 +- 5 files changed, 15 insertions(+), 12 deletions(-) diff --git a/sphinx/ext/imgmath.py b/sphinx/ext/imgmath.py index 04d6b708a..a8a7f5d8c 100644 --- a/sphinx/ext/imgmath.py +++ b/sphinx/ext/imgmath.py @@ -334,7 +334,7 @@ def html_visit_displaymath(self, node): self.body.append(self.starttag(node, 'div', CLASS='math')) self.body.append('

') if node['number']: - number = get_node_equation_number(self.builder.env, node) + number = get_node_equation_number(self, node) self.body.append('(%s)' % number) self.add_permalink_ref(node, _('Permalink to this equation')) self.body.append('') diff --git a/sphinx/ext/jsmath.py b/sphinx/ext/jsmath.py index 978e3f3d6..3c31b0a02 100644 --- a/sphinx/ext/jsmath.py +++ b/sphinx/ext/jsmath.py @@ -36,7 +36,7 @@ def html_visit_displaymath(self, node): if i == 0: # necessary to e.g. set the id property correctly if node['number']: - number = get_node_equation_number(self.builder.env, node) + number = get_node_equation_number(self, node) self.body.append('(%s)' % number) self.add_permalink_ref(node, _('Permalink to this equation')) self.body.append('') diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py index 313f72bd4..5f353ac9c 100644 --- a/sphinx/ext/mathbase.py +++ b/sphinx/ext/mathbase.py @@ -133,17 +133,20 @@ class MathDomain(Domain): return len(targets) + 1 -def get_node_equation_number(env, node): - if env.config.math_numfig and env.config.numfig: - docname = node['docname'] - if docname in env.toc_fignumbers: - id = node['ids'][0] - number = env.toc_fignumbers[docname]['displaymath'].get(id, ()) - number = '.'.join(map(str, number)) +def get_node_equation_number(writer, node): + if writer.builder.config.math_numfig and writer.builder.config.numfig: + figtype = 'displaymath' + if writer.builder.name == 'singlehtml': + key = u"%s/%s" % (writer.docnames[-1], figtype) else: - number = '' + key = figtype + + id = node['ids'][0] + number = writer.builder.fignumbers.get(key, {}).get(id, ()) + number = '.'.join(map(str, number)) else: number = node['number'] + return number diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py index aff5c103b..8b7e700ac 100644 --- a/sphinx/ext/mathjax.py +++ b/sphinx/ext/mathjax.py @@ -37,7 +37,7 @@ def html_visit_displaymath(self, node): # necessary to e.g. set the id property correctly if node['number']: - number = get_node_equation_number(self.builder.env, node) + number = get_node_equation_number(self, node) self.body.append('(%s)' % number) self.add_permalink_ref(node, _('Permalink to this equation')) self.body.append('') diff --git a/sphinx/ext/pngmath.py b/sphinx/ext/pngmath.py index 968139f15..499f37e79 100644 --- a/sphinx/ext/pngmath.py +++ b/sphinx/ext/pngmath.py @@ -243,7 +243,7 @@ def html_visit_displaymath(self, node): self.body.append(self.starttag(node, 'div', CLASS='math')) self.body.append('

') if node['number']: - number = get_node_equation_number(self.builder.env, node) + number = get_node_equation_number(self, node) self.body.append('(%s)' % number) if fname is None: # something failed -- use text-only as a bad substitute From 832914423e84067f3cf764bcb84e20ade00f02af Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 17 Dec 2017 00:03:56 +0900 Subject: [PATCH 118/275] autodoc: refactor AutoDirective --- sphinx/application.py | 3 +- sphinx/ext/autodoc/__init__.py | 123 +-------------------- sphinx/ext/autodoc/directive.py | 172 +++++++++++++++++++++++++++++ sphinx/ext/autosummary/__init__.py | 2 +- sphinx/util/docutils.py | 8 +- 5 files changed, 180 insertions(+), 128 deletions(-) create mode 100644 sphinx/ext/autodoc/directive.py diff --git a/sphinx/application.py b/sphinx/application.py index 05d302c81..e49ac6174 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -659,8 +659,9 @@ class Sphinx(object): # type: (Any) -> None logger.debug('[app] adding autodocumenter: %r', cls) from sphinx.ext import autodoc + from sphinx.ext.autodoc.directive import AutodocDirective autodoc.add_documenter(cls) - self.add_directive('auto' + cls.objtype, autodoc.AutoDirective) + self.add_directive('auto' + cls.objtype, AutodocDirective) def add_autodoc_attrgetter(self, type, getter): # type: (Any, Callable) -> None diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index ff161565c..c74ca43c9 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -18,8 +18,6 @@ import traceback from six import PY2, iterkeys, iteritems, itervalues, text_type, class_types, string_types -from docutils import nodes -from docutils.utils import assemble_option_dict from docutils.parsers.rst import Directive from docutils.statemachine import ViewList @@ -32,7 +30,6 @@ from sphinx.locale import _ from sphinx.pycode import ModuleAnalyzer, PycodeError from sphinx.application import ExtensionError from sphinx.util import logging -from sphinx.util.nodes import nested_parse_with_titles from sphinx.util.inspect import Signature, isdescriptor, safe_getmembers, \ safe_getattr, object_description, is_builtin_class_method, \ isenumclass, isenumattribute, getdoc @@ -42,11 +39,11 @@ if False: # For type annotation from types import ModuleType # NOQA from typing import Any, Callable, Dict, Iterator, List, Sequence, Set, Tuple, Type, Union # NOQA - from docutils.utils import Reporter # NOQA from sphinx.application import Sphinx # NOQA logger = logging.getLogger(__name__) + # This type isn't exposed directly in any modules, but can be found # here in most Python versions MethodDescriptorType = type(type.__subclasses__) @@ -63,42 +60,11 @@ py_ext_sig_re = re.compile( ''', re.VERBOSE) -class DefDict(dict): - """A dict that returns a default on nonexisting keys.""" - def __init__(self, default): - # type: (Any) -> None - dict.__init__(self) - self.default = default - - def __getitem__(self, key): - # type: (Any) -> Any - try: - return dict.__getitem__(self, key) - except KeyError: - return self.default - - def __bool__(self): - # type: () -> bool - # docutils check "if option_spec" - return True - __nonzero__ = __bool__ # for python2 compatibility - - def identity(x): # type: (Any) -> Any return x -class Options(dict): - """A dict/attribute hybrid that returns None on nonexisting keys.""" - def __getattr__(self, name): - # type: (unicode) -> Any - try: - return self[name.replace('_', '-')] - except KeyError: - return None - - ALL = object() INSTANCEATTR = object() @@ -1525,93 +1491,6 @@ class AutoDirective(Directive): # a registry of type -> getattr function _special_attrgetters = {} # type: Dict[Type, Callable] - # flags that can be given in autodoc_default_flags - _default_flags = set([ - 'members', 'undoc-members', 'inherited-members', 'show-inheritance', - 'private-members', 'special-members', - ]) - - # standard docutils directive settings - has_content = True - required_arguments = 1 - optional_arguments = 0 - final_argument_whitespace = True - # allow any options to be passed; the options are parsed further - # by the selected Documenter - option_spec = DefDict(identity) - - def warn(self, msg): - # type: (unicode) -> None - self.warnings.append(self.reporter.warning(msg, line=self.lineno)) - - def run(self): - # type: () -> List[nodes.Node] - self.filename_set = set() # type: Set[unicode] - # a set of dependent filenames - self.reporter = self.state.document.reporter - self.env = self.state.document.settings.env - self.warnings = [] # type: List[unicode] - self.result = ViewList() - - try: - source, lineno = self.reporter.get_source_and_line(self.lineno) - except AttributeError: - source = lineno = None - logger.debug('[autodoc] %s:%s: input:\n%s', - source, lineno, self.block_text) - - # find out what documenter to call - objtype = self.name[4:] - doc_class = self._registry[objtype] - # add default flags - for flag in self._default_flags: - if flag not in doc_class.option_spec: - continue - negated = self.options.pop('no-' + flag, 'not given') is None - if flag in self.env.config.autodoc_default_flags and \ - not negated: - self.options[flag] = None - # process the options with the selected documenter's option_spec - try: - self.genopt = Options(assemble_option_dict( - self.options.items(), doc_class.option_spec)) - except (KeyError, ValueError, TypeError) as err: - # an option is either unknown or has a wrong type - msg = self.reporter.error('An option to %s is either unknown or ' - 'has an invalid value: %s' % (self.name, err), - line=self.lineno) - return [msg] - # generate the output - documenter = doc_class(self, self.arguments[0]) - documenter.generate(more_content=self.content) - if not self.result: - return self.warnings - - logger.debug('[autodoc] output:\n%s', '\n'.join(self.result)) - - # record all filenames as dependencies -- this will at least - # partially make automatic invalidation possible - for fn in self.filename_set: - self.state.document.settings.record_dependencies.add(fn) - - # use a custom reporter that correctly assigns lines to source - # filename/description and lineno - old_reporter = self.state.memo.reporter - self.state.memo.reporter = AutodocReporter(self.result, - self.state.memo.reporter) - - if documenter.titles_allowed: - node = nodes.section() - # necessary so that the child nodes get the right source/line set - node.document = self.state.document - nested_parse_with_titles(self.state, self.result, node) - else: - node = nodes.paragraph() - node.document = self.state.document - self.state.nested_parse(self.result, 0, node) - self.state.memo.reporter = old_reporter - return self.warnings + node.children - def add_documenter(cls): # type: (Type[Documenter]) -> None diff --git a/sphinx/ext/autodoc/directive.py b/sphinx/ext/autodoc/directive.py new file mode 100644 index 000000000..9be273982 --- /dev/null +++ b/sphinx/ext/autodoc/directive.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- +""" + sphinx.ext.autodoc.directive + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +from docutils import nodes +from docutils.parsers.rst import Directive +from docutils.statemachine import ViewList +from docutils.utils import assemble_option_dict + +from sphinx.ext.autodoc import AutoDirective, AutodocReporter, identity +from sphinx.util import logging +from sphinx.util.nodes import nested_parse_with_titles + +if False: + # For type annotation + from typing import Any, Dict, List, Set, Type # NOQA + from docutils.statemachine import State, StateMachine, StringList # NOQA + from docutils.utils import Reporter # NOQA + from sphinx.config import Config # NOQA + from sphinx.environment import BuildEnvironment # NOQA + from sphinx.ext.autodoc import Documenter # NOQA + +logger = logging.getLogger(__name__) + + +# common option names for autodoc directives +AUTODOC_DEFAULT_OPTIONS = ['members', 'undoc-members', 'inherited-members', + 'show-inheritance', 'private-members', 'special-members'] + + +class DefDict(dict): + """A dict that returns a default on nonexisting keys.""" + def __init__(self, default): + # type: (Any) -> None + dict.__init__(self) + self.default = default + + def __getitem__(self, key): + # type: (Any) -> Any + try: + return dict.__getitem__(self, key) + except KeyError: + return self.default + + def __bool__(self): + # type: () -> bool + # docutils check "if option_spec" + return True + + __nonzero__ = __bool__ # for python2 compatibility + + +class Options(dict): + """A dict/attribute hybrid that returns None on nonexisting keys.""" + def __getattr__(self, name): + # type: (unicode) -> Any + try: + return self[name.replace('_', '-')] + except KeyError: + return None + + +class DocumenterBridge(object): + def __init__(self, env, reporter, options, lineno): + # type: (BuildEnvironment, Reporter, Options, int) -> None + self.env = env + self.reporter = reporter + self.genopt = options + self.lineno = lineno + self.filename_set = set() # type: Set[unicode] + self.warnings = [] # type: List[nodes.Node] + self.result = ViewList() + + def warn(self, msg): + # type: (unicode) -> None + self.warnings.append(self.reporter.warning(msg, line=self.lineno)) + + +def process_documenter_options(documenter, config, options): + # type: (Type[Documenter], Config, Dict) -> Options + for name in AUTODOC_DEFAULT_OPTIONS: + if name not in documenter.option_spec: + continue + else: + negated = options.pop('no-' + name, True) is None + if name in config.autodoc_default_flags and not negated: + options[name] = None + + return Options(assemble_option_dict(options.items(), documenter.option_spec)) + + +def parse_generated_content(state, content, documenter): + # type: (State, StringList, Documenter) -> List[nodes.Node] + try: + # use a custom reporter that correctly assigns lines to source + # filename/description and lineno + old_reporter = state.memo.reporter + state.memo.reporter = AutodocReporter(content, state.memo.reporter) + + if documenter.titles_allowed: + node = nodes.section() + # necessary so that the child nodes get the right source/line set + node.document = state.document + nested_parse_with_titles(state, content, node) + else: + node = nodes.paragraph() + node.document = state.document + state.nested_parse(content, 0, node) + + return node.children + finally: + state.memo.reporter = old_reporter + + +class AutodocDirective(Directive): + """A directive class for all autodoc directives. It works as a dispatcher of Documenters. + + It invokes a Documenter on running. After the processing, it parses and returns + the generated content by Documenter. + """ + option_spec = DefDict(identity) + has_content = True + required_arguments = 1 + optional_arguments = 0 + final_argument_whitespace = True + + def run(self): + # type: () -> List[nodes.Node] + env = self.state.document.settings.env + reporter = self.state.document.reporter + + try: + source, lineno = reporter.get_source_and_line(self.lineno) + except AttributeError: + source, lineno = (None, None) + logger.debug('[autodoc] %s:%s: input:\n%s', source, lineno, self.block_text) + + # look up target Documenter + objtype = self.name[4:] # strip prefix (auto-). + doccls = AutoDirective._registry[objtype] + + # process the options with the selected documenter's option_spec + try: + documenter_options = process_documenter_options(doccls, env.config, self.options) + except (KeyError, ValueError, TypeError) as exc: + # an option is either unknown or has a wrong type + msg = reporter.error('An option to %s is either unknown or ' + 'has an invalid value: %s' % (self.name, exc), + line=lineno) + return [msg] + + # generate the output + params = DocumenterBridge(env, reporter, documenter_options, lineno) + documenter = doccls(params, self.arguments[0]) + documenter.generate(more_content=self.content) + if not params.result: + return params.warnings + + logger.debug('[autodoc] output:\n%s', '\n'.join(params.result)) + + # record all filenames as dependencies -- this will at least + # partially make automatic invalidation possible + for fn in params.filename_set: + self.state.document.settings.record_dependencies.add(fn) + + result = parse_generated_content(self.state, params.result, documenter) + return params.warnings + result diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 21bfe7b13..b56f649bf 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -72,7 +72,7 @@ from sphinx import addnodes from sphinx.environment.adapters.toctree import TocTree from sphinx.util import import_object, rst, logging from sphinx.pycode import ModuleAnalyzer, PycodeError -from sphinx.ext.autodoc import Options +from sphinx.ext.autodoc.directive import Options from sphinx.ext.autodoc.importer import import_module if False: diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index 00ea5919e..a745e058a 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -31,7 +31,7 @@ report_re = re.compile('^(.+?:(?:\\d+)?): \\((DEBUG|INFO|WARNING|ERROR|SEVERE)/( if False: # For type annotation - from typing import Any, Callable, Iterator, List, Tuple # NOQA + from typing import Any, Callable, Dict, Iterator, List, Tuple # NOQA from docutils import nodes # NOQA from sphinx.environment import BuildEnvironment # NOQA from sphinx.io import SphinxFileInput # NOQA @@ -204,12 +204,12 @@ def is_html5_writer_available(): return __version_info__ > (0, 13, 0) -def directive_helper(obj, has_content=None, argument_spec=None, **option_spec): - # type: (Any, bool, Tuple[int, int, bool], Any) -> Any +def directive_helper(obj, has_content=None, argument_spec=None, option_spec=None, **options): + # type: (Any, bool, Tuple[int, int, bool], Dict, Any) -> Any if isinstance(obj, (types.FunctionType, types.MethodType)): obj.content = has_content # type: ignore obj.arguments = argument_spec or (0, 0, False) # type: ignore - obj.options = option_spec # type: ignore + obj.options = option_spec or options # type: ignore return convert_directive_function(obj) else: if has_content or argument_spec or option_spec: From cac965cf77cb69d7807df566bcaa62d31cafd143 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 16 Dec 2017 23:43:08 +0900 Subject: [PATCH 119/275] autodoc: refactor option_spec of autodirectives --- sphinx/ext/autodoc/directive.py | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/sphinx/ext/autodoc/directive.py b/sphinx/ext/autodoc/directive.py index 9be273982..f348e105a 100644 --- a/sphinx/ext/autodoc/directive.py +++ b/sphinx/ext/autodoc/directive.py @@ -12,7 +12,7 @@ from docutils.parsers.rst import Directive from docutils.statemachine import ViewList from docutils.utils import assemble_option_dict -from sphinx.ext.autodoc import AutoDirective, AutodocReporter, identity +from sphinx.ext.autodoc import AutoDirective, AutodocReporter from sphinx.util import logging from sphinx.util.nodes import nested_parse_with_titles @@ -33,26 +33,12 @@ AUTODOC_DEFAULT_OPTIONS = ['members', 'undoc-members', 'inherited-members', 'show-inheritance', 'private-members', 'special-members'] -class DefDict(dict): - """A dict that returns a default on nonexisting keys.""" - def __init__(self, default): - # type: (Any) -> None - dict.__init__(self) - self.default = default +class DummyOptionSpec(object): + """An option_spec allows any options.""" def __getitem__(self, key): # type: (Any) -> Any - try: - return dict.__getitem__(self, key) - except KeyError: - return self.default - - def __bool__(self): - # type: () -> bool - # docutils check "if option_spec" - return True - - __nonzero__ = __bool__ # for python2 compatibility + return lambda x: x class Options(dict): @@ -123,7 +109,7 @@ class AutodocDirective(Directive): It invokes a Documenter on running. After the processing, it parses and returns the generated content by Documenter. """ - option_spec = DefDict(identity) + option_spec = DummyOptionSpec() has_content = True required_arguments = 1 optional_arguments = 0 From 299b11f26f98b1f6bf61602ff9955a12b7d1593e Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 17 Dec 2017 01:20:18 +0900 Subject: [PATCH 120/275] Replace AutodocReporter by switch_source_input() --- CHANGES | 2 ++ doc/extdev/markupapi.rst | 22 ++++++++++++++++++++-- sphinx/ext/autodoc/__init__.py | 5 +++++ sphinx/ext/autodoc/directive.py | 12 +++--------- sphinx/util/docutils.py | 22 +++++++++++++++++++++- 5 files changed, 51 insertions(+), 12 deletions(-) diff --git a/CHANGES b/CHANGES index ed76ea4a7..73a75a894 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,8 @@ Deprecated * using a string value for :confval:`html_sidebars` is deprecated and only list values will be accepted at 2.0. +* ``sphinx.ext.autodoc.AutodocReporter`` is replaced by ``sphinx.util.docutils. + switch_source_input()`` and now deprecated. It will be removed in Sphinx-2.0. Features added -------------- diff --git a/doc/extdev/markupapi.rst b/doc/extdev/markupapi.rst index df23f164d..8a18e2306 100644 --- a/doc/extdev/markupapi.rst +++ b/doc/extdev/markupapi.rst @@ -117,12 +117,30 @@ Both APIs parse the content into a given node. They are used like this:: node = docutils.nodes.paragraph() # either - from sphinx.ext.autodoc import AutodocReporter - self.state.memo.reporter = AutodocReporter(self.result, self.state.memo.reporter) # override reporter to avoid errors from "include" directive nested_parse_with_titles(self.state, self.result, node) # or self.state.nested_parse(self.result, 0, node) +.. note:: + + ``sphinx.util.docutils.switch_source_input()`` allows to change a target file + during nested_parse. It is useful to mixture contents. For example, ``sphinx. + ext.autodoc`` uses it to parse docstrings. + + from sphinx.util.docutils import switch_source_input + + # Switch source_input between parsing content. + # Inside this context, all parsing errors and warnings are reported as + # happened in new source_input (in this case, ``self.result``). + with switch_source_input(self.state, self.result): + node = docutils.nodes.paragraph() + self.state.nested_parse(self.result, 0, node) + + .. deprecated:: 1.7 + + Since Sphinx-1.6, ``sphinx.ext.autodoc.AutodocReporter`` is used for this purpose. + For now, it is replaced by ``switch_source_input()``. + If you don't need the wrapping node, you can use any concrete node type and return ``node.children`` from the Directive. diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index c74ca43c9..ebe929ea3 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -15,6 +15,7 @@ import re import sys import inspect import traceback +import warnings from six import PY2, iterkeys, iteritems, itervalues, text_type, class_types, string_types @@ -22,6 +23,7 @@ from docutils.parsers.rst import Directive from docutils.statemachine import ViewList import sphinx +from sphinx.deprecation import RemovedInSphinx20Warning from sphinx.ext.autodoc.importer import mock, import_module from sphinx.ext.autodoc.importer import _MockImporter # to keep compatibility # NOQA from sphinx.ext.autodoc.inspector import format_annotation, formatargspec # to keep compatibility # NOQA @@ -112,6 +114,9 @@ class AutodocReporter(object): """ def __init__(self, viewlist, reporter): # type: (ViewList, Reporter) -> None + warnings.warn('AutodocRerporter is now deprecated. ' + 'Use sphinx.util.docutils.switch_source_input() instead.', + RemovedInSphinx20Warning) self.viewlist = viewlist self.reporter = reporter diff --git a/sphinx/ext/autodoc/directive.py b/sphinx/ext/autodoc/directive.py index f348e105a..78593d27c 100644 --- a/sphinx/ext/autodoc/directive.py +++ b/sphinx/ext/autodoc/directive.py @@ -12,8 +12,9 @@ from docutils.parsers.rst import Directive from docutils.statemachine import ViewList from docutils.utils import assemble_option_dict -from sphinx.ext.autodoc import AutoDirective, AutodocReporter +from sphinx.ext.autodoc import AutoDirective from sphinx.util import logging +from sphinx.util.docutils import switch_source_input from sphinx.util.nodes import nested_parse_with_titles if False: @@ -82,12 +83,7 @@ def process_documenter_options(documenter, config, options): def parse_generated_content(state, content, documenter): # type: (State, StringList, Documenter) -> List[nodes.Node] - try: - # use a custom reporter that correctly assigns lines to source - # filename/description and lineno - old_reporter = state.memo.reporter - state.memo.reporter = AutodocReporter(content, state.memo.reporter) - + with switch_source_input(state, content): if documenter.titles_allowed: node = nodes.section() # necessary so that the child nodes get the right source/line set @@ -99,8 +95,6 @@ def parse_generated_content(state, content, documenter): state.nested_parse(content, 0, node) return node.children - finally: - state.memo.reporter = old_reporter class AutodocDirective(Directive): diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index a745e058a..f4dd96158 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -18,7 +18,7 @@ from contextlib import contextmanager import docutils from docutils.languages import get_language -from docutils.statemachine import ViewList +from docutils.statemachine import StateMachine, ViewList from docutils.parsers.rst import directives, roles, convert_directive_function from docutils.utils import Reporter @@ -33,6 +33,7 @@ if False: # For type annotation from typing import Any, Callable, Dict, Iterator, List, Tuple # NOQA from docutils import nodes # NOQA + from docutils.statemachine import State # NOQA from sphinx.environment import BuildEnvironment # NOQA from sphinx.io import SphinxFileInput # NOQA @@ -216,3 +217,22 @@ def directive_helper(obj, has_content=None, argument_spec=None, option_spec=None raise ExtensionError(__('when adding directive classes, no ' 'additional arguments may be given')) return obj + + +@contextmanager +def switch_source_input(state, content): + # type: (State, ViewList) -> None + """Switch current source input of state temporarily.""" + try: + # remember the original ``get_source_and_line()`` method + get_source_and_line = state.memo.reporter.get_source_and_line + + # replace it by new one + state_machine = StateMachine([], None) + state_machine.input_lines = content + state.memo.reporter.get_source_and_line = state_machine.get_source_and_line + + yield + finally: + # restore the method + state.memo.reporter.get_source_and_line = get_source_and_line From 1ab0d96a5f8b3ef1f07598a80aaf6c1f9eb5076c Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 17 Dec 2017 01:31:32 +0900 Subject: [PATCH 121/275] Update docstrings --- sphinx/ext/autodoc/directive.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sphinx/ext/autodoc/directive.py b/sphinx/ext/autodoc/directive.py index 78593d27c..077ee5dfd 100644 --- a/sphinx/ext/autodoc/directive.py +++ b/sphinx/ext/autodoc/directive.py @@ -53,6 +53,8 @@ class Options(dict): class DocumenterBridge(object): + """A parameters container for Documenters.""" + def __init__(self, env, reporter, options, lineno): # type: (BuildEnvironment, Reporter, Options, int) -> None self.env = env @@ -70,6 +72,7 @@ class DocumenterBridge(object): def process_documenter_options(documenter, config, options): # type: (Type[Documenter], Config, Dict) -> Options + """Recognize options of Documenter from user input.""" for name in AUTODOC_DEFAULT_OPTIONS: if name not in documenter.option_spec: continue @@ -83,6 +86,7 @@ def process_documenter_options(documenter, config, options): def parse_generated_content(state, content, documenter): # type: (State, StringList, Documenter) -> List[nodes.Node] + """Parse a generated content by Documenter.""" with switch_source_input(state, content): if documenter.titles_allowed: node = nodes.section() From 9b18e83e32942bd1b4b8e636619ec3d479302194 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 17 Dec 2017 01:39:15 +0900 Subject: [PATCH 122/275] Make AutoDirective as a simple object (not directive) --- sphinx/ext/autodoc/__init__.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index ebe929ea3..45195ff41 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -1475,11 +1475,11 @@ class InstanceAttributeDocumenter(AttributeDocumenter): AttributeDocumenter.add_content(self, more_content, no_docstring=True) -class AutoDirective(Directive): +class AutoDirective(object): """ - The AutoDirective class is used for all autodoc directives. It dispatches - most of the work to one of the Documenters, which it selects through its - *_registry* dictionary. + A registry of Documenters and attrgetters. + + The *_registry* attribute is used to store registered Documenters. The *_special_attrgetters* attribute is used to customize ``getattr()`` calls that the Documenters make; its entries are of the form ``type: From 8bb6a01210ffc9994b4a2642545fb7b049655558 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 17 Dec 2017 02:21:10 +0900 Subject: [PATCH 123/275] Fix mark up --- doc/extdev/markupapi.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/extdev/markupapi.rst b/doc/extdev/markupapi.rst index 8a18e2306..6f289ed9f 100644 --- a/doc/extdev/markupapi.rst +++ b/doc/extdev/markupapi.rst @@ -125,7 +125,7 @@ Both APIs parse the content into a given node. They are used like this:: ``sphinx.util.docutils.switch_source_input()`` allows to change a target file during nested_parse. It is useful to mixture contents. For example, ``sphinx. - ext.autodoc`` uses it to parse docstrings. + ext.autodoc`` uses it to parse docstrings:: from sphinx.util.docutils import switch_source_input From c6775bce0778b76efa0bd525fba681ba239c2606 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vedran=20Mileti=C4=87?= Date: Thu, 5 Oct 2017 01:07:05 +0200 Subject: [PATCH 124/275] Add more EXAMPLES --- EXAMPLES | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/EXAMPLES b/EXAMPLES index 7c88805eb..0b2de95d9 100644 --- a/EXAMPLES +++ b/EXAMPLES @@ -34,6 +34,8 @@ Documentation using the alabaster theme * pytest: https://docs.pytest.org/ (customized) * python-apt: https://apt.alioth.debian.org/python-apt-doc/ * PyVisfile: https://documen.tician.de/pyvisfile/ +* Requests: http://www.python-requests.org/ +* searx: https://asciimoo.github.io/searx/ * Tablib: http://docs.python-tablib.org/ * urllib3: https://urllib3.readthedocs.io/ (customized) * Werkzeug: http://werkzeug.pocoo.org/docs/ (customized) @@ -46,6 +48,7 @@ Documentation using the classic theme * APSW: https://rogerbinns.github.io/apsw/ * Arb: http://arblib.org/ * Bazaar: http://doc.bazaar.canonical.com/ (customized) +* Beautiful Soup: https://www.crummy.com/software/BeautifulSoup/bs4/doc/ * Blender: https://docs.blender.org/api/current/ * Bugzilla: https://bugzilla.readthedocs.io/ * Buildbot: https://docs.buildbot.net/latest/ @@ -79,6 +82,8 @@ Documentation using the classic theme * Pyevolve: http://pyevolve.sourceforge.net/ * Pygame: https://www.pygame.org/docs/ (customized) * PyMQI: https://pythonhosted.org/pymqi/ +* PyQt4: http://pyqt.sourceforge.net/Docs/PyQt4/ (customized) +* PyQt5: http://pyqt.sourceforge.net/Docs/PyQt5/ (customized) * Python 2: https://docs.python.org/2/ * Python 3: https://docs.python.org/3/ (customized) * Python Packaging Authority: https://www.pypa.io/ (customized) @@ -121,11 +126,16 @@ Documentation using the nature theme * Alembic: http://alembic.zzzcomputing.com/ * Cython: http://docs.cython.org/ +* easybuild: https://easybuild.readthedocs.io/ * jsFiddle: http://doc.jsfiddle.net/ * libLAS: https://www.liblas.org/ (customized) +* Lmod: https://lmod.readthedocs.io/ * MapServer: http://mapserver.org/ (customized) +* Pandas: https://pandas.pydata.org/pandas-docs/stable/ +* pyglet: https://pyglet.readthedocs.io/ (customized) * Setuptools: https://setuptools.readthedocs.io/ * Spring Python: https://docs.spring.io/spring-python/1.2.x/sphinx/html/ +* StatsModels: http://www.statsmodels.org/ (customized) * Sylli: http://sylli.sourceforge.net/ Documentation using another builtin theme @@ -133,6 +143,7 @@ Documentation using another builtin theme * Breathe: https://breathe.readthedocs.io/ (haiku) * MPipe: https://vmlaker.github.io/mpipe/ (sphinx13) +* NLTK: http://www.nltk.org/ (agogo) * Programmieren mit PyGTK und Glade (German): http://www.florian-diesch.de/doc/python-und-glade/online/ (agogo, customized) * PyPubSub: https://pypubsub.readthedocs.io/ (bizstyle) @@ -150,8 +161,10 @@ Documentation using sphinx_rtd_theme * ASE: https://wiki.fysik.dtu.dk/ase/ * Autofac: http://docs.autofac.org/ * BigchainDB: https://docs.bigchaindb.com/ +* Blocks: https://blocks.readthedocs.io/ * bootstrap-datepicker: https://bootstrap-datepicker.readthedocs.io/ * Certbot: https://letsencrypt.readthedocs.io/ +* Chainer: https://docs.chainer.org/ (customized) * CherryPy: http://docs.cherrypy.org/ * Chainer: https://docs.chainer.org/ * CodeIgniter: https://www.codeigniter.com/user_guide/ @@ -178,14 +191,18 @@ Documentation using sphinx_rtd_theme * Idris: http://docs.idris-lang.org/ * javasphinx: https://bronto-javasphinx.readthedocs.io/ * Julia: https://julia.readthedocs.io/ +* Jupyter Notebook: https://jupyter-notebook.readthedocs.io/ +* Lasagne: https://lasagne.readthedocs.io/ * Linguistica: https://linguistica-uchicago.github.io/lxa5/ * Linux kernel: https://www.kernel.org/doc/html/latest/index.html * MathJax: https://docs.mathjax.org/ * MDTraj: http://mdtraj.org/latest/ (customized) * MICrobial Community Analysis (micca): http://micca.org/docs/latest/ * MicroPython: https://docs.micropython.org/ +* Minds: https://www.minds.org/docs/ (customized) * Mink: http://mink.behat.org/ * Mockery: http://docs.mockery.io/ +* mod_wsgi: https://modwsgi.readthedocs.io/ * MoinMoin: https://moin-20.readthedocs.io/ * Mopidy: https://docs.mopidy.com/ * MyHDL: http://docs.myhdl.org/ @@ -224,13 +241,16 @@ Documentation using sphinx_rtd_theme * Sylius: http://docs.sylius.org/ * Tango Controls: https://tango-controls.readthedocs.io/ (customized) * Topshelf: http://docs.topshelf-project.com/ +* Theano: http://www.deeplearning.net/software/theano/ * ThreatConnect: https://docs.threatconnect.com/ * Tuleap: https://tuleap.net/doc/en/ * TYPO3: https://docs.typo3.org/ (customized) +* uWSGI: https://uwsgi-docs.readthedocs.io/ * Wagtail: http://docs.wagtail.io/ * Web Application Attack and Audit Framework (w3af): http://docs.w3af.org/ * Weblate: https://docs.weblate.org/ * x265: https://x265.readthedocs.io/ +* ZeroNet: https://zeronet.readthedocs.io/ Documentation using sphinx_bootstrap_theme ------------------------------------------ @@ -245,12 +265,14 @@ Documentation using sphinx_bootstrap_theme * Open Dylan: https://opendylan.org/documentation/ * Pootle: http://docs.translatehouse.org/projects/pootle/ * PyUblas: https://documen.tician.de/pyublas/ +* seaborn: https://seaborn.pydata.org/ Documentation using a custom theme or integrated in a website ------------------------------------------------------------- * Apache Cassandra: https://cassandra.apache.org/doc/ * Astropy: http://docs.astropy.org/ +* Bokeh: https://bokeh.pydata.org/ * Boto 3: https://boto3.readthedocs.io/ * CakePHP: https://book.cakephp.org/ * CasperJS: http://docs.casperjs.org/ @@ -263,6 +285,7 @@ Documentation using a custom theme or integrated in a website * Enterprise Toolkit for Acrobat products: https://www.adobe.com/devnet-docs/acrobatetk/ * Gameduino: http://excamera.com/sphinx/gameduino/ +* gensim: https://radimrehurek.com/gensim/ * GeoServer: http://docs.geoserver.org/ * gevent: http://www.gevent.org/ * GHC - Glasgow Haskell Compiler: http://downloads.haskell.org/~ghc/master/users-guide/ @@ -307,6 +330,7 @@ Documentation using a custom theme or integrated in a website * Sulu: http://docs.sulu.io/ * SQLAlchemy: https://docs.sqlalchemy.org/ * tinyTiM: http://tinytim.sourceforge.net/docs/2.0/ +* Twisted: http://twistedmatrix.com/documents/current/ * Ubuntu Packaging Guide: http://packaging.ubuntu.com/html/ * WebFaction: https://docs.webfaction.com/ * WTForms: https://wtforms.readthedocs.io/ @@ -320,8 +344,10 @@ Homepages and other non-documentation sites * Benoit Boissinot: https://bboissin.appspot.com/ (classic, customized) * Computer Networks, Parallelization, and Simulation Laboratory (CNPSLab): https://lab.miletic.net/ (sphinx_rtd_theme) +* Deep Learning Tutorials: http://www.deeplearning.net/tutorial/ (sphinxdoc) * Loyola University Chicago COMP 339-439 Distributed Systems course: http://books.cs.luc.edu/distributedsystems/ (sphinx_bootstrap_theme) +* Pylearn2: http://www.deeplearning.net/software/pylearn2/ (sphinxdoc, customized) * SciPy Cookbook: https://scipy-cookbook.readthedocs.io/ (sphinx_rtd_theme) * The Wine Cellar Book: https://www.thewinecellarbook.com/doc/en/ (sphinxdoc) * Thomas Cokelaer's Python, Sphinx and reStructuredText tutorials: From 464f94c2380b4cb2600735c0c0085e771da2bce4 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 17 Dec 2017 15:25:44 +0900 Subject: [PATCH 125/275] deprecate formatargspec() and format_annotation() --- CHANGES | 2 ++ sphinx/ext/autodoc/inspector.py | 8 ++++++ tests/test_autodoc.py | 50 --------------------------------- 3 files changed, 10 insertions(+), 50 deletions(-) diff --git a/CHANGES b/CHANGES index ed76ea4a7..2ec7d56bb 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,8 @@ Deprecated * using a string value for :confval:`html_sidebars` is deprecated and only list values will be accepted at 2.0. +* ``format_annotation()`` and ``formatargspec()`` is deprecated. Please use + ``sphinx.util.inspect.Signature`` instead. Features added -------------- diff --git a/sphinx/ext/autodoc/inspector.py b/sphinx/ext/autodoc/inspector.py index 5d157c797..50c5a9082 100644 --- a/sphinx/ext/autodoc/inspector.py +++ b/sphinx/ext/autodoc/inspector.py @@ -10,9 +10,11 @@ """ import typing +import warnings from six import StringIO, string_types +from sphinx.deprecation import RemovedInSphinx20Warning from sphinx.util.inspect import object_description if False: @@ -29,6 +31,9 @@ def format_annotation(annotation): Displaying complex types from ``typing`` relies on its private API. """ + warnings.warn('format_annotation() is now deprecated. ' + 'Please use sphinx.util.inspect.Signature instead.', + RemovedInSphinx20Warning) if isinstance(annotation, typing.TypeVar): # type: ignore return annotation.__name__ if annotation == Ellipsis: @@ -107,6 +112,9 @@ def formatargspec(function, args, varargs=None, varkw=None, defaults=None, An enhanced version of ``inspect.formatargspec()`` that handles typing annotations better. """ + warnings.warn('formatargspec() is now deprecated. ' + 'Please use sphinx.util.inspect.Signature instead.', + RemovedInSphinx20Warning) def format_arg_with_annotation(name): # type: (str) -> str diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index 11958800a..989c367b6 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -1108,53 +1108,3 @@ class EnumCls(enum.Enum): val2 = 23 #: doc for val2 val3 = 34 """doc for val3""" - - -def test_type_hints(): - from sphinx.ext.autodoc import formatargspec - from sphinx.util.inspect import getargspec - - try: - from typing_test_data import f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11 - except (ImportError, SyntaxError): - pytest.skip('Cannot import Python code with function annotations') - - def verify_arg_spec(f, expected): - assert formatargspec(f, *getargspec(f)) == expected - - # Class annotations - verify_arg_spec(f0, '(x: int, y: numbers.Integral) -> None') - - # Generic types with concrete parameters - verify_arg_spec(f1, '(x: typing.List[int]) -> typing.List[int]') - - # TypeVars and generic types with TypeVars - verify_arg_spec(f2, '(x: typing.List[T],' - ' y: typing.List[T_co],' - ' z: T) -> typing.List[T_contra]') - - # Union types - verify_arg_spec(f3, '(x: typing.Union[str, numbers.Integral]) -> None') - - # Quoted annotations - verify_arg_spec(f4, '(x: str, y: str) -> None') - - # Keyword-only arguments - verify_arg_spec(f5, '(x: int, *, y: str, z: str) -> None') - - # Keyword-only arguments with varargs - verify_arg_spec(f6, '(x: int, *args, y: str, z: str) -> None') - - # Space around '=' for defaults - verify_arg_spec(f7, '(x: int = None, y: dict = {}) -> None') - - # Callable types - verify_arg_spec(f8, '(x: typing.Callable[[int, str], int]) -> None') - verify_arg_spec(f9, '(x: typing.Callable) -> None') - - # Tuple types - verify_arg_spec(f10, '(x: typing.Tuple[int, str],' - ' y: typing.Tuple[int, ...]) -> None') - - # Instance annotations - verify_arg_spec(f11, '(x: CustomAnnotation, y: 123) -> None') From 41f9cb200acfa506b8cebed37841fa39a625a719 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 17 Dec 2017 23:44:28 +0900 Subject: [PATCH 126/275] Fix doc: now eq role works whole of project --- doc/ext/math.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/ext/math.rst b/doc/ext/math.rst index 2aad7853f..66c24e902 100644 --- a/doc/ext/math.rst +++ b/doc/ext/math.rst @@ -102,8 +102,7 @@ or use Python raw strings (``r"raw"``). .. rst:role:: eq - Role for cross-referencing equations via their label. This currently works - only within the same document. Example:: + Role for cross-referencing equations via their label. Example:: .. math:: e^{i\pi} + 1 = 0 :label: euler From 109e01d94b7a9db338b4b0c5eea24aedffa7d245 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 18 Dec 2017 00:59:00 +0900 Subject: [PATCH 127/275] Fix mypy violations --- sphinx/ext/autodoc/__init__.py | 6 ++++-- sphinx/ext/autosummary/__init__.py | 8 ++++---- sphinx/util/docutils.py | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 45195ff41..150620a62 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -19,7 +19,6 @@ import warnings from six import PY2, iterkeys, iteritems, itervalues, text_type, class_types, string_types -from docutils.parsers.rst import Directive from docutils.statemachine import ViewList import sphinx @@ -41,7 +40,10 @@ if False: # For type annotation from types import ModuleType # NOQA from typing import Any, Callable, Dict, Iterator, List, Sequence, Set, Tuple, Type, Union # NOQA + from docutils import nodes # NOQA + from docutils.utils import Reporter # NOQA from sphinx.application import Sphinx # NOQA + from sphinx.ext.autodoc.directive import DocumenterBridge # NOQA logger = logging.getLogger(__name__) @@ -271,7 +273,7 @@ class Documenter(object): raise NotImplementedError('must be implemented in subclasses') def __init__(self, directive, name, indent=u''): - # type: (Directive, unicode, unicode) -> None + # type: (DocumenterBridge, unicode, unicode) -> None self.directive = directive self.env = directive.env self.options = directive.genopt diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index b56f649bf..3294709ad 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -72,7 +72,7 @@ from sphinx import addnodes from sphinx.environment.adapters.toctree import TocTree from sphinx.util import import_object, rst, logging from sphinx.pycode import ModuleAnalyzer, PycodeError -from sphinx.ext.autodoc.directive import Options +from sphinx.ext.autodoc.directive import DocumenterBridge, Options from sphinx.ext.autodoc.importer import import_module if False: @@ -153,9 +153,9 @@ def autosummary_table_visit_html(self, node): # -- autodoc integration ------------------------------------------------------- -class FakeDirective(object): - env = {} # type: Dict - genopt = Options() +class FakeDirective(DocumenterBridge): + def __init__(self): + super(FakeDirective, self).__init__({}, None, Options(), 0) # type: ignore def get_documenter(obj, parent): diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index f4dd96158..5377e493c 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -31,7 +31,7 @@ report_re = re.compile('^(.+?:(?:\\d+)?): \\((DEBUG|INFO|WARNING|ERROR|SEVERE)/( if False: # For type annotation - from typing import Any, Callable, Dict, Iterator, List, Tuple # NOQA + from typing import Any, Callable, Dict, Generator, Iterator, List, Tuple # NOQA from docutils import nodes # NOQA from docutils.statemachine import State # NOQA from sphinx.environment import BuildEnvironment # NOQA @@ -221,7 +221,7 @@ def directive_helper(obj, has_content=None, argument_spec=None, option_spec=None @contextmanager def switch_source_input(state, content): - # type: (State, ViewList) -> None + # type: (State, ViewList) -> Generator """Switch current source input of state temporarily.""" try: # remember the original ``get_source_and_line()`` method From 46b18962283d4ed7cab4e87a737ab9001d6933aa Mon Sep 17 00:00:00 2001 From: jfbu Date: Sun, 17 Dec 2017 17:56:03 +0100 Subject: [PATCH 128/275] Again rewording docs about numfig_secnum_depth --- doc/config.rst | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/doc/config.rst b/doc/config.rst index fc87c4ddc..8f4656060 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -335,14 +335,21 @@ General configuration .. confval:: numfig_secnum_depth - The scope for numbering: ``0`` means "continuous numbering", - ``1`` means "reset per section" - (i.e. numbers will be x.1, x.2, x.3 ... with x the section number, - assuming that the :rst:dir:`toctree` directive was used with its option - ``:numbered:``), - ``2`` means "per subsection" - (i.e. numbers will be x.y.1, x.y.2, ...), - and so on. Default is ``1``. + - if set to ``0``, figures, tables and code-blocks are continuously numbered + starting at ``1``. + - if ``1`` (default) numbers will be ``x.1``, ``x.2``, ... with ``x`` + the section number (top level sectioning; no ``x.`` if no section). + This naturally applies only if section numbering has been activated via + the ``:numbered:`` option of the :rst:dir:`toctree` directive. + - ``2`` means that numbers will be ``x.y.1``, ``x.y.2``, ... if located in + a sub-section (but still ``x.1``, ``x.2``, ... if located directly under a + section and ``1``, ``2``, ... if not in any top level section.) + - etc... + + .. note:: + + The LaTeX builder currently ignores this configuration setting. It will + obey it at Sphinx 1.7. .. versionadded:: 1.3 From 27285dfeed9f732727be7500335e34b8434a4478 Mon Sep 17 00:00:00 2001 From: Oliver Jahn Date: Sun, 17 Dec 2017 13:56:06 -0500 Subject: [PATCH 129/275] use :rst:role: markup --- doc/ext/math.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ext/math.rst b/doc/ext/math.rst index 5fdf842ee..6dddd7ece 100644 --- a/doc/ext/math.rst +++ b/doc/ext/math.rst @@ -48,9 +48,9 @@ or use Python raw strings (``r"raw"``). If ``True``, displayed math equations are numbered across pages in html and related (epub, ...) output. The :confval:`numfig` config value must be - enabled and :confval:`numfig_secnum_depth` is respected. The ``:eq:`` role - must be used to reference equation numbers, not the ``:numref:`` role. - Default is ``False``. + enabled and :confval:`numfig_secnum_depth` is respected. The :rst:role:`eq` + role must be used to reference equation numbers, not the :rst:role:`numref` + role. Default is ``False``. :mod:`.mathbase` defines these new markup elements: From 56d4e0c80d8c63b409ed33e2bf241bdc05ef9d64 Mon Sep 17 00:00:00 2001 From: Oliver Jahn Date: Sun, 17 Dec 2017 14:02:32 -0500 Subject: [PATCH 130/275] make math_numfig default to True --- doc/ext/math.rst | 8 ++++---- sphinx/ext/mathbase.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/ext/math.rst b/doc/ext/math.rst index 6dddd7ece..fe0baefea 100644 --- a/doc/ext/math.rst +++ b/doc/ext/math.rst @@ -47,10 +47,10 @@ or use Python raw strings (``r"raw"``). .. confval:: math_numfig If ``True``, displayed math equations are numbered across pages in html and - related (epub, ...) output. The :confval:`numfig` config value must be - enabled and :confval:`numfig_secnum_depth` is respected. The :rst:role:`eq` - role must be used to reference equation numbers, not the :rst:role:`numref` - role. Default is ``False``. + related (epub, ...) output when :confval:`numfig` is enabled. + :confval:`numfig_secnum_depth` is respected. The :rst:role:`eq` role must + be used to reference equation numbers, not the :rst:role:`numref` role. + Default is ``True``. :mod:`.mathbase` defines these new markup elements: diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py index 5f353ac9c..50c4b157f 100644 --- a/sphinx/ext/mathbase.py +++ b/sphinx/ext/mathbase.py @@ -365,7 +365,7 @@ def setup_math(app, htmlinlinevisitors, htmldisplayvisitors): # type: (Sphinx, Tuple[Callable, Any], Tuple[Callable, Any]) -> None app.add_config_value('math_number_all', False, 'env') app.add_config_value('math_eqref_format', None, 'env', string_classes) - app.add_config_value('math_numfig', False, 'env') + app.add_config_value('math_numfig', True, 'env') app.add_domain(MathDomain) app.add_node(math, override=True, latex=(latex_visit_math, None), From af46ed16b023ad2b4a2ff4c71b57f638ce7ca363 Mon Sep 17 00:00:00 2001 From: jfbu Date: Mon, 18 Dec 2017 00:26:36 +0100 Subject: [PATCH 131/275] Fixes #4315: latex_toplevel_sectioning induced \chapter in article class --- sphinx/writers/latex.py | 45 +++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 2c2b62659..39c7bc81e 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -48,6 +48,8 @@ BEGIN_DOC = r''' URI_SCHEMES = ('mailto:', 'http:', 'https:', 'ftp:') SECNUMDEPTH = 3 +LATEXSECTIONNAMES = ["part", "chapter", "section", "subsection", + "subsubsection", "paragraph", "subparagraph"] DEFAULT_SETTINGS = { 'latex_engine': 'pdflatex', @@ -501,8 +503,6 @@ def rstdim_to_latexdim(width_str): class LaTeXTranslator(nodes.NodeVisitor): - sectionnames = ["part", "chapter", "section", "subsection", - "subsubsection", "paragraph", "subparagraph"] ignore_missing_images = False @@ -532,16 +532,6 @@ class LaTeXTranslator(nodes.NodeVisitor): self.compact_list = 0 self.first_param = 0 - # determine top section level - if builder.config.latex_toplevel_sectioning: - self.top_sectionlevel = \ - self.sectionnames.index(builder.config.latex_toplevel_sectioning) - else: - if document.settings.docclass == 'howto': - self.top_sectionlevel = 2 - else: - self.top_sectionlevel = 1 - # sort out some elements self.elements = DEFAULT_SETTINGS.copy() self.elements.update(ADDITIONAL_SETTINGS.get(builder.config.latex_engine, {})) @@ -564,11 +554,30 @@ class LaTeXTranslator(nodes.NodeVisitor): }) if builder.config.latex_keep_old_macro_names: self.elements['sphinxpkgoptions'] = '' + + # we assume LaTeX class provides \chapter command except in case + # of non-Japanese 'howto' case + self.sectionnames = LATEXSECTIONNAMES[:] if document.settings.docclass == 'howto': docclass = builder.config.latex_docclass.get('howto', 'article') + if docclass[0] == 'j': # Japanese class... + pass + else: + self.sectionnames.remove('chapter') else: docclass = builder.config.latex_docclass.get('manual', 'report') self.elements['docclass'] = docclass + + # determine top section level + self.top_sectionlevel = 1 + if builder.config.latex_toplevel_sectioning: + try: + self.top_sectionlevel = \ + self.sectionnames.index(builder.config.latex_toplevel_sectioning) + except ValueError: + logger.warning('unknown %r toplevel_sectioning for class %r' % + (builder.config.latex_toplevel_sectioning, docclass)) + if builder.config.today: self.elements['date'] = builder.config.today else: @@ -631,21 +640,23 @@ class LaTeXTranslator(nodes.NodeVisitor): usepackages = (declare_package(*p) for p in builder.usepackages) self.elements['usepackages'] += "\n".join(usepackages) if document.get('tocdepth'): - # redece tocdepth if `part` or `chapter` is used for top_sectionlevel + # reduce tocdepth if `part` or `chapter` is used for top_sectionlevel # tocdepth = -1: show only parts # tocdepth = 0: show parts and chapters # tocdepth = 1: show parts, chapters and sections # tocdepth = 2: show parts, chapters, sections and subsections # ... + tocdepth = document['tocdepth'] + self.top_sectionlevel - 2 - maxdepth = len(self.sectionnames) - self.top_sectionlevel - if tocdepth > maxdepth: + if len(self.sectionnames) < 7 and self.top_sectionlevel > 0: + tocdepth += 1 # because top_sectionlevel is shifted by -1 + if tocdepth > 5: # 5 corresponds to subparagraph logger.warning('too large :maxdepth:, ignored.') - tocdepth = maxdepth + tocdepth = 5 self.elements['tocdepth'] = '\\setcounter{tocdepth}{%d}' % tocdepth if tocdepth >= SECNUMDEPTH: - # Increase secnumdepth if tocdepth is depther than default SECNUMDEPTH + # Increase secnumdepth if tocdepth is deeper than default SECNUMDEPTH self.elements['secnumdepth'] = '\\setcounter{secnumdepth}{%d}' % tocdepth if getattr(document.settings, 'contentsname', None): From 245876c6e7917f315857ee59e4c456959f4e6e5c Mon Sep 17 00:00:00 2001 From: jfbu Date: Mon, 18 Dec 2017 08:13:28 +0100 Subject: [PATCH 132/275] Add test for latex_toplevel_sectioning --- tests/roots/test-latex-toplevel/conf.py | 12 ++++++++++++ tests/roots/test-latex-toplevel/index.rst | 8 ++++++++ tests/roots/test-latex-toplevel/indexhowto.rst | 10 ++++++++++ tests/roots/test-latex-toplevel/indexmanual.rst | 13 +++++++++++++ tests/test_build_latex.py | 14 ++++++++++++++ 5 files changed, 57 insertions(+) create mode 100644 tests/roots/test-latex-toplevel/conf.py create mode 100644 tests/roots/test-latex-toplevel/index.rst create mode 100644 tests/roots/test-latex-toplevel/indexhowto.rst create mode 100644 tests/roots/test-latex-toplevel/indexmanual.rst diff --git a/tests/roots/test-latex-toplevel/conf.py b/tests/roots/test-latex-toplevel/conf.py new file mode 100644 index 000000000..88efc87ed --- /dev/null +++ b/tests/roots/test-latex-toplevel/conf.py @@ -0,0 +1,12 @@ +# -*- coding: utf-8 -*- + +master_doc = 'index' + +latex_toplevel_sectioning = 'part' + +latex_documents = [ + ('indexmanual', 'SphinxManual.tex', 'Test toplevel manual', + 'Sphinx', 'manual'), + ('indexhowto', 'SphinxHowTo.tex', 'Test toplevel howto', + 'Sphinx', 'howto'), +] diff --git a/tests/roots/test-latex-toplevel/index.rst b/tests/roots/test-latex-toplevel/index.rst new file mode 100644 index 000000000..833bc67bb --- /dev/null +++ b/tests/roots/test-latex-toplevel/index.rst @@ -0,0 +1,8 @@ +=================== +test-latex-toplevel +=================== + +.. toctree:: + + indexmanual + indexhowto diff --git a/tests/roots/test-latex-toplevel/indexhowto.rst b/tests/roots/test-latex-toplevel/indexhowto.rst new file mode 100644 index 000000000..7c0c92d1a --- /dev/null +++ b/tests/roots/test-latex-toplevel/indexhowto.rst @@ -0,0 +1,10 @@ +========================= +test-latex-toplevel-howto +========================= + +This is a part +============== + +This is a section +----------------- + diff --git a/tests/roots/test-latex-toplevel/indexmanual.rst b/tests/roots/test-latex-toplevel/indexmanual.rst new file mode 100644 index 000000000..2181b1426 --- /dev/null +++ b/tests/roots/test-latex-toplevel/indexmanual.rst @@ -0,0 +1,13 @@ +========================== +test-latex-toplevel-manual +========================== + +First part +========== + +This is chapter +--------------- + +This is section +~~~~~~~~~~~~~~~ + diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index b1ba73730..edaf107c4 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -1039,3 +1039,17 @@ def test_latex_image_in_parsed_literal(app, status, warning): assert ('{\\sphinxunactivateextrasandspace \\raisebox{-0.5\\height}' '{\\scalebox{2.000000}{\\sphinxincludegraphics[height=1cm]{{pic}.png}}}' '}AFTER') in result + + +@pytest.mark.sphinx('latex', testroot='latex-toplevel') +def test_latex_toplevel_is_part(app, status, warning): + app.builder.build_all() + + result = (app.outdir / 'SphinxManual.tex').text(encoding='utf8') + assert ('\\part{First part}') in result + assert ('\\chapter{This is chapter}') in result + assert ('\\section{This is section}') in result + + result = (app.outdir / 'SphinxHowTo.tex').text(encoding='utf8') + assert ('\\part{This is a part}') in result + assert ('\\section{This is a section}') in result From 72bffcf0f4bb81fe934c1065d27c8bff1e510fe9 Mon Sep 17 00:00:00 2001 From: jfbu Date: Mon, 18 Dec 2017 11:15:51 +0100 Subject: [PATCH 133/275] Add precision to docs of latex_toplevel_sectioning --- doc/config.rst | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/config.rst b/doc/config.rst index 8f4656060..1f222451d 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -1617,10 +1617,15 @@ These options influence LaTeX output. See further :doc:`latex`. .. confval:: latex_toplevel_sectioning This value determines the topmost sectioning unit. It should be chosen from - ``part``, ``chapter`` or ``section``. The default is ``None``; the topmost - sectioning unit is switched by documentclass. ``section`` is used if + ``'part'``, ``'chapter'`` or ``'section'``. The default is ``None``; + the topmost + sectioning unit is switched by documentclass: ``section`` is used if documentclass will be ``howto``, otherwise ``chapter`` will be used. + Note that if LaTeX uses ``\part`` command, then the numbering of sectioning + units one level deep gets off-sync with HTML numbering, because LaTeX + numbers continuously ``\chapter`` (or ``\section`` for ``howto``.) + .. versionadded:: 1.4 .. confval:: latex_appendices From 9a392952917b5bbd560accde1037e4e7c955e96d Mon Sep 17 00:00:00 2001 From: Oliver Jahn Date: Mon, 18 Dec 2017 06:41:50 -0500 Subject: [PATCH 134/275] add version --- doc/ext/math.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/ext/math.rst b/doc/ext/math.rst index fe0baefea..de7ff485b 100644 --- a/doc/ext/math.rst +++ b/doc/ext/math.rst @@ -52,6 +52,8 @@ or use Python raw strings (``r"raw"``). be used to reference equation numbers, not the :rst:role:`numref` role. Default is ``True``. + .. versionadded:: 1.7 + :mod:`.mathbase` defines these new markup elements: .. rst:role:: math From a102e8e29b23e08fb779c8153f03beb6fa8fe196 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sat, 21 Oct 2017 12:19:04 +0100 Subject: [PATCH 135/275] setup.py: Include 'flake8' in 'test' requirements We are using this in our testing and actually need it for the flake8 plugin, so include this in the list of 'test' requirements. Signed-off-by: Stephen Finucane --- .travis.yml | 1 - setup.py | 1 + tox.ini | 1 - 3 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1d065b178..a5214057d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,7 +39,6 @@ install: - pip install -U pip setuptools - pip install docutils==$DOCUTILS - pip install .[test,websupport] - - pip install flake8 - if [[ $TRAVIS_PYTHON_VERSION == '3.6' ]]; then python3.6 -m pip install mypy typed-ast; fi script: - flake8 diff --git a/setup.py b/setup.py index 10a513166..5c0b70959 100644 --- a/setup.py +++ b/setup.py @@ -72,6 +72,7 @@ extras_require = { 'pytest', 'pytest-cov', 'html5lib', + 'flake8', ], 'test:python_version<"3"': [ 'enum34', diff --git a/tox.ini b/tox.ini index 00b3c99e2..2ea05641b 100644 --- a/tox.ini +++ b/tox.ini @@ -38,7 +38,6 @@ deps= {[testenv]deps} [testenv:flake8] -deps=flake8 commands=flake8 [testenv:pylint] From 41c19ddf91018e2b9a8c0001a24a78f3ecb893be Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Mon, 2 Oct 2017 22:28:22 +0100 Subject: [PATCH 136/275] tests: Skip tests with missing binaries While there are already some skips included here, they clearly aren't doing their job and the test fail locally. Resolve this. Signed-off-by: Stephen Finucane --- tests/test_ext_math.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/test_ext_math.py b/tests/test_ext_math.py index 92501a3db..4d2fb9836 100644 --- a/tests/test_ext_math.py +++ b/tests/test_ext_math.py @@ -9,11 +9,25 @@ :license: BSD, see LICENSE for details. """ +import os import re +import subprocess import pytest +def has_binary(binary): + try: + subprocess.check_output([binary]) + except OSError as e: + if e.errno == os.errno.ENOENT: + # handle file not found error. + return False + else: + return True + return True + + @pytest.mark.sphinx( 'html', testroot='ext-math', confoverrides = {'extensions': ['sphinx.ext.jsmath'], 'jsmath_path': 'dummy.js'}) @@ -34,6 +48,8 @@ def test_jsmath(app, status, warning): assert '

\na + 1 < b
' in content +@pytest.mark.skipif(not has_binary('dvipng'), + reason='Requires dvipng" binary') @pytest.mark.sphinx('html', testroot='ext-math-simple', confoverrides = {'extensions': ['sphinx.ext.imgmath']}) def test_imgmath_png(app, status, warning): @@ -49,6 +65,8 @@ def test_imgmath_png(app, status, warning): assert re.search(html, content, re.S) +@pytest.mark.skipif(not has_binary('dvisvgm'), + reason='Requires dvisvgm" binary') @pytest.mark.sphinx('html', testroot='ext-math-simple', confoverrides={'extensions': ['sphinx.ext.imgmath'], 'imgmath_image_format': 'svg'}) From e243e827236467b67b057b83131248ef1742aacb Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 26 Oct 2017 16:49:44 +0100 Subject: [PATCH 137/275] tests: Ignore tests using 'collect_ignore' Per the pytest docs [1], this is the preferred way to ignore tests. This necessitates removing the 'test-async' target as it no longer makes any sense. [1] https://docs.pytest.org/en/latest/example/pythoncollection.html Signed-off-by: Stephen Finucane --- .travis.yml | 2 +- Makefile | 4 ++-- tests/conftest.py | 5 +++++ tox.ini | 15 ++------------- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index a5214057d..1d6694b3d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,5 +42,5 @@ install: - if [[ $TRAVIS_PYTHON_VERSION == '3.6' ]]; then python3.6 -m pip install mypy typed-ast; fi script: - flake8 - - if [[ $TRAVIS_PYTHON_VERSION == '3.6' ]]; then make type-check test-async; fi + - if [[ $TRAVIS_PYTHON_VERSION == '3.6' ]]; then make type-check test; fi - if [[ $TRAVIS_PYTHON_VERSION != '3.6' ]]; then make test; fi diff --git a/Makefile b/Makefile index 5b3d5aad4..e4abba088 100644 --- a/Makefile +++ b/Makefile @@ -69,11 +69,11 @@ reindent: .PHONY: test test: - @cd tests; $(PYTHON) run.py --ignore py35 -v $(TEST) + @cd tests; $(PYTHON) run.py -v $(TEST) .PHONY: test-async test-async: - @cd tests; $(PYTHON) run.py -v $(TEST) + @echo "This target no longer does anything and will be removed imminently" .PHONY: covertest covertest: diff --git a/tests/conftest.py b/tests/conftest.py index 28dbd6ed4..c9719bf80 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,12 +8,17 @@ """ import os +import sys import pytest from sphinx.testing.path import path pytest_plugins = 'sphinx.testing.fixtures' +# Disable Python version-specific +if sys.version_info < (3, 5): + collect_ignore = ['py35'] + @pytest.fixture(scope='session') def rootdir(): diff --git a/tox.ini b/tox.ini index 2ea05641b..051b56381 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion=2.0 -envlist=flake8,mypy,py{27,34,35,36},pypy,du{11,12,13,14} +envlist=docs,flake8,mypy,py{27,34,35,36},pypy,du{11,12,13,14} [testenv] passenv = https_proxy http_proxy no_proxy @@ -13,9 +13,7 @@ deps = setenv = SPHINX_TEST_TEMPDIR = {envdir}/testbuild commands= - {envpython} -Wall tests/run.py --ignore tests/py35 --cov=sphinx \ - --durations 25 {posargs} - sphinx-build -q -W -b html -d {envtmpdir}/doctrees doc {envtmpdir}/html + {envpython} -Wall tests/run.py --cov sphinx --durations 25 {posargs} [testenv:du11] deps= @@ -47,15 +45,6 @@ deps= commands= pylint --rcfile utils/pylintrc sphinx -[testenv:py27] -deps= - {[testenv]deps} - -[testenv:py35] -commands= - {envpython} -Wall tests/run.py --cov=sphinx --durations 25 {posargs} - sphinx-build -q -W -b html -d {envtmpdir}/doctrees doc {envtmpdir}/html - [testenv:mypy] basepython=python3 deps= From c8d56236c9286adca9664782debf3b1c768ef92d Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 26 Oct 2017 16:59:46 +0100 Subject: [PATCH 138/275] tests: Ignore roots using 'collect_ignore' This is slightly cleaner than how we're doing this at the moment. Signed-off-by: Stephen Finucane --- tests/conftest.py | 5 ++++- tests/run.py | 11 +---------- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index c9719bf80..9ea99dbd9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -15,9 +15,12 @@ from sphinx.testing.path import path pytest_plugins = 'sphinx.testing.fixtures' +# Exclude 'roots' dirs for pytest test collector +collect_ignore = ['roots'] + # Disable Python version-specific if sys.version_info < (3, 5): - collect_ignore = ['py35'] + collect_ignore += ['py35'] @pytest.fixture(scope='session') diff --git a/tests/run.py b/tests/run.py index a8439ba02..2116e345c 100755 --- a/tests/run.py +++ b/tests/run.py @@ -55,14 +55,5 @@ os.makedirs(tempdir) print('Running Sphinx test suite (with Python %s)...' % sys.version.split()[0]) sys.stdout.flush() -# exclude 'roots' dirs for pytest test collector -ignore_paths = [ - os.path.relpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), sub)) - for sub in ('roots',) -] -args = sys.argv[1:] -for ignore_path in ignore_paths: - args.extend(['--ignore', ignore_path]) - import pytest # NOQA -sys.exit(pytest.main(args)) +sys.exit(pytest.main(sys.argv[1:])) From 5d812ccefc034e8cc93223454f3e6fa36528546a Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 26 Oct 2017 18:11:13 +0100 Subject: [PATCH 139/275] tox: Add 'coverage' target Enabling coverage results in an increase in runtime, and while this may be an acceptable compromise for some developers, it's not necessarily something we need to run all the time. Move it to a separate target so it can be run only by those who wish to use it. Signed-off-by: Stephen Finucane --- tox.ini | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 051b56381..05074761e 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion=2.0 -envlist=docs,flake8,mypy,py{27,34,35,36},pypy,du{11,12,13,14} +envlist=docs,flake8,mypy,coverage,py{27,34,35,36,py},du{11,12,13,14} [testenv] passenv = https_proxy http_proxy no_proxy @@ -12,8 +12,9 @@ deps = .[test,websupport] setenv = SPHINX_TEST_TEMPDIR = {envdir}/testbuild + coverage: PYTEST_ADDOPTS = --cov sphinx commands= - {envpython} -Wall tests/run.py --cov sphinx --durations 25 {posargs} + {envpython} -Wall tests/run.py --durations 25 {posargs} [testenv:du11] deps= From fd1df0815b8fd83cd7918a9fcf5eea734161f336 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 27 Oct 2017 10:11:10 +0100 Subject: [PATCH 140/275] tox: Make further use of factor-conditional deps This is how we reduce boilerplate [1]. Succinctness FTW. [1] https://tox.readthedocs.io/en/latest/config.html#factors-and-factor-conditional-settings Signed-off-by: Stephen Finucane --- tox.ini | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/tox.ini b/tox.ini index 05074761e..22a34f6f8 100644 --- a/tox.ini +++ b/tox.ini @@ -10,32 +10,16 @@ passenv = https_proxy http_proxy no_proxy # https://tox.readthedocs.io/en/latest/config.html#confval-extras=MULTI-LINE-LIST deps = .[test,websupport] + du11: docutils==0.11 + du12: docutils==0.12 + du13: docutils==0.13.1 + du14: docutils==0.14 setenv = SPHINX_TEST_TEMPDIR = {envdir}/testbuild coverage: PYTEST_ADDOPTS = --cov sphinx commands= {envpython} -Wall tests/run.py --durations 25 {posargs} -[testenv:du11] -deps= - docutils==0.11 - {[testenv]deps} - -[testenv:du12] -deps= - docutils==0.12 - {[testenv]deps} - -[testenv:du13] -deps= - docutils==0.13.1 - {[testenv]deps} - -[testenv:du14] -deps= - docutils==0.14 - {[testenv]deps} - [testenv:flake8] commands=flake8 From f74b6756ac80e7a07f2b7c8a7f304e245404c116 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sat, 21 Oct 2017 14:19:28 +0100 Subject: [PATCH 141/275] setup.cfg: Restructure file Place configuration of the package itself first in the file, followed by configuration of other tools. Signed-off-by: Stephen Finucane --- setup.cfg | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/setup.cfg b/setup.cfg index cb6887fc3..00e7833d3 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,11 +1,20 @@ +[metadata] +license_file = LICENSE + [egg_info] tag_build = .dev tag_date = true +[bdist_wheel] +universal = 1 + [aliases] release = egg_info -Db '' upload = upload --sign --identity=36580288 +[build_sphinx] +warning-is-error = 1 + [extract_messages] mapping_file = babel.cfg output_file = sphinx/locale/sphinx.pot @@ -20,12 +29,6 @@ output_dir = sphinx/locale/ domain = sphinx directory = sphinx/locale/ -[bdist_wheel] -universal = 1 - -[metadata] -license_file = LICENSE - [flake8] max-line-length = 95 ignore = E116,E241,E251,E741 @@ -40,6 +43,3 @@ follow_imports = skip incremental = True check_untyped_defs = True warn_unused_ignores = True - -[build_sphinx] -warning-is-error = 1 From 393f59da004baaac3a4d1f03a0b4585ed71f76f7 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sat, 21 Oct 2017 15:20:21 +0100 Subject: [PATCH 142/275] Improve README We're going to be adding additional badges to this but, before we do that, we should improve the README and remove a lot of the duplication that has built up here. The 'long_description' from 'setup.py' is moved into the README as there is serious value in displaying this on GitHub, as much as there is value in including the badges and other content from README. Signed-off-by: Stephen Finucane --- README.rst | 111 +++++++++++++++++++++++++++++------------------------ setup.py | 30 +-------------- 2 files changed, 63 insertions(+), 78 deletions(-) diff --git a/README.rst b/README.rst index 1e027ec8e..54493bb8b 100644 --- a/README.rst +++ b/README.rst @@ -1,3 +1,7 @@ +======== + Sphinx +======== + .. image:: https://img.shields.io/pypi/v/sphinx.svg :target: https://pypi.python.org/pypi/Sphinx .. image:: https://readthedocs.org/projects/sphinx/badge/ @@ -6,40 +10,81 @@ .. image:: https://travis-ci.org/sphinx-doc/sphinx.svg?branch=master :target: https://travis-ci.org/sphinx-doc/sphinx -================= -README for Sphinx -================= +Sphinx is a tool that makes it easy to create intelligent and beautiful +documentation for Python projects (or other documents consisting of multiple +reStructuredText sources), written by Georg Brandl. It was originally created +for the new Python documentation, and has excellent facilities for Python +project documentation, but C/C++ is supported as well, and more languages are +planned. -This is the Sphinx documentation generator, see http://www.sphinx-doc.org/. +Sphinx uses reStructuredText as its markup language, and many of its strengths +come from the power and straightforwardness of reStructuredText and its parsing +and translating suite, the Docutils. +Among its features are the following: -Installing -========== +* Output formats: HTML (including derivative formats such as HTML Help, Epub + and Qt Help), plain text, manual pages and LaTeX or direct PDF output + using rst2pdf +* Extensive cross-references: semantic markup and automatic links + for functions, classes, glossary terms and similar pieces of information +* Hierarchical structure: easy definition of a document tree, with automatic + links to siblings, parents and children +* Automatic indices: general index as well as a module index +* Code handling: automatic highlighting using the Pygments highlighter +* Flexible HTML output using the Jinja 2 templating engine +* Various extensions are available, e.g. for automatic testing of snippets + and inclusion of appropriately formatted docstrings +* Setuptools integration -Install from PyPI to use stable version:: +For more information, refer to the `the documentation`__. + +__ http://www.sphinx-doc.org/ + +Installation +============ + +Sphinx is published on `PyPI`__ and can be installed from there:: pip install -U sphinx -Install from PyPI to use beta version:: +We also publish beta releases:: pip install -U --pre sphinx -Install from newest dev version in stable branch:: +If you wish to install `Sphinx` for development purposes, refer to `the +contributors guide`__. - pip install git+https://github.com/sphinx-doc/sphinx@stable +__ https://pypi.python.org/pypi/Sphinx +__ CONTRIBUTING.rst -Install from newest dev version in master branch:: +Documentation +============= - pip install git+https://github.com/sphinx-doc/sphinx +Documentation is available from `sphinx-doc.org`__. -Install from cloned source:: +__ http://www.sphinx-doc.org/ - pip install . +Testing +======= -Install from cloned source as editable:: +Continuous testing is provided by `Travis`__ (for unit tests and style checks +on Linux), `AppVeyor`__ (for unit tests on Windows), and `CircleCI`__ (for +large processes like TeX compilation). - pip install -e . +For information on running tests locally, refer to `the contributors guide`__. +__ https://travis-ci.org/sphinx-doc/sphinx +__ https://ci.appveyor.com/project/sphinxdoc/sphinx +__ https://circleci.com/gh/sphinx-doc/sphinx +__ CONTRIBUTING.rst + +Contributing +============ + +Refer to `the contributors guide`_. + +__ CONTRIBUTING.rst Release signatures ================== @@ -48,37 +93,3 @@ Releases are signed with following keys: * `498D6B9E `_ * `5EBA0E07 `_ - -Reading the docs -================ - -You can read them online at . - -Or, after installing:: - - cd doc - make html - -Then, direct your browser to ``_build/html/index.html``. - -Testing -======= - -To run the tests with the interpreter available as ``python``, use:: - - make test - -If you want to use a different interpreter, e.g. ``python3``, use:: - - PYTHON=python3 make test - -Continuous testing runs on travis: https://travis-ci.org/sphinx-doc/sphinx - - -Contributing -============ - -See `CONTRIBUTING.rst`__ - -.. __: CONTRIBUTING.rst - diff --git a/setup.py b/setup.py index 5c0b70959..6b7de9129 100644 --- a/setup.py +++ b/setup.py @@ -8,34 +8,8 @@ from distutils.cmd import Command import sphinx -long_desc = ''' -Sphinx is a tool that makes it easy to create intelligent and beautiful -documentation for Python projects (or other documents consisting of multiple -reStructuredText sources), written by Georg Brandl. It was originally created -for the new Python documentation, and has excellent facilities for Python -project documentation, but C/C++ is supported as well, and more languages are -planned. - -Sphinx uses reStructuredText as its markup language, and many of its strengths -come from the power and straightforwardness of reStructuredText and its parsing -and translating suite, the Docutils. - -Among its features are the following: - -* Output formats: HTML (including derivative formats such as HTML Help, Epub - and Qt Help), plain text, manual pages and LaTeX or direct PDF output - using rst2pdf -* Extensive cross-references: semantic markup and automatic links - for functions, classes, glossary terms and similar pieces of information -* Hierarchical structure: easy definition of a document tree, with automatic - links to siblings, parents and children -* Automatic indices: general index as well as a module index -* Code handling: automatic highlighting using the Pygments highlighter -* Flexible HTML output using the Jinja 2 templating engine -* Various extensions are available, e.g. for automatic testing of snippets - and inclusion of appropriately formatted docstrings -* Setuptools integration -''' +with open('README.rst') as f: + long_desc = f.read() if sys.version_info < (2, 7) or (3, 0) <= sys.version_info < (3, 4): print('ERROR: Sphinx requires at least Python 2.7 or 3.4 to run.') From a6f0ba0fc95db043a08d4379481d69a9cb917453 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sat, 21 Oct 2017 15:29:35 +0100 Subject: [PATCH 143/275] README: Cleanup badges Add AppVeyor badge and include 'alt' attributes for the others. Signed-off-by: Stephen Finucane --- README.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README.rst b/README.rst index 54493bb8b..39c58143b 100644 --- a/README.rst +++ b/README.rst @@ -4,11 +4,23 @@ .. image:: https://img.shields.io/pypi/v/sphinx.svg :target: https://pypi.python.org/pypi/Sphinx + :alt: Package on PyPi + .. image:: https://readthedocs.org/projects/sphinx/badge/ :target: http://www.sphinx-doc.org/ :alt: Documentation Status + .. image:: https://travis-ci.org/sphinx-doc/sphinx.svg?branch=master :target: https://travis-ci.org/sphinx-doc/sphinx + :alt: Build Status (Travis CI) + +.. image:: https://ci.appveyor.com/api/projects/status/github/sphinx-doc/sphinx?branch=master&svg=true + :target: https://ci.appveyor.com/project/sphinxdoc/sphinx + :alt: Build Status (AppVeyor) + +.. image:: https://circleci.com/gh/sphinx-doc/sphinx.svg?style=shield + :target: https://circleci.com/gh/sphinx-doc/sphinx + :alt: Build Status (CircleCI) Sphinx is a tool that makes it easy to create intelligent and beautiful documentation for Python projects (or other documents consisting of multiple From 04995b703fbf43345ee805a140a64f6bf78b0ff9 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 20 Dec 2017 00:05:57 +0900 Subject: [PATCH 144/275] Fix typo --- doc/extdev/markupapi.rst | 2 +- sphinx/ext/autodoc/__init__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/extdev/markupapi.rst b/doc/extdev/markupapi.rst index 6f289ed9f..97abc17b9 100644 --- a/doc/extdev/markupapi.rst +++ b/doc/extdev/markupapi.rst @@ -138,7 +138,7 @@ Both APIs parse the content into a given node. They are used like this:: .. deprecated:: 1.7 - Since Sphinx-1.6, ``sphinx.ext.autodoc.AutodocReporter`` is used for this purpose. + Until Sphinx-1.6, ``sphinx.ext.autodoc.AutodocReporter`` is used for this purpose. For now, it is replaced by ``switch_source_input()``. If you don't need the wrapping node, you can use any concrete node type and diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 150620a62..68f78eeb2 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -116,7 +116,7 @@ class AutodocReporter(object): """ def __init__(self, viewlist, reporter): # type: (ViewList, Reporter) -> None - warnings.warn('AutodocRerporter is now deprecated. ' + warnings.warn('AutodocReporter is now deprecated. ' 'Use sphinx.util.docutils.switch_source_input() instead.', RemovedInSphinx20Warning) self.viewlist = viewlist From 25b96b833d79936734df5f23ee055b59969cd6a2 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 20 Dec 2017 00:09:49 +0900 Subject: [PATCH 145/275] Revert the changes of directive_helper --- sphinx/util/docutils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index 5377e493c..3cd257cba 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -31,7 +31,7 @@ report_re = re.compile('^(.+?:(?:\\d+)?): \\((DEBUG|INFO|WARNING|ERROR|SEVERE)/( if False: # For type annotation - from typing import Any, Callable, Dict, Generator, Iterator, List, Tuple # NOQA + from typing import Any, Callable, Generator, Iterator, List, Tuple # NOQA from docutils import nodes # NOQA from docutils.statemachine import State # NOQA from sphinx.environment import BuildEnvironment # NOQA @@ -205,12 +205,12 @@ def is_html5_writer_available(): return __version_info__ > (0, 13, 0) -def directive_helper(obj, has_content=None, argument_spec=None, option_spec=None, **options): - # type: (Any, bool, Tuple[int, int, bool], Dict, Any) -> Any +def directive_helper(obj, has_content=None, argument_spec=None, **option_spec): + # type: (Any, bool, Tuple[int, int, bool], Any) -> Any if isinstance(obj, (types.FunctionType, types.MethodType)): obj.content = has_content # type: ignore obj.arguments = argument_spec or (0, 0, False) # type: ignore - obj.options = option_spec or options # type: ignore + obj.options = option_spec # type: ignore return convert_directive_function(obj) else: if has_content or argument_spec or option_spec: From 242bf9a38a9aa179e4f40c57d4b9a7ff90695127 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 20 Dec 2017 00:11:28 +0900 Subject: [PATCH 146/275] Fix typo --- doc/extdev/markupapi.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/extdev/markupapi.rst b/doc/extdev/markupapi.rst index 97abc17b9..ffa08cae7 100644 --- a/doc/extdev/markupapi.rst +++ b/doc/extdev/markupapi.rst @@ -124,7 +124,7 @@ Both APIs parse the content into a given node. They are used like this:: .. note:: ``sphinx.util.docutils.switch_source_input()`` allows to change a target file - during nested_parse. It is useful to mixture contents. For example, ``sphinx. + during nested_parse. It is useful to mixed contents. For example, ``sphinx. ext.autodoc`` uses it to parse docstrings:: from sphinx.util.docutils import switch_source_input From 76bd63187232030b7cff56153e7a648a190eebb6 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 26 Oct 2017 18:15:58 +0100 Subject: [PATCH 147/275] travis: Start using tox for testing This allows us to validate and reuse the testing tools we use locally for "gate" tests and moves us closer to the eventual goal of deprecating the Makefile targets. This involves adding two new targets to the list of default targets run by tox - docs and mypy. Note that we don't use tox-travis because, wonderful though it may be, configuring it to exclude as many of the tests as we want to exclude is a little convoluted (we have a big test matrix). Signed-off-by: Stephen Finucane --- .travis.yml | 53 ++++++++++++++++++++++++----------------------------- 1 file changed, 24 insertions(+), 29 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1d6694b3d..900853cf7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,45 +2,40 @@ language: python sudo: false dist: trusty cache: pip -python: - - "pypy-5.4.1" - - "3.6" - - "3.5" - - "3.4" - - "2.7" - - "nightly" + env: global: - - TEST='-v --durations 25' - PYTHONFAULTHANDLER=x - PYTHONWARNINGS=all - SKIP_LATEX_BUILD=1 - matrix: - - DOCUTILS=0.13.1 - - DOCUTILS=0.14 + matrix: - exclude: - - python: "3.4" - env: DOCUTILS=0.13.1 - - python: "3.5" - env: DOCUTILS=0.13.1 - - python: "3.6" - env: DOCUTILS=0.13.1 - - python: nightly - env: DOCUTILS=0.13.1 - - python: "pypy-5.4.1" - env: DOCUTILS=0.13.1 + include: + - python: 'pypy' + env: TOXENV=pypy + - python: '2.7' + env: TOXENV=du13 + - python: '3.4' + env: TOXENV=py34 + - python: '3.5' + env: TOXENV=py35 + - python: '3.6' + env: TOXENV=py36 + - python: 'nightly' + env: TOXENV=py37 + - python: '3.6' + env: TOXENV=mypy + - python: '2.7' + env: TOXENV=flake8 + addons: apt: packages: - graphviz - imagemagick + install: - - pip install -U pip setuptools - - pip install docutils==$DOCUTILS - - pip install .[test,websupport] - - if [[ $TRAVIS_PYTHON_VERSION == '3.6' ]]; then python3.6 -m pip install mypy typed-ast; fi + - pip install -U tox + script: - - flake8 - - if [[ $TRAVIS_PYTHON_VERSION == '3.6' ]]; then make type-check test; fi - - if [[ $TRAVIS_PYTHON_VERSION != '3.6' ]]; then make test; fi + - tox -- -v From 638e6467669d5ebc2111a5f7fb2c5612a8bcf1e5 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Tue, 3 Oct 2017 10:00:40 +0100 Subject: [PATCH 148/275] doc: Rework CONTRIBUTING to encourage use of tox Embrace the tox-ified future. This explicitly asks users to use a virtualenv to stop them shooting themselves in the foot. Signed-off-by: Stephen Finucane --- CONTRIBUTING.rst | 68 +++++++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 7c8a90c6b..c4b8569b0 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -33,10 +33,10 @@ Bug Reports and Feature Requests If you have encountered a problem with Sphinx or have an idea for a new feature, please submit it to the `issue tracker`_ on GitHub or discuss it -on the sphinx-dev mailing list. +on the `sphinx-dev`_ mailing list. For bug reports, please include the output produced during the build process -and also the log file Sphinx creates after it encounters an un-handled +and also the log file Sphinx creates after it encounters an unhandled exception. The location of this file should be shown towards the end of the error message. @@ -45,6 +45,7 @@ issue. If possible, try to create a minimal project that produces the error and post that instead. .. _`issue tracker`: https://github.com/sphinx-doc/sphinx/issues +.. _`sphinx-dev`: mailto:sphinx-dev@googlegroups.com Contributing to Sphinx @@ -58,7 +59,7 @@ of the core developers before it is merged into the main repository. #. Check for open issues or open a fresh issue to start a discussion around a feature idea or a bug. #. If you feel uncomfortable or uncertain about an issue or your changes, feel - free to email sphinx-dev@googlegroups.com. + free to email the *sphinx-dev* mailing list. #. Fork `the repository`_ on GitHub to start making your changes to the **master** branch for next major version, or **stable** branch for next minor version. @@ -98,10 +99,14 @@ These are the basic steps needed to start developing on Sphinx. For new features or other substantial changes that should wait until the next major release, use the ``master`` branch. -#. Optional: setup a virtual environment. :: +#. Setup a virtual environment. - virtualenv ~/sphinxenv - . ~/sphinxenv/bin/activate + This is not necessary for unit testing, thanks to ``tox``, but it is + necessary if you wish to run ``sphinx-build`` locally or run unit tests + without the help of ``tox``. :: + + virtualenv ~/.venv + . ~/.venv/bin/activate pip install -e . #. Create a new working branch. Choose any name you like. :: @@ -112,44 +117,53 @@ These are the basic steps needed to start developing on Sphinx. For tips on working with the code, see the `Coding Guide`_. -#. Test, test, test. Possible steps: +#. Test, test, test. - * Run the unit tests:: + Testing is best done through ``tox``, which provides a number of targets and + allows testing against multiple different Python environments: - pip install .[test,websupport] - make test + * To list all possible targets:: - * Again, it's useful to turn on deprecation warnings on so they're shown in - the test output:: + tox -av - PYTHONWARNINGS=all make test + * To run unit tests for a specific Python version, such as 3.6:: - * Arguments to pytest can be passed via tox, e.g. in order to run a + tox -e py36 + + * To run unit tests for a specific Python version and turn on deprecation + warnings on so they're shown in the test output:: + + PYTHONWARNINGS=all tox -e py36 + + * To run code style and type checks:: + + tox -e mypy + tox -e flake8 + + * Arguments to ``pytest`` can be passed via ``tox``, e.g. in order to run a particular test:: - tox -e py27 tests/test_module.py::test_new_feature + tox -e py36 tests/test_module.py::test_new_feature - * Build the documentation and check the output for different builders:: + * To build the documentation:: - make docs target="clean html latexpdf" + tox -e docs - * Run code style checks and type checks (type checks require mypy):: + * To build the documentation in multiple formats:: - make style-check - make type-check + tox -e docs -- -b html,latexpdf - * Run the unit tests under different Python environments using - :program:`tox`:: + You can also test by installing dependencies in your local environment. :: - pip install tox - tox -v + pip install .[test] - * Add a new unit test in the ``tests`` directory if you can. + New unit tests should be included in the ``tests`` directory where + necessary: * For bug fixes, first add a test that fails without your changes and passes after they are applied. - * Tests that need a sphinx-build run should be integrated in one of the + * Tests that need a ``sphinx-build`` run should be integrated in one of the existing test modules if possible. New tests that to ``@with_app`` and then ``build_all`` for a few assertions are not good since *the test suite should not take more than a minute to run*. @@ -266,7 +280,7 @@ Debugging Tips code by running the command ``make clean`` or using the :option:`sphinx-build -E` option. -* Use the :option:`sphinx-build -P` option to run Pdb on exceptions. +* Use the :option:`sphinx-build -P` option to run ``pdb`` on exceptions. * Use ``node.pformat()`` and ``node.asdom().toxml()`` to generate a printable representation of the document structure. From 838f7fc29a0af74d778cb99d235d645716ba02ab Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 20 Dec 2017 00:31:32 +0900 Subject: [PATCH 149/275] Add Domain.add_object_type() to update internal caches correctly --- sphinx/domains/__init__.py | 12 ++++++++++++ sphinx/registry.py | 3 ++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index 1b9a7345a..868f56c91 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -188,6 +188,18 @@ class Domain(object): self.objtypes_for_role = self._role2type.get # type: Callable[[unicode], List[unicode]] # NOQA self.role_for_objtype = self._type2role.get # type: Callable[[unicode], unicode] + def add_object_type(self, name, objtype): + # type: (Objtype) -> None + """Add an object type.""" + self.object_types[name] = objtype + if objtype.roles: + self._type2role[name] = objtype.roles[0] + else: + self._type2role[name] = '' + + for role in objtype.roles: + self._role2type.setdefault(role, []).append(name) + def role(self, name): # type: (unicode) -> Callable """Return a role adapter function that always gives the registered diff --git a/sphinx/registry.py b/sphinx/registry.py index 885c7a256..6ec966a6a 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -112,10 +112,11 @@ class SphinxComponentRegistry(object): domain = DomainClass(env) # transplant components added by extensions - domain.object_types.update(self.domain_object_types.get(domain.name, {})) domain.directives.update(self.domain_directives.get(domain.name, {})) domain.roles.update(self.domain_roles.get(domain.name, {})) domain.indices.extend(self.domain_indices.get(domain.name, [])) + for name, objtype in iteritems(self.domain_object_types.get(domain.name, {})): + domain.add_object_type(name, objtype) yield domain From a2a873d58afb91143c3b71c9037384458043c080 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Tue, 19 Dec 2017 15:55:10 +0000 Subject: [PATCH 150/275] tox: Add documentation for all targets This should make 'tox -av' more helpful. Signed-off-by: Stephen Finucane --- tox.ini | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/tox.ini b/tox.ini index 22a34f6f8..4b462d612 100644 --- a/tox.ini +++ b/tox.ini @@ -1,9 +1,15 @@ [tox] -minversion=2.0 -envlist=docs,flake8,mypy,coverage,py{27,34,35,36,py},du{11,12,13,14} +minversion = 2.0 +envlist = docs,flake8,mypy,coverage,py{27,34,35,36,py},du{11,12,13,14} [testenv] -passenv = https_proxy http_proxy no_proxy +passenv = + https_proxy http_proxy no_proxy +description = + py{27,34,35,36,py}: Run unit tests against {envname}. + du{11,12,13,14}: Run unit tests with the given version of docutils. + coverage: Run code coverage checks. + # TODO(stephenfin) Replace this with the 'extras' config option when tox 2.4 is # widely available, likely some time after the Ubuntu 18.04 release # @@ -21,22 +27,30 @@ commands= {envpython} -Wall tests/run.py --durations 25 {posargs} [testenv:flake8] -commands=flake8 +description = + Run style checks. +commands = + flake8 [testenv:pylint] -deps= +description = + Run source code analyzer. +deps = pylint {[testenv]deps} -commands= +commands = pylint --rcfile utils/pylintrc sphinx [testenv:mypy] -basepython=python3 -deps= +description = + Run type checks. +deps = mypy commands= mypy sphinx/ [testenv:docs] -commands= +description = + Build documentation. +commands = python setup.py build_sphinx {posargs} From ac9ae4d54b0ad01dd62d94811046f6e3e9af860a Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Tue, 19 Dec 2017 16:00:20 +0000 Subject: [PATCH 151/275] README: Fix typo Signed-off-by: Stephen Finucane Fixes: 393f59d ("Improve README") --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 39c58143b..79d8d6632 100644 --- a/README.rst +++ b/README.rst @@ -94,7 +94,7 @@ __ CONTRIBUTING.rst Contributing ============ -Refer to `the contributors guide`_. +Refer to `the contributors guide`__. __ CONTRIBUTING.rst From b103b3c24ac8d983498f1170d8e104f8cd72c3df Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 20 Dec 2017 01:28:07 +0900 Subject: [PATCH 152/275] doc: Use anonymous link target for README --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 79d8d6632..6419503e4 100644 --- a/README.rst +++ b/README.rst @@ -51,7 +51,7 @@ Among its features are the following: For more information, refer to the `the documentation`__. -__ http://www.sphinx-doc.org/ +.. __: http://www.sphinx-doc.org/ Installation ============ From 7a194f52960fe5ace04ef7daa72563e6d3bf094f Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 18 Dec 2017 22:09:29 +0900 Subject: [PATCH 153/275] autodoc: Use logging module to emit warnings --- CHANGES | 2 ++ sphinx/ext/autodoc/__init__.py | 41 +++++++++++++++------------------ tests/py35/test_autodoc_py35.py | 25 ++++++++------------ tests/test_autodoc.py | 38 +++++++++++++++--------------- 4 files changed, 51 insertions(+), 55 deletions(-) diff --git a/CHANGES b/CHANGES index 2ec7d56bb..cb43a26ae 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,8 @@ Incompatible changes * #3929: apidoc: Move sphinx.apidoc to sphinx.ext.apidoc * #4226: apidoc: Generate new style makefile (make-mode) * #4274: sphinx-build returns 2 as an exit code on argument error +* autodoc does not generate warnings messages to the generated document even if + :confval:`keep_warnings` is True. They are only emitted to stderr. Deprecated ---------- diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index ff161565c..48afbcc91 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -354,8 +354,7 @@ class Documenter(object): explicit_modname, path, base, args, retann = \ py_ext_sig_re.match(self.name).groups() # type: ignore except AttributeError: - self.directive.warn('invalid signature for auto%s (%r)' % - (self.objtype, self.name)) + logger.warning('invalid signature for auto%s (%r)' % (self.objtype, self.name)) return False # support explicit module and class name separation via :: @@ -432,8 +431,7 @@ class Documenter(object): if PY2: errmsg = errmsg.decode('utf-8') # type: ignore - logger.debug(errmsg) - self.directive.warn(errmsg) + logger.warning(errmsg) self.env.note_reread() return False @@ -493,8 +491,8 @@ class Documenter(object): try: args = self.format_args() except Exception as err: - self.directive.warn('error while formatting arguments for ' - '%s: %s' % (self.fullname, err)) + logger.warning('error while formatting arguments for %s: %s' % + (self.fullname, err)) args = None retann = self.retann @@ -623,8 +621,8 @@ class Documenter(object): members.append((mname, self.get_attr(self.object, mname))) except AttributeError: if mname not in analyzed_member_names: - self.directive.warn('missing attribute %s in object %s' - % (mname, self.fullname)) + logger.warning('missing attribute %s in object %s' % + (mname, self.fullname)) elif self.options.inherited_members: # safe_getmembers() uses dir() which pulls in members from all # base classes @@ -820,11 +818,11 @@ class Documenter(object): """ if not self.parse_name(): # need a module to import - self.directive.warn( + logger.warning( 'don\'t know which module to import for autodocumenting ' '%r (try placing a "module" or "currentmodule" directive ' - 'in the document, or giving an explicit module name)' - % self.name) + 'in the document, or giving an explicit module name)' % + self.name) return # now, import the module and get object to document @@ -910,15 +908,15 @@ class ModuleDocumenter(Documenter): def resolve_name(self, modname, parents, path, base): # type: (str, Any, str, Any) -> Tuple[str, List[unicode]] if modname is not None: - self.directive.warn('"::" in automodule name doesn\'t make sense') + logger.warning('"::" in automodule name doesn\'t make sense') return (path or '') + base, [] def parse_name(self): # type: () -> bool ret = Documenter.parse_name(self) if self.args or self.retann: - self.directive.warn('signature arguments or return annotation ' - 'given for automodule %s' % self.fullname) + logger.warning('signature arguments or return annotation ' + 'given for automodule %s' % self.fullname) return ret def add_directive_header(self, sig): @@ -949,7 +947,7 @@ class ModuleDocumenter(Documenter): # Sometimes __all__ is broken... if not isinstance(memberlist, (list, tuple)) or not \ all(isinstance(entry, string_types) for entry in memberlist): - self.directive.warn( + logger.warning( '__all__ should be a list of strings, not %r ' '(in module %s) -- ignoring __all__' % (memberlist, self.fullname)) @@ -962,10 +960,10 @@ class ModuleDocumenter(Documenter): try: ret.append((mname, safe_getattr(self.object, mname))) except AttributeError: - self.directive.warn( + logger.warning( 'missing attribute mentioned in :members: or __all__: ' - 'module %s, attribute %s' % ( - safe_getattr(self.object, '__name__', '???'), mname)) + 'module %s, attribute %s' % + (safe_getattr(self.object, '__name__', '???'), mname)) return False, ret @@ -1542,7 +1540,7 @@ class AutoDirective(Directive): def warn(self, msg): # type: (unicode) -> None - self.warnings.append(self.reporter.warning(msg, line=self.lineno)) + logger.warning(msg, line=self.lineno) def run(self): # type: () -> List[nodes.Node] @@ -1550,7 +1548,6 @@ class AutoDirective(Directive): # a set of dependent filenames self.reporter = self.state.document.reporter self.env = self.state.document.settings.env - self.warnings = [] # type: List[unicode] self.result = ViewList() try: @@ -1585,7 +1582,7 @@ class AutoDirective(Directive): documenter = doc_class(self, self.arguments[0]) documenter.generate(more_content=self.content) if not self.result: - return self.warnings + return [] logger.debug('[autodoc] output:\n%s', '\n'.join(self.result)) @@ -1610,7 +1607,7 @@ class AutoDirective(Directive): node.document = self.state.document self.state.nested_parse(self.result, 0, node) self.state.memo.reporter = old_reporter - return self.warnings + node.children + return node.children def add_documenter(cls): diff --git a/tests/py35/test_autodoc_py35.py b/tests/py35/test_autodoc_py35.py index 481374948..9a94dbd27 100644 --- a/tests/py35/test_autodoc_py35.py +++ b/tests/py35/test_autodoc_py35.py @@ -21,6 +21,7 @@ from docutils.statemachine import ViewList from sphinx.ext.autodoc import AutoDirective, add_documenter, \ ModuleLevelDocumenter, FunctionDocumenter, cut_lines, between, ALL +from sphinx.util import logging app = None @@ -30,7 +31,7 @@ def setup_module(rootdir, sphinx_test_tempdir): global app srcdir = sphinx_test_tempdir / 'autodoc-root' if not srcdir.exists(): - (rootdir/'test-root').copytree(srcdir) + (rootdir / 'test-root').copytree(srcdir) app = SphinxTestApp(srcdir=srcdir) app.builder.env.app = app app.builder.env.temp_data['docname'] = 'dummy' @@ -47,7 +48,7 @@ directive = options = None @pytest.fixture def setup_test(): global options, directive - global processed_docstrings, processed_signatures, _warnings + global processed_docstrings, processed_signatures options = Struct( inherited_members = False, @@ -70,24 +71,17 @@ def setup_test(): env = app.builder.env, genopt = options, result = ViewList(), - warn = warnfunc, filename_set = set(), ) processed_docstrings = [] processed_signatures = [] - _warnings = [] -_warnings = [] processed_docstrings = [] processed_signatures = [] -def warnfunc(msg): - _warnings.append(msg) - - def process_docstring(app, what, name, obj, options, lines): processed_docstrings.append((what, name)) if name == 'bar': @@ -111,20 +105,21 @@ def skip_member(app, what, name, obj, skip, options): @pytest.mark.usefixtures('setup_test') def test_generate(): + logging.setup(app, app._status, app._warning) + def assert_warns(warn_str, objtype, name, **kw): inst = AutoDirective._registry[objtype](directive, name) inst.generate(**kw) assert len(directive.result) == 0, directive.result - assert len(_warnings) == 1, _warnings - assert warn_str in _warnings[0], _warnings - del _warnings[:] + assert warn_str in app._warning.getvalue() + app._warning.truncate(0) def assert_works(objtype, name, **kw): inst = AutoDirective._registry[objtype](directive, name) inst.generate(**kw) assert directive.result # print '\n'.join(directive.result) - assert len(_warnings) == 0, _warnings + assert app._warning.getvalue() == '' del directive.result[:] def assert_processes(items, objtype, name, **kw): @@ -137,7 +132,7 @@ def test_generate(): inst = AutoDirective._registry[objtype](directive, name) inst.generate(**kw) # print '\n'.join(directive.result) - assert len(_warnings) == 0, _warnings + assert app._warning.getvalue() == '' assert item in directive.result del directive.result[:] @@ -145,7 +140,7 @@ def test_generate(): inst = AutoDirective._registry[objtype](directive, name) inst.options.member_order = member_order inst.generate(**kw) - assert len(_warnings) == 0, _warnings + assert app._warning.getvalue() == '' items = list(reversed(items)) lineiter = iter(directive.result) # for line in directive.result: diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index 989c367b6..4ab58d891 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -21,6 +21,7 @@ from docutils.statemachine import ViewList from sphinx.ext.autodoc import AutoDirective, add_documenter, \ ModuleLevelDocumenter, FunctionDocumenter, cut_lines, between, ALL +from sphinx.util import logging app = None @@ -47,7 +48,7 @@ directive = options = None @pytest.fixture def setup_test(): global options, directive - global processed_docstrings, processed_signatures, _warnings + global processed_docstrings, processed_signatures options = Struct( inherited_members = False, @@ -70,28 +71,24 @@ def setup_test(): env = app.builder.env, genopt = options, result = ViewList(), - warn = warnfunc, filename_set = set(), ) processed_docstrings = [] processed_signatures = [] - _warnings = [] + + app._status.truncate(0) + app._warning.truncate(0) yield AutoDirective._special_attrgetters.clear() -_warnings = [] processed_docstrings = [] processed_signatures = [] -def warnfunc(msg): - _warnings.append(msg) - - def process_docstring(app, what, name, obj, options, lines): processed_docstrings.append((what, name)) if name == 'bar': @@ -115,6 +112,8 @@ def skip_member(app, what, name, obj, skip, options): @pytest.mark.usefixtures('setup_test') def test_parse_name(): + logging.setup(app, app._status, app._warning) + def verify(objtype, name, result): inst = AutoDirective._registry[objtype](directive, name) assert inst.parse_name() @@ -124,8 +123,7 @@ def test_parse_name(): verify('module', 'test_autodoc', ('test_autodoc', [], None, None)) verify('module', 'test.test_autodoc', ('test.test_autodoc', [], None, None)) verify('module', 'test(arg)', ('test', [], 'arg', None)) - assert 'signature arguments' in _warnings[0] - del _warnings[:] + assert 'signature arguments' in app._warning.getvalue() # for functions/classes verify('function', 'test_autodoc.raises', @@ -241,7 +239,6 @@ def test_format_signature(): # test exception handling (exception is caught and args is '') directive.env.config.autodoc_docstring_signature = False assert formatsig('function', 'int', int, None, None) == '' - del _warnings[:] # test processing by event handler assert formatsig('method', 'bar', H.foo1, None, None) == '42' @@ -533,6 +530,8 @@ def test_docstring_property_processing(): @pytest.mark.usefixtures('setup_test') def test_new_documenter(): + logging.setup(app, app._status, app._warning) + class MyDocumenter(ModuleLevelDocumenter): objtype = 'integer' directivetype = 'data' @@ -548,10 +547,11 @@ def test_new_documenter(): add_documenter(MyDocumenter) def assert_result_contains(item, objtype, name, **kw): + app._warning.truncate(0) inst = AutoDirective._registry[objtype](directive, name) inst.generate(**kw) # print '\n'.join(directive.result) - assert len(_warnings) == 0, _warnings + assert app._warning.getvalue() == '' assert item in directive.result del directive.result[:] @@ -593,20 +593,22 @@ def test_attrgetter_using(): @pytest.mark.usefixtures('setup_test') def test_generate(): + logging.setup(app, app._status, app._warning) + def assert_warns(warn_str, objtype, name, **kw): inst = AutoDirective._registry[objtype](directive, name) inst.generate(**kw) assert len(directive.result) == 0, directive.result - assert len(_warnings) == 1, _warnings - assert warn_str in _warnings[0], _warnings - del _warnings[:] + + assert warn_str in app._warning.getvalue() + app._warning.truncate(0) def assert_works(objtype, name, **kw): inst = AutoDirective._registry[objtype](directive, name) inst.generate(**kw) assert directive.result # print '\n'.join(directive.result) - assert len(_warnings) == 0, _warnings + assert app._warning.getvalue() == '' del directive.result[:] def assert_processes(items, objtype, name, **kw): @@ -619,7 +621,7 @@ def test_generate(): inst = AutoDirective._registry[objtype](directive, name) inst.generate(**kw) # print '\n'.join(directive.result) - assert len(_warnings) == 0, _warnings + assert app._warning.getvalue() == '' assert item in directive.result del directive.result[:] @@ -627,7 +629,7 @@ def test_generate(): inst = AutoDirective._registry[objtype](directive, name) inst.options.member_order = member_order inst.generate(**kw) - assert len(_warnings) == 0, _warnings + assert app._warning.getvalue() == '' items = list(reversed(items)) lineiter = iter(directive.result) # for line in directive.result: From 221aa470fa26ae369627b1b301cc16de754a44f5 Mon Sep 17 00:00:00 2001 From: Paul V Craven Date: Tue, 19 Dec 2017 17:28:28 -0600 Subject: [PATCH 154/275] Add "Arcade" library documentation to examples --- EXAMPLES | 1 + 1 file changed, 1 insertion(+) diff --git a/EXAMPLES b/EXAMPLES index fa91b206e..26000cb31 100644 --- a/EXAMPLES +++ b/EXAMPLES @@ -111,6 +111,7 @@ Documentation using the sphinxdoc theme Documentation using another builtin theme ----------------------------------------- +* Arcade: https://arcade.academy/ (sphinx_rtd_theme) * ASE: https://wiki.fysik.dtu.dk/ase/ (sphinx_rtd_theme) * C/C++ Development with Eclipse: http://eclipsebook.in/ (agogo) * ESWP3 (http://eswp3.org) (sphinx_rtd_theme) From 7054c0306aafb2cfa8abe4553729385dfb928ffe Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 19 Dec 2017 22:28:54 +0900 Subject: [PATCH 155/275] doc: Remove mentions to deprecated options (both are removed at 8c2fabe v1.3) --- doc/config.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/doc/config.rst b/doc/config.rst index d748f5706..62c4ccc73 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -138,12 +138,10 @@ General configuration - ``'library/xml.rst'`` -- ignores the ``library/xml.rst`` file (replaces entry in :confval:`unused_docs`) - - ``'library/xml'`` -- ignores the ``library/xml`` directory (replaces entry - in :confval:`exclude_trees`) + - ``'library/xml'`` -- ignores the ``library/xml`` directory - ``'library/xml*'`` -- ignores all files and directories starting with ``library/xml`` - - ``'**/.svn'`` -- ignores all ``.svn`` directories (replaces entry in - :confval:`exclude_dirnames`) + - ``'**/.svn'`` -- ignores all ``.svn`` directories :confval:`exclude_patterns` is also consulted when looking for static files in :confval:`html_static_path` and :confval:`html_extra_path`. From 3fe218e759f75f3a1a613dd845ed0db65a6fa196 Mon Sep 17 00:00:00 2001 From: Paul V Craven Date: Tue, 19 Dec 2017 21:14:36 -0600 Subject: [PATCH 156/275] Update arcade.academy link Update http://arcade.academy link to use http instead of https. --- EXAMPLES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EXAMPLES b/EXAMPLES index 26000cb31..9d3b24311 100644 --- a/EXAMPLES +++ b/EXAMPLES @@ -111,7 +111,7 @@ Documentation using the sphinxdoc theme Documentation using another builtin theme ----------------------------------------- -* Arcade: https://arcade.academy/ (sphinx_rtd_theme) +* Arcade: http://arcade.academy/ (sphinx_rtd_theme) * ASE: https://wiki.fysik.dtu.dk/ase/ (sphinx_rtd_theme) * C/C++ Development with Eclipse: http://eclipsebook.in/ (agogo) * ESWP3 (http://eswp3.org) (sphinx_rtd_theme) From c7a145cc1803787a71654fe052ec9005d6a6f0a9 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Wed, 20 Dec 2017 09:05:34 +0100 Subject: [PATCH 157/275] C++, handle defaulted constrained template type parameters --- sphinx/domains/cpp.py | 115 +++++++++++++++++++++++++++++++++++---- tests/test_domain_cpp.py | 4 ++ 2 files changed, 107 insertions(+), 12 deletions(-) diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index c77c38413..971d6ad68 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -1314,6 +1314,44 @@ class ASTTemplateParamType(ASTBase): self.data.describe_signature(signode, mode, env, symbol) +class ASTTemplateParamConstrainedTypeWithInit(ASTBase): + def __init__(self, type, init): + # type: (Any, Any) -> None + assert type + self.type = type + self.init = init + + @property + def name(self): + # type: () -> ASTNestedName + return self.type.name + + def get_id(self, version, objectType=None, symbol=None): + # type: (int, unicode, Symbol) -> unicode + # this is not part of the normal name mangling in C++ + assert version >= 2 + if symbol: + # the anchor will be our parent + return symbol.parent.declaration.get_id(version, prefixed=False) + else: + return self.type.get_id(version) + + def __unicode__(self): + # type: () -> unicode + res = text_type(self.type) + if self.init: + res += " = " + res += text_type(self.init) + return res + + def describe_signature(self, signode, mode, env, symbol): + # type: (addnodes.desc_signature, unicode, BuildEnvironment, Symbol) -> None + self.type.describe_signature(signode, mode, env, symbol) + if self.init: + signode += nodes.Text(" = ") + self.init.describe_signature(signode, mode, env, symbol) + + class ASTTemplateParamTemplateType(ASTBase): def __init__(self, nestedParams, data): # type: (Any, Any) -> None @@ -3781,6 +3819,8 @@ class DefinitionParser(object): self.last_match = None # type: Match self._previous_state = (0, None) # type: Tuple[int, Match] self.otherErrors = [] # type: List[DefinitionError] + # in our tests the following is set to False to capture bad parsing + self.allowFallbackExpressionParsing = True self.warnEnv = warnEnv self.config = config @@ -4121,6 +4161,13 @@ class DefinitionParser(object): # TODO: hmm, would we need to try both with operatorCast and with None? prefix = self._parse_type(False, 'operatorCast') prefixType = 'typeOperatorCast' + # | simple-type-specifier "(" expression-list [opt] ")" + # | simple-type-specifier braced-init-list + # | typename-specifier "(" expression-list [opt] ")" + # | typename-specifier braced-init-list + self.skip_ws() + if self.current_char != '(' and self.current_char != '{': + self.fail("Expecting '(' or '{' after type in cast expression.") except DefinitionError as eInner: self.pos = pos header = "Error in postfix expression, expected primary expression or type." @@ -4361,7 +4408,7 @@ class DefinitionParser(object): # TODO: actually parse the second production return self._parse_assignment_expression(inTemplate=inTemplate) - def _parse_expression_fallback(self, end, parser): + def _parse_expression_fallback(self, end, parser, allow=True): # Stupidly "parse" an expression. # 'end' should be a list of characters which ends the expression. @@ -4370,6 +4417,10 @@ class DefinitionParser(object): try: return parser() except DefinitionError as e: + # some places (e.g., template parameters) we really don't want to use fallback, + # and for testing we may want to globally disable it + if not allow or not self.allowFallbackExpressionParsing: + raise self.warn("Parsing of expression failed. Using fallback parser." " Error was:\n%s" % e.description) self.pos = prevPos @@ -4598,7 +4649,7 @@ class DefinitionParser(object): self.fail('Expected ")" after "..." in ' 'parameters_and_qualifiers.') break - # note: it seems that function arguments can always sbe named, + # note: it seems that function arguments can always be named, # even in function pointers and similar. arg = self._parse_type_with_init(outer=None, named='single') # TODO: parse default parameters # TODO: didn't we just do that? @@ -4919,8 +4970,8 @@ class DefinitionParser(object): header = "Error in declarator or parameters and qualifiers" raise self._make_multi_error(prevErrors, header) - def _parse_initializer(self, outer=None): - # type: (unicode) -> ASTInitializer + def _parse_initializer(self, outer=None, allowFallback=True): + # type: (unicode, bool) -> ASTInitializer self.skip_ws() # TODO: support paren and brace initialization for memberObject if not self.skip_string('='): @@ -4929,15 +4980,18 @@ class DefinitionParser(object): if outer == 'member': def parser(): return self._parse_assignment_expression(inTemplate=False) - value = self._parse_expression_fallback([], parser) + value = self._parse_expression_fallback([], parser, + allow=allowFallback) elif outer == 'templateParam': def parser(): return self._parse_assignment_expression(inTemplate=True) - value = self._parse_expression_fallback([',', '>'], parser) + value = self._parse_expression_fallback([',', '>'], parser, + allow=allowFallback) elif outer is None: # function parameter def parser(): return self._parse_assignment_expression(inTemplate=False) - value = self._parse_expression_fallback([',', ')'], parser) + value = self._parse_expression_fallback([',', ')'], parser, + allow=allowFallback) else: self.fail("Internal error, initializer for outer '%s' not " "implemented." % outer) @@ -5027,12 +5081,48 @@ class DefinitionParser(object): return ASTType(declSpecs, decl) def _parse_type_with_init(self, named, outer): - # type: (Union[bool, unicode], unicode) -> ASTTypeWithInit + # type: (Union[bool, unicode], unicode) -> Any if outer: assert outer in ('type', 'member', 'function', 'templateParam') type = self._parse_type(outer=outer, named=named) - init = self._parse_initializer(outer=outer) - return ASTTypeWithInit(type, init) + if outer != 'templateParam': + init = self._parse_initializer(outer=outer) + return ASTTypeWithInit(type, init) + # it could also be a constrained type parameter, e.g., C T = int& + pos = self.pos + eExpr = None + try: + init = self._parse_initializer(outer=outer, allowFallback=False) + # note: init may be None if there is no = + if init is None: + return ASTTypeWithInit(type, None) + # we parsed an expression, so we must have a , or a >, + # otherwise the expression didn't get everything + self.skip_ws() + if self.current_char != ',' and self.current_char != '>': + # pretend it didn't happen + self.pos = pos + init = None + else: + # we assume that it was indeed an expression + return ASTTypeWithInit(type, init) + except DefinitionError as e: + self.pos = pos + eExpr = e + if not self.skip_string("="): + return ASTTypeWithInit(type, None) + try: + typeInit = self._parse_type(named=False, outer=None) + return ASTTemplateParamConstrainedTypeWithInit(type, typeInit) + except DefinitionError as eType: + if eExpr is None: + raise eType + errs = [] + errs.append((eExpr, "If default is an expression")) + errs.append((eType, "If default is a type")) + msg = "Error in non-type template parameter" + msg += " or constrianted template paramter." + raise self._make_multi_error(errs, msg) def _parse_type_using(self): # type: () -> ASTTypeUsing @@ -5156,13 +5246,14 @@ class DefinitionParser(object): param = ASTTemplateParamType(data) templateParams.append(param) else: - # declare a non-type parameter + # declare a non-type parameter, or constrained type parameter pos = self.pos try: param = self._parse_type_with_init('maybe', 'templateParam') templateParams.append(ASTTemplateParamNonType(param)) except DefinitionError as e: - prevErrors.append((e, "If non-type template parameter")) + msg = "If non-type template parameter or constrained template parameter" + prevErrors.append((e, msg)) self.pos = pos self.skip_ws() if self.skip_string('>'): diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py index f3f0037f5..e4f3a678b 100644 --- a/tests/test_domain_cpp.py +++ b/tests/test_domain_cpp.py @@ -25,6 +25,7 @@ def parse(name, string): cpp_id_attributes = ["id_attr"] cpp_paren_attributes = ["paren_attr"] parser = DefinitionParser(string, None, Config()) + parser.allowFallbackExpressionParsing = False ast = parser.parse_declaration(name) parser.assert_end() # The scopedness would usually have been set by CPPEnumObject @@ -569,6 +570,9 @@ def test_templates(): check('member', 'template int A::B::b', {2: 'IEIEN1AIiE1BIiE1bE'}, output='template<> template<> int A::B::b') # same as above + # defaulted constrained type parameters + check('type', 'template A', {2:'I_1CE1A'}) + def test_template_args(): # from breathe#218 From b07de530619d7e26a62540cf75954839f0f712d9 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 21 Dec 2017 00:19:02 +0900 Subject: [PATCH 158/275] Fix mypy violation --- sphinx/domains/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index 868f56c91..1c80d3a42 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -189,7 +189,7 @@ class Domain(object): self.role_for_objtype = self._type2role.get # type: Callable[[unicode], unicode] def add_object_type(self, name, objtype): - # type: (Objtype) -> None + # type: (unicode, ObjType) -> None """Add an object type.""" self.object_types[name] = objtype if objtype.roles: From e932ff5ad2f9e1241c06506d42b14c2d5ecd8b44 Mon Sep 17 00:00:00 2001 From: Kevin Keating Date: Wed, 20 Dec 2017 15:07:33 -0500 Subject: [PATCH 159/275] Closes #947: autodoc now supports ignore-module-all to ignore a module's __all__ --- CHANGES | 1 + doc/ext/autodoc.rst | 8 +++++--- sphinx/ext/autodoc/__init__.py | 7 ++++--- tests/test_autodoc.py | 7 +++++++ 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 3023ee8c0..0206e84b5 100644 --- a/CHANGES +++ b/CHANGES @@ -50,6 +50,7 @@ Features added * #3160: html: Use ```` to represent ``:kbd:`` role * #4212: autosummary: catch all exceptions when importing modules * #3991, #4080: Add :confval:`math_numfig` for equation numbering by section +* #947: autodoc now supports ignore-module-all to ignore a module's ``__all__`` Features removed diff --git a/doc/ext/autodoc.rst b/doc/ext/autodoc.rst index bfd55c81a..09098f39c 100644 --- a/doc/ext/autodoc.rst +++ b/doc/ext/autodoc.rst @@ -103,8 +103,10 @@ inserting them into the page source under a suitable :rst:dir:`py:module`, will document all non-private member functions and properties (that is, those whose name doesn't start with ``_``). - For modules, ``__all__`` will be respected when looking for members; the - order of the members will also be the order in ``__all__``. + For modules, ``__all__`` will be respected when looking for members unless + you give the ``ignore-module-all`` flag option. Without + ``ignore-module-all``, the order of the members will also be the order in + ``__all__``. You can also give an explicit list of members; only these will then be documented:: @@ -339,7 +341,7 @@ There are also new config values that you can set: This value is a list of autodoc directive flags that should be automatically applied to all autodoc directives. The supported flags are ``'members'``, ``'undoc-members'``, ``'private-members'``, ``'special-members'``, - ``'inherited-members'`` and ``'show-inheritance'``. + ``'inherited-members'``, ``'show-inheritance'`` and ``'ignore-module-all'``. If you set one of these flags in this config value, you can use a negated form, :samp:`'no-{flag}'`, in an autodoc directive, to disable it once. diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index ff161565c..ddf34a211 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -898,7 +898,7 @@ class ModuleDocumenter(Documenter): 'platform': identity, 'deprecated': bool_option, 'member-order': identity, 'exclude-members': members_set_option, 'private-members': bool_option, 'special-members': members_option, - 'imported-members': bool_option, + 'imported-members': bool_option, 'ignore-module-all': bool_option } # type: Dict[unicode, Callable] @classmethod @@ -940,7 +940,8 @@ class ModuleDocumenter(Documenter): def get_object_members(self, want_all): # type: (bool) -> Tuple[bool, List[Tuple[unicode, object]]] if want_all: - if not hasattr(self.object, '__all__'): + if (self.options.ignore_module_all or not + hasattr(self.object, '__all__')): # for implicit module members, check __module__ to avoid # documenting imported objects return True, safe_getmembers(self.object) @@ -1528,7 +1529,7 @@ class AutoDirective(Directive): # flags that can be given in autodoc_default_flags _default_flags = set([ 'members', 'undoc-members', 'inherited-members', 'show-inheritance', - 'private-members', 'special-members', + 'private-members', 'special-members', 'ignore-module-all' ]) # standard docutils directive settings diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index 989c367b6..fda1c561e 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -64,6 +64,7 @@ def setup_test(): members = [], member_order = 'alphabetic', exclude_members = set(), + ignore_module_all = False, ) directive = Struct( @@ -736,6 +737,12 @@ def test_generate(): else: assert False, 'documented CustomEx which is not in __all__' + # test ignore-module-all + options.ignore_module_all = True + assert_result_contains('.. py:class:: Class(arg)', 'module', 'test_autodoc') + assert_result_contains('.. py:exception:: CustomEx', 'module', + 'test_autodoc') + # test noindex flag options.members = [] options.noindex = True From 1ee2c2fb9543d91f13251a3b818feee121d8a2c9 Mon Sep 17 00:00:00 2001 From: jfbu Date: Wed, 20 Dec 2017 21:30:05 +0100 Subject: [PATCH 160/275] Re-use some existing test with extras --- tests/roots/test-latex-toplevel/conf.py | 12 ---- tests/roots/test-latex-toplevel/index.rst | 8 --- .../roots/test-latex-toplevel/indexhowto.rst | 10 --- .../roots/test-latex-toplevel/indexmanual.rst | 13 ---- tests/test_build_latex.py | 64 ++++++++++++------- 5 files changed, 41 insertions(+), 66 deletions(-) delete mode 100644 tests/roots/test-latex-toplevel/conf.py delete mode 100644 tests/roots/test-latex-toplevel/index.rst delete mode 100644 tests/roots/test-latex-toplevel/indexhowto.rst delete mode 100644 tests/roots/test-latex-toplevel/indexmanual.rst diff --git a/tests/roots/test-latex-toplevel/conf.py b/tests/roots/test-latex-toplevel/conf.py deleted file mode 100644 index 88efc87ed..000000000 --- a/tests/roots/test-latex-toplevel/conf.py +++ /dev/null @@ -1,12 +0,0 @@ -# -*- coding: utf-8 -*- - -master_doc = 'index' - -latex_toplevel_sectioning = 'part' - -latex_documents = [ - ('indexmanual', 'SphinxManual.tex', 'Test toplevel manual', - 'Sphinx', 'manual'), - ('indexhowto', 'SphinxHowTo.tex', 'Test toplevel howto', - 'Sphinx', 'howto'), -] diff --git a/tests/roots/test-latex-toplevel/index.rst b/tests/roots/test-latex-toplevel/index.rst deleted file mode 100644 index 833bc67bb..000000000 --- a/tests/roots/test-latex-toplevel/index.rst +++ /dev/null @@ -1,8 +0,0 @@ -=================== -test-latex-toplevel -=================== - -.. toctree:: - - indexmanual - indexhowto diff --git a/tests/roots/test-latex-toplevel/indexhowto.rst b/tests/roots/test-latex-toplevel/indexhowto.rst deleted file mode 100644 index 7c0c92d1a..000000000 --- a/tests/roots/test-latex-toplevel/indexhowto.rst +++ /dev/null @@ -1,10 +0,0 @@ -========================= -test-latex-toplevel-howto -========================= - -This is a part -============== - -This is a section ------------------ - diff --git a/tests/roots/test-latex-toplevel/indexmanual.rst b/tests/roots/test-latex-toplevel/indexmanual.rst deleted file mode 100644 index 2181b1426..000000000 --- a/tests/roots/test-latex-toplevel/indexmanual.rst +++ /dev/null @@ -1,13 +0,0 @@ -========================== -test-latex-toplevel-manual -========================== - -First part -========== - -This is chapter ---------------- - -This is section -~~~~~~~~~~~~~~~ - diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index edaf107c4..faa2f46a7 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -713,20 +713,16 @@ def test_latex_logo_if_not_found(app, status, warning): assert isinstance(exc, SphinxError) -@pytest.mark.sphinx('latex', testroot='toctree-maxdepth', - confoverrides={'latex_documents': [ - ('index', 'SphinxTests.tex', 'Sphinx Tests Documentation', - 'Georg Brandl', 'manual'), - ]}) +@pytest.mark.sphinx('latex', testroot='toctree-maxdepth') def test_toctree_maxdepth_manual(app, status, warning): app.builder.build_all() - result = (app.outdir / 'SphinxTests.tex').text(encoding='utf8') + result = (app.outdir / 'Python.tex').text(encoding='utf8') print(result) print(status.getvalue()) print(warning.getvalue()) assert '\\setcounter{tocdepth}{1}' in result assert '\\setcounter{secnumdepth}' not in result - + assert '\\chapter{Foo}' in result @pytest.mark.sphinx( 'latex', testroot='toctree-maxdepth', @@ -742,7 +738,7 @@ def test_toctree_maxdepth_howto(app, status, warning): print(warning.getvalue()) assert '\\setcounter{tocdepth}{2}' in result assert '\\setcounter{secnumdepth}' not in result - + assert '\\section{Foo}' in result @pytest.mark.sphinx( 'latex', testroot='toctree-maxdepth', @@ -755,7 +751,7 @@ def test_toctree_not_found(app, status, warning): print(warning.getvalue()) assert '\\setcounter{tocdepth}' not in result assert '\\setcounter{secnumdepth}' not in result - + assert '\\chapter{Foo A}' in result @pytest.mark.sphinx( 'latex', testroot='toctree-maxdepth', @@ -805,6 +801,26 @@ def test_latex_toplevel_sectioning_is_part(app, status, warning): print(status.getvalue()) print(warning.getvalue()) assert '\\part{Foo}' in result + assert '\\chapter{Foo A}' in result + assert '\\chapter{Foo B}' in result + + +@pytest.mark.sphinx( + 'latex', testroot='toctree-maxdepth', + confoverrides={'latex_toplevel_sectioning': 'part', + 'latex_documents': [ + ('index', 'Python.tex', 'Sphinx Tests Documentation', + 'Georg Brandl', 'howto') + ]}) +def test_latex_toplevel_sectioning_is_part_with_howto(app, status, warning): + app.builder.build_all() + result = (app.outdir / 'Python.tex').text(encoding='utf8') + print(result) + print(status.getvalue()) + print(warning.getvalue()) + assert '\\part{Foo}' in result + assert '\\section{Foo A}' in result + assert '\\section{Foo B}' in result @pytest.mark.sphinx( @@ -819,6 +835,22 @@ def test_latex_toplevel_sectioning_is_chapter(app, status, warning): assert '\\chapter{Foo}' in result +@pytest.mark.sphinx( + 'latex', testroot='toctree-maxdepth', + confoverrides={'latex_toplevel_sectioning': 'chapter', + 'latex_documents': [ + ('index', 'Python.tex', 'Sphinx Tests Documentation', + 'Georg Brandl', 'howto') + ]}) +def test_latex_toplevel_sectioning_is_chapter_with_howto(app, status, warning): + app.builder.build_all() + result = (app.outdir / 'Python.tex').text(encoding='utf8') + print(result) + print(status.getvalue()) + print(warning.getvalue()) + assert '\\section{Foo}' in result + + @pytest.mark.sphinx( 'latex', testroot='toctree-maxdepth', confoverrides={'latex_toplevel_sectioning': 'section'}) @@ -1039,17 +1071,3 @@ def test_latex_image_in_parsed_literal(app, status, warning): assert ('{\\sphinxunactivateextrasandspace \\raisebox{-0.5\\height}' '{\\scalebox{2.000000}{\\sphinxincludegraphics[height=1cm]{{pic}.png}}}' '}AFTER') in result - - -@pytest.mark.sphinx('latex', testroot='latex-toplevel') -def test_latex_toplevel_is_part(app, status, warning): - app.builder.build_all() - - result = (app.outdir / 'SphinxManual.tex').text(encoding='utf8') - assert ('\\part{First part}') in result - assert ('\\chapter{This is chapter}') in result - assert ('\\section{This is section}') in result - - result = (app.outdir / 'SphinxHowTo.tex').text(encoding='utf8') - assert ('\\part{This is a part}') in result - assert ('\\section{This is a section}') in result From dab7b49cd95c97d3efc5d6fd09ffdefc6155aad3 Mon Sep 17 00:00:00 2001 From: jfbu Date: Wed, 20 Dec 2017 22:19:35 +0100 Subject: [PATCH 161/275] Correct merge error in writers/latex.py --- sphinx/writers/latex.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 26a1b904e..54f288d61 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -552,8 +552,6 @@ class LaTeXTranslator(nodes.NodeVisitor): self.elements.update({ 'releasename': _('Release'), }) - if builder.config.latex_keep_old_macro_names: - self.elements['sphinxpkgoptions'] = '' # we assume LaTeX class provides \chapter command except in case # of non-Japanese 'howto' case From 8c72f98c784328ffa3d400b5fc4b119449585d2d Mon Sep 17 00:00:00 2001 From: jfbu Date: Wed, 20 Dec 2017 22:45:22 +0100 Subject: [PATCH 162/275] Update CHANGES for PR #4316 --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 1b8289784..271e935f2 100644 --- a/CHANGES +++ b/CHANGES @@ -34,6 +34,8 @@ Bugs fixed remote image * #1421: Respect the quiet flag in sphinx-quickstart * #4281: Race conditions when creating output directory +* #4315: For PDF 'howto' documents, ``latex_toplevel_sectioning='part'`` generates + ``\chapter`` commands Testing -------- From 7ea4fa535a0e40a3ca16d78b706e376dea275030 Mon Sep 17 00:00:00 2001 From: jfbu Date: Sun, 17 Dec 2017 00:23:54 +0100 Subject: [PATCH 163/275] Make LaTeX obey numfig_secnum_depth for figures, tables, code-blocks Notes: - also fixes #4314 - although numbering of figures, tables and code-blocks will be same as in html, due to issue #4318 the numbering of enclosing sectioning units themselves may go deeper in html than PDF via latex. But this commit makes sure numbering goes to minimal depth needed by numfig_secnum_depth --- doc/config.rst | 11 ++--- sphinx/texinputs/sphinx.sty | 99 ++++++++++++++++++++++++++++++++----- sphinx/writers/latex.py | 34 +++++++++++-- 3 files changed, 123 insertions(+), 21 deletions(-) diff --git a/doc/config.rst b/doc/config.rst index 2ca622211..881387b48 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -341,20 +341,19 @@ General configuration starting at ``1``. - if ``1`` (default) numbers will be ``x.1``, ``x.2``, ... with ``x`` the section number (top level sectioning; no ``x.`` if no section). - This naturally applies only if section numbering has been activated via + This naturally applies only if section numbering has been activated via the ``:numbered:`` option of the :rst:dir:`toctree` directive. - ``2`` means that numbers will be ``x.y.1``, ``x.y.2``, ... if located in a sub-section (but still ``x.1``, ``x.2``, ... if located directly under a section and ``1``, ``2``, ... if not in any top level section.) - etc... - .. note:: - - The LaTeX builder currently ignores this configuration setting. It will - obey it at Sphinx 1.7. - .. versionadded:: 1.3 + .. versionchanged:: 1.7 + The LaTeX builder obeys this setting (if :confval:`numfig` is set to + ``True``). + .. confval:: tls_verify If true, Sphinx verifies server certifications. Default is ``True``. diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 80b81f6d6..f890b40f8 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -183,7 +183,7 @@ % control caption around literal-block \RequirePackage{capt-of} \RequirePackage{needspace} - +\RequirePackage{remreset}% provides \@removefromreset % to make pdf with correct encoded bookmarks in Japanese % this should precede the hyperref package \ifx\kanjiskip\@undefined @@ -247,7 +247,9 @@ \fi \DeclareStringOption[0]{maxlistdepth}% \newcommand*\spx@opt@maxlistdepth{0} - +\DeclareStringOption[-1]{numfigreset} +\DeclareBoolOption[false]{nonumfigreset} +% \DeclareBoolOption[false]{usespart}% not used % dimensions, we declare the \dimen registers here. \newdimen\sphinxverbatimsep \newdimen\sphinxverbatimborder @@ -349,6 +351,8 @@ \ProcessKeyvalOptions* % don't allow use of maxlistdepth via \sphinxsetup. \DisableKeyvalOption{sphinx}{maxlistdepth} +\DisableKeyvalOption{sphinx}{numfigreset} +\DisableKeyvalOption{sphinx}{nonumfigreset} % user interface: options can be changed midway in a document! \newcommand\sphinxsetup[1]{\setkeys{sphinx}{#1}} @@ -657,6 +661,7 @@ {\abovecaptionskip\smallskipamount \belowcaptionskip\smallskipamount} + %% FOOTNOTES % % Support large numbered footnotes in minipage @@ -665,6 +670,87 @@ \def\thempfootnote{\arabic{mpfootnote}} +%% NUMBERING OF FIGURES, TABLES, AND LITERAL BLOCKS +\ltx@ifundefined{c@chapter} + {\newcounter{literalblock}}% + {\newcounter{literalblock}[chapter]% + \def\theliteralblock{\ifnum\c@chapter>\z@\arabic{chapter}.\fi + \arabic{literalblock}}% + }% +\ifspx@opt@nonumfigreset + \ltx@ifundefined{c@chapter}{}{% + \@removefromreset{figure}{chapter}% + \@removefromreset{table}{chapter}% + \@removefromreset{literalblock}{chapter}% + }% + \def\thefigure{\arabic{figure}}% + \def\thetable {\arabic{table}}% + \def\theliteralblock{\arabic{literalblock}}% + %\let\theHliteralblock\theliteralblock +\else +\let\spx@preAthefigure\@empty +\let\spx@preBthefigure\@empty +% \ifspx@opt@usespart % <-- LaTeX writer could pass such a 'usespart' boolean +% % as sphinx.sty package option +% If document uses \part, (triggered in Sphinx by latex_toplevel_sectioning) +% LaTeX core per default does not reset chapter or section +% counters at each part. +% But if we modify this, we need to redefine \thechapter, \thesection to +% include the part number and this will cause problems in table of contents +% because of too wide numbering. Simplest is to do nothing. +% \fi +\ifnum\spx@opt@numfigreset>0 + \ltx@ifundefined{c@chapter} + {} + {\g@addto@macro\spx@preAthefigure{\ifnum\c@chapter>\z@\arabic{chapter}.}% + \g@addto@macro\spx@preBthefigure{\fi}}% +\fi +\ifnum\spx@opt@numfigreset>1 + \@addtoreset{figure}{section}% + \@addtoreset{table}{section}% + \@addtoreset{literalblock}{section}% + \g@addto@macro\spx@preAthefigure{\ifnum\c@section>\z@\arabic{section}.}% + \g@addto@macro\spx@preBthefigure{\fi}% +\fi +\ifnum\spx@opt@numfigreset>2 + \@addtoreset{figure}{subsection}% + \@addtoreset{table}{subsection}% + \@addtoreset{literalblock}{subsection}% + \g@addto@macro\spx@preAthefigure{\ifnum\c@subsection>\z@\arabic{subsection}.}% + \g@addto@macro\spx@preBthefigure{\fi}% +\fi +\ifnum\spx@opt@numfigreset>3 + \@addtoreset{figure}{subsubsection}% + \@addtoreset{table}{subsubsection}% + \@addtoreset{literalblock}{subsubsection}% + \g@addto@macro\spx@preAthefigure{\ifnum\c@subsubsection>\z@\arabic{subsubsection}.}% + \g@addto@macro\spx@preBthefigure{\fi}% +\fi +\ifnum\spx@opt@numfigreset>4 + \@addtoreset{figure}{paragraph}% + \@addtoreset{table}{paragraph}% + \@addtoreset{literalblock}{paragraph}% + \g@addto@macro\spx@preAthefigure{\ifnum\c@subparagraph>\z@\arabic{subparagraph}.}% + \g@addto@macro\spx@preBthefigure{\fi}% +\fi +\ifnum\spx@opt@numfigreset>5 + \@addtoreset{figure}{subparagraph}% + \@addtoreset{table}{subparagraph}% + \@addtoreset{literalblock}{subparagraph}% + \g@addto@macro\spx@preAthefigure{\ifnum\c@subsubparagraph>\z@\arabic{subsubparagraph}.}% + \g@addto@macro\spx@preBthefigure{\fi}% +\fi +\expandafter\g@addto@macro +\expandafter\spx@preAthefigure\expandafter{\spx@preBthefigure}% +\let\thefigure\spx@preAthefigure +\let\thetable\spx@preAthefigure +\let\theliteralblock\spx@preAthefigure +\g@addto@macro\thefigure{\arabic{figure}}% +\g@addto@macro\thetable{\arabic{table}}% +\g@addto@macro\theliteralblock{\arabic{literalblock}}% +\fi + + %% LITERAL BLOCKS % % Based on use of "fancyvrb.sty"'s Verbatim. @@ -680,15 +766,6 @@ \let\endOriginalVerbatim\endVerbatim % for captions of literal blocks -% also define `\theH...` macros for hyperref -\newcounter{literalblock} -\ltx@ifundefined{c@chapter} - {\@addtoreset{literalblock}{section} - \def\theliteralblock {\ifnum\c@section>\z@ \thesection.\fi\arabic{literalblock}} - \def\theHliteralblock {\theHsection.\arabic{literalblock}}} - {\@addtoreset{literalblock}{chapter} - \def\theliteralblock {\ifnum\c@chapter>\z@ \thechapter.\fi\arabic{literalblock}} - \def\theHliteralblock {\theHchapter.\arabic{literalblock}}} % at start of caption title \newcommand*{\fnum@literalblock}{\literalblockname\nobreakspace\theliteralblock} % this will be overwritten in document preamble by Babel translation diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 54f288d61..95938cc50 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -48,7 +48,6 @@ BEGIN_DOC = r''' URI_SCHEMES = ('mailto:', 'http:', 'https:', 'ftp:') -SECNUMDEPTH = 3 LATEXSECTIONNAMES = ["part", "chapter", "section", "subsection", "subsubsection", "paragraph", "subparagraph"] @@ -504,6 +503,8 @@ def rstdim_to_latexdim(width_str): class LaTeXTranslator(nodes.NodeVisitor): + secnumdepth = 2 # legacy sphinxhowto.cls uses this, whereas article.cls + # default is originally 3. For book/report, 2 is already LaTeX default. ignore_missing_images = False # sphinx specific document classes @@ -581,6 +582,24 @@ class LaTeXTranslator(nodes.NodeVisitor): else: self.elements['date'] = format_date(builder.config.today_fmt or _('%b %d, %Y'), # type: ignore # NOQA language=builder.config.language) + + if builder.config.numfig: + self.numfig_secnum_depth = builder.config.numfig_secnum_depth + if self.numfig_secnum_depth > 0: # default is 1 + # numfig_secnum_depth as passed to sphinx.sty indices same names as in + # LATEXSECTIONNAMES but with -1 for part, 0 for chapter, 1 for section... + if len(self.sectionnames) < 7 and self.top_sectionlevel > 0: + self.numfig_secnum_depth += self.top_sectionlevel + else: + self.numfig_secnum_depth += self.top_sectionlevel - 1 + if self.numfig_secnum_depth >= len(self.sectionnames): + self.numfig_secnum_depth = len(self.sectionnames) - 1 + # if passed key value is < 1 LaTeX will act as if 0; see sphinx.sty + self.elements['sphinxpkgoptions'] += \ + (',numfigreset=%s' % self.numfig_secnum_depth) + else: + self.elements['sphinxpkgoptions'] += ',nonumfigreset' + if builder.config.latex_logo: # no need for \\noindent here, used in flushright self.elements['logo'] = '\\sphinxincludegraphics{%s}\\par' % \ @@ -637,6 +656,8 @@ class LaTeXTranslator(nodes.NodeVisitor): return '\\usepackage{%s}' % (packagename,) usepackages = (declare_package(*p) for p in builder.usepackages) self.elements['usepackages'] += "\n".join(usepackages) + + minsecnumdepth = self.secnumdepth # 2 from legacy sphinx manual/howto if document.get('tocdepth'): # reduce tocdepth if `part` or `chapter` is used for top_sectionlevel # tocdepth = -1: show only parts @@ -653,9 +674,14 @@ class LaTeXTranslator(nodes.NodeVisitor): tocdepth = 5 self.elements['tocdepth'] = '\\setcounter{tocdepth}{%d}' % tocdepth - if tocdepth >= SECNUMDEPTH: - # Increase secnumdepth if tocdepth is deeper than default SECNUMDEPTH - self.elements['secnumdepth'] = '\\setcounter{secnumdepth}{%d}' % tocdepth + minsecnumdepth = max(minsecnumdepth, tocdepth) + + if builder.config.numfig and (builder.config.numfig_secnum_depth > 0): + minsecnumdepth = max(minsecnumdepth, self.numfig_secnum_depth - 1) + + if minsecnumdepth > self.secnumdepth: + self.elements['secnumdepth'] = '\\setcounter{secnumdepth}{%d}' %\ + minsecnumdepth if getattr(document.settings, 'contentsname', None): self.elements['contentsname'] = \ From 43bed034cd1b19340125388f5e2d5b81f28d9345 Mon Sep 17 00:00:00 2001 From: jfbu Date: Mon, 18 Dec 2017 13:02:09 +0100 Subject: [PATCH 164/275] Add test for latex obey numfig_secnum_depth feature --- tests/roots/test-latex-numfig/conf.py | 10 +++++ tests/roots/test-latex-numfig/index.rst | 9 +++++ tests/roots/test-latex-numfig/indexhowto.rst | 10 +++++ tests/roots/test-latex-numfig/indexmanual.rst | 13 +++++++ tests/test_build_latex.py | 37 +++++++++++++++++++ 5 files changed, 79 insertions(+) create mode 100644 tests/roots/test-latex-numfig/conf.py create mode 100644 tests/roots/test-latex-numfig/index.rst create mode 100644 tests/roots/test-latex-numfig/indexhowto.rst create mode 100644 tests/roots/test-latex-numfig/indexmanual.rst diff --git a/tests/roots/test-latex-numfig/conf.py b/tests/roots/test-latex-numfig/conf.py new file mode 100644 index 000000000..61ea52b42 --- /dev/null +++ b/tests/roots/test-latex-numfig/conf.py @@ -0,0 +1,10 @@ +# -*- coding: utf-8 -*- + +master_doc = 'index' + +latex_documents = [ + ('indexmanual', 'SphinxManual.tex', 'Test numfig manual', + 'Sphinx', 'manual'), + ('indexhowto', 'SphinxHowTo.tex', 'Test numfig howto', + 'Sphinx', 'howto'), +] diff --git a/tests/roots/test-latex-numfig/index.rst b/tests/roots/test-latex-numfig/index.rst new file mode 100644 index 000000000..6b8b9688c --- /dev/null +++ b/tests/roots/test-latex-numfig/index.rst @@ -0,0 +1,9 @@ +================= +test-latex-numfig +================= + +.. toctree:: + :numbered: + + indexmanual + indexhowto diff --git a/tests/roots/test-latex-numfig/indexhowto.rst b/tests/roots/test-latex-numfig/indexhowto.rst new file mode 100644 index 000000000..4749f1ecd --- /dev/null +++ b/tests/roots/test-latex-numfig/indexhowto.rst @@ -0,0 +1,10 @@ +======================= +test-latex-numfig-howto +======================= + +This is a part +============== + +This is a section +----------------- + diff --git a/tests/roots/test-latex-numfig/indexmanual.rst b/tests/roots/test-latex-numfig/indexmanual.rst new file mode 100644 index 000000000..8bab4fbfd --- /dev/null +++ b/tests/roots/test-latex-numfig/indexmanual.rst @@ -0,0 +1,13 @@ +======================== +test-latex-numfig-manual +======================== + +First part +========== + +This is chapter +--------------- + +This is section +~~~~~~~~~~~~~~~ + diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index bf6082705..ca96d10ec 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -335,6 +335,43 @@ def test_numref_with_language_ja(app, status, warning): '\\nameref{\\detokenize{foo:foo}}}') in result +@pytest.mark.sphinx('latex', testroot='latex-numfig') +def test_latex_obey_numfig_is_false(app, status, warning): + app.builder.build_all() + + result = (app.outdir / 'SphinxManual.tex').text(encoding='utf8') + assert '\\usepackage{sphinx}' in result + + result = (app.outdir / 'SphinxHowTo.tex').text(encoding='utf8') + assert '\\usepackage{sphinx}' in result + + +@pytest.mark.sphinx( + 'latex', testroot='latex-numfig', + confoverrides={'numfig': True, 'numfig_secnum_depth': 0}) +def test_latex_obey_numfig_secnum_depth_is_zero(app, status, warning): + app.builder.build_all() + + result = (app.outdir / 'SphinxManual.tex').text(encoding='utf8') + assert '\\usepackage[,nonumfigreset]{sphinx}' in result + + result = (app.outdir / 'SphinxHowTo.tex').text(encoding='utf8') + assert '\\usepackage[,nonumfigreset]{sphinx}' in result + + +@pytest.mark.sphinx( + 'latex', testroot='latex-numfig', + confoverrides={'numfig': True, 'numfig_secnum_depth': 2}) +def test_latex_obey_numfig_secnum_depth_is_two(app, status, warning): + app.builder.build_all() + + result = (app.outdir / 'SphinxManual.tex').text(encoding='utf8') + assert '\\usepackage[,numfigreset=2]{sphinx}' in result + + result = (app.outdir / 'SphinxHowTo.tex').text(encoding='utf8') + assert '\\usepackage[,numfigreset=3]{sphinx}' in result + + @pytest.mark.sphinx('latex') def test_latex_add_latex_package(app, status, warning): app.add_latex_package('foo') From 91350f35faa4761aae04f11b5505cecaaf9560e5 Mon Sep 17 00:00:00 2001 From: jfbu Date: Wed, 20 Dec 2017 23:55:56 +0100 Subject: [PATCH 165/275] Remove hard-coded numbers to let LATEXSECTIONNAMES become patchable --- sphinx/writers/latex.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 95938cc50..70d394623 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -588,12 +588,14 @@ class LaTeXTranslator(nodes.NodeVisitor): if self.numfig_secnum_depth > 0: # default is 1 # numfig_secnum_depth as passed to sphinx.sty indices same names as in # LATEXSECTIONNAMES but with -1 for part, 0 for chapter, 1 for section... - if len(self.sectionnames) < 7 and self.top_sectionlevel > 0: + if len(self.sectionnames) < len(LATEXSECTIONNAMES) and \ + self.top_sectionlevel > 0: self.numfig_secnum_depth += self.top_sectionlevel else: self.numfig_secnum_depth += self.top_sectionlevel - 1 - if self.numfig_secnum_depth >= len(self.sectionnames): - self.numfig_secnum_depth = len(self.sectionnames) - 1 + # this (minus one) will serve as minimum to LaTeX's secnumdepth + self.numfig_secnum_depth = min(self.numfig_secnum_depth, + len(LATEXSECTIONNAMES) - 1) # if passed key value is < 1 LaTeX will act as if 0; see sphinx.sty self.elements['sphinxpkgoptions'] += \ (',numfigreset=%s' % self.numfig_secnum_depth) @@ -665,13 +667,13 @@ class LaTeXTranslator(nodes.NodeVisitor): # tocdepth = 1: show parts, chapters and sections # tocdepth = 2: show parts, chapters, sections and subsections # ... - tocdepth = document['tocdepth'] + self.top_sectionlevel - 2 - if len(self.sectionnames) < 7 and self.top_sectionlevel > 0: + if len(self.sectionnames) < len(LATEXSECTIONNAMES) and \ + self.top_sectionlevel > 0: tocdepth += 1 # because top_sectionlevel is shifted by -1 - if tocdepth > 5: # 5 corresponds to subparagraph + if tocdepth > len(LATEXSECTIONNAMES) - 2: # default is 5 <-> subparagraph logger.warning('too large :maxdepth:, ignored.') - tocdepth = 5 + tocdepth = len(LATEXSECTIONNAMES) - 2 self.elements['tocdepth'] = '\\setcounter{tocdepth}{%d}' % tocdepth minsecnumdepth = max(minsecnumdepth, tocdepth) From c7a4283ff7fd906035405b4cf99810b3a2bc4862 Mon Sep 17 00:00:00 2001 From: jfbu Date: Thu, 21 Dec 2017 00:04:40 +0100 Subject: [PATCH 166/275] Update CHANGES for PR #4311 --- CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index a5701f4fc..d4e08333d 100644 --- a/CHANGES +++ b/CHANGES @@ -50,6 +50,7 @@ Features added * #3160: html: Use ```` to represent ``:kbd:`` role * #4212: autosummary: catch all exceptions when importing modules * #3991, #4080: Add :confval:`math_numfig` for equation numbering by section +* #4311: Let LaTeX obey :confval:`numfig_secnum_depth` for figures, tables, ... Features removed @@ -91,6 +92,8 @@ Bugs fixed * #4094: C++, allow empty template argument lists. * C++, also hyperlink types in the name of declarations with qualified names. * C++, do not add index entries for declarations inside concepts. +* #4314: For PDF 'howto' documents, numbering of code-blocks differs from the + one of figures and tables Testing -------- From 24c9103a2cfb58da19362689f39f649e46027f45 Mon Sep 17 00:00:00 2001 From: jfbu Date: Thu, 21 Dec 2017 00:19:23 +0100 Subject: [PATCH 167/275] Update CHANGES --- CHANGES | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index d4e08333d..1d6c3994f 100644 --- a/CHANGES +++ b/CHANGES @@ -49,7 +49,8 @@ Features added * HTML themes can set up default sidebars through ``theme.conf`` * #3160: html: Use ```` to represent ``:kbd:`` role * #4212: autosummary: catch all exceptions when importing modules -* #3991, #4080: Add :confval:`math_numfig` for equation numbering by section +* #4166: Add :confval:`math_numfig` for equation numbering by section (refs: + #3991, #4080). Thanks to Oliver Jahn. * #4311: Let LaTeX obey :confval:`numfig_secnum_depth` for figures, tables, ... From ec240614d9d47546f8640afb922753ca15f5e9e4 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 17 Dec 2017 10:35:51 +0900 Subject: [PATCH 168/275] test_autodoc: Separate testdata (python objects) and testcases --- .../roots/test-ext-autodoc/target/__init__.py | 225 ++++++++++ tests/roots/test-root/autodoc.txt | 4 +- tests/roots/test-root/autodoc_target.py | 225 ++++++++++ tests/test_autodoc.py | 399 ++++-------------- tests/test_build_html.py | 4 +- tests/test_build_html5.py | 4 +- tests/test_ext_coverage.py | 16 +- 7 files changed, 557 insertions(+), 320 deletions(-) create mode 100644 tests/roots/test-ext-autodoc/target/__init__.py create mode 100644 tests/roots/test-root/autodoc_target.py diff --git a/tests/roots/test-ext-autodoc/target/__init__.py b/tests/roots/test-ext-autodoc/target/__init__.py new file mode 100644 index 000000000..bd00bf183 --- /dev/null +++ b/tests/roots/test-ext-autodoc/target/__init__.py @@ -0,0 +1,225 @@ +# -*- coding: utf-8 -*- + +import enum +from six import StringIO, add_metaclass +from sphinx.ext.autodoc import add_documenter # NOQA + + +__all__ = ['Class'] + +#: documentation for the integer +integer = 1 + + +def raises(exc, func, *args, **kwds): + """Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*.""" + pass + + +class CustomEx(Exception): + """My custom exception.""" + + def f(self): + """Exception method.""" + + +class CustomDataDescriptor(object): + """Descriptor class docstring.""" + + def __init__(self, doc): + self.__doc__ = doc + + def __get__(self, obj, type=None): + if obj is None: + return self + return 42 + + def meth(self): + """Function.""" + return "The Answer" + + +class CustomDataDescriptorMeta(type): + """Descriptor metaclass docstring.""" + + +@add_metaclass(CustomDataDescriptorMeta) +class CustomDataDescriptor2(CustomDataDescriptor): + """Descriptor class with custom metaclass docstring.""" + + +def _funky_classmethod(name, b, c, d, docstring=None): + """Generates a classmethod for a class from a template by filling out + some arguments.""" + def template(cls, a, b, c, d=4, e=5, f=6): + return a, b, c, d, e, f + from functools import partial + function = partial(template, b=b, c=c, d=d) + function.__name__ = name + function.__doc__ = docstring + return classmethod(function) + + +class Base(object): + def inheritedmeth(self): + """Inherited function.""" + + +class Derived(Base): + def inheritedmeth(self): + # no docstring here + pass + + +class Class(Base): + """Class to document.""" + + descr = CustomDataDescriptor("Descriptor instance docstring.") + + def meth(self): + """Function.""" + + def undocmeth(self): + pass + + def skipmeth(self): + """Method that should be skipped.""" + + def excludemeth(self): + """Method that should be excluded.""" + + # should not be documented + skipattr = 'foo' + + #: should be documented -- süß + attr = 'bar' + + @property + def prop(self): + """Property.""" + + docattr = 'baz' + """should likewise be documented -- süß""" + + udocattr = 'quux' + u"""should be documented as well - süß""" + + # initialized to any class imported from another module + mdocattr = StringIO() + """should be documented as well - süß""" + + roger = _funky_classmethod("roger", 2, 3, 4) + + moore = _funky_classmethod("moore", 9, 8, 7, + docstring="moore(a, e, f) -> happiness") + + def __init__(self, arg): + self.inst_attr_inline = None #: an inline documented instance attr + #: a documented instance attribute + self.inst_attr_comment = None + self.inst_attr_string = None + """a documented instance attribute""" + self._private_inst_attr = None #: a private instance attribute + + def __special1__(self): + """documented special method""" + + def __special2__(self): + # undocumented special method + pass + + +class CustomDict(dict): + """Docstring.""" + + +def function(foo, *args, **kwds): + """ + Return spam. + """ + pass + + +class Outer(object): + """Foo""" + + class Inner(object): + """Foo""" + + def meth(self): + """Foo""" + + # should be documented as an alias + factory = dict + + +class DocstringSig(object): + def meth(self): + """meth(FOO, BAR=1) -> BAZ +First line of docstring + + rest of docstring + """ + + def meth2(self): + """First line, no signature + Second line followed by indentation:: + + indented line + """ + + @property + def prop1(self): + """DocstringSig.prop1(self) + First line of docstring + """ + return 123 + + @property + def prop2(self): + """First line of docstring + Second line of docstring + """ + return 456 + + +class StrRepr(str): + def __repr__(self): + return self + + +class AttCls(object): + a1 = StrRepr('hello\nworld') + a2 = None + + +class InstAttCls(object): + """Class with documented class and instance attributes.""" + + #: Doc comment for class attribute InstAttCls.ca1. + #: It can have multiple lines. + ca1 = 'a' + + ca2 = 'b' #: Doc comment for InstAttCls.ca2. One line only. + + ca3 = 'c' + """Docstring for class attribute InstAttCls.ca3.""" + + def __init__(self): + #: Doc comment for instance attribute InstAttCls.ia1 + self.ia1 = 'd' + + self.ia2 = 'e' + """Docstring for instance attribute InstAttCls.ia2.""" + + +class EnumCls(enum.Enum): + """ + this is enum class + """ + + #: doc for val1 + val1 = 12 + val2 = 23 #: doc for val2 + val3 = 34 + """doc for val3""" diff --git a/tests/roots/test-root/autodoc.txt b/tests/roots/test-root/autodoc.txt index aa0dffba1..3c83ebf6e 100644 --- a/tests/roots/test-root/autodoc.txt +++ b/tests/roots/test-root/autodoc.txt @@ -5,7 +5,7 @@ Just testing a few autodoc possibilities... .. automodule:: util -.. automodule:: test_autodoc +.. automodule:: autodoc_target :members: .. autofunction:: function @@ -34,7 +34,7 @@ Just testing a few autodoc possibilities... .. autoclass:: MarkupError -.. currentmodule:: test_autodoc +.. currentmodule:: autodoc_target .. autoclass:: InstAttCls :members: diff --git a/tests/roots/test-root/autodoc_target.py b/tests/roots/test-root/autodoc_target.py new file mode 100644 index 000000000..bd00bf183 --- /dev/null +++ b/tests/roots/test-root/autodoc_target.py @@ -0,0 +1,225 @@ +# -*- coding: utf-8 -*- + +import enum +from six import StringIO, add_metaclass +from sphinx.ext.autodoc import add_documenter # NOQA + + +__all__ = ['Class'] + +#: documentation for the integer +integer = 1 + + +def raises(exc, func, *args, **kwds): + """Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*.""" + pass + + +class CustomEx(Exception): + """My custom exception.""" + + def f(self): + """Exception method.""" + + +class CustomDataDescriptor(object): + """Descriptor class docstring.""" + + def __init__(self, doc): + self.__doc__ = doc + + def __get__(self, obj, type=None): + if obj is None: + return self + return 42 + + def meth(self): + """Function.""" + return "The Answer" + + +class CustomDataDescriptorMeta(type): + """Descriptor metaclass docstring.""" + + +@add_metaclass(CustomDataDescriptorMeta) +class CustomDataDescriptor2(CustomDataDescriptor): + """Descriptor class with custom metaclass docstring.""" + + +def _funky_classmethod(name, b, c, d, docstring=None): + """Generates a classmethod for a class from a template by filling out + some arguments.""" + def template(cls, a, b, c, d=4, e=5, f=6): + return a, b, c, d, e, f + from functools import partial + function = partial(template, b=b, c=c, d=d) + function.__name__ = name + function.__doc__ = docstring + return classmethod(function) + + +class Base(object): + def inheritedmeth(self): + """Inherited function.""" + + +class Derived(Base): + def inheritedmeth(self): + # no docstring here + pass + + +class Class(Base): + """Class to document.""" + + descr = CustomDataDescriptor("Descriptor instance docstring.") + + def meth(self): + """Function.""" + + def undocmeth(self): + pass + + def skipmeth(self): + """Method that should be skipped.""" + + def excludemeth(self): + """Method that should be excluded.""" + + # should not be documented + skipattr = 'foo' + + #: should be documented -- süß + attr = 'bar' + + @property + def prop(self): + """Property.""" + + docattr = 'baz' + """should likewise be documented -- süß""" + + udocattr = 'quux' + u"""should be documented as well - süß""" + + # initialized to any class imported from another module + mdocattr = StringIO() + """should be documented as well - süß""" + + roger = _funky_classmethod("roger", 2, 3, 4) + + moore = _funky_classmethod("moore", 9, 8, 7, + docstring="moore(a, e, f) -> happiness") + + def __init__(self, arg): + self.inst_attr_inline = None #: an inline documented instance attr + #: a documented instance attribute + self.inst_attr_comment = None + self.inst_attr_string = None + """a documented instance attribute""" + self._private_inst_attr = None #: a private instance attribute + + def __special1__(self): + """documented special method""" + + def __special2__(self): + # undocumented special method + pass + + +class CustomDict(dict): + """Docstring.""" + + +def function(foo, *args, **kwds): + """ + Return spam. + """ + pass + + +class Outer(object): + """Foo""" + + class Inner(object): + """Foo""" + + def meth(self): + """Foo""" + + # should be documented as an alias + factory = dict + + +class DocstringSig(object): + def meth(self): + """meth(FOO, BAR=1) -> BAZ +First line of docstring + + rest of docstring + """ + + def meth2(self): + """First line, no signature + Second line followed by indentation:: + + indented line + """ + + @property + def prop1(self): + """DocstringSig.prop1(self) + First line of docstring + """ + return 123 + + @property + def prop2(self): + """First line of docstring + Second line of docstring + """ + return 456 + + +class StrRepr(str): + def __repr__(self): + return self + + +class AttCls(object): + a1 = StrRepr('hello\nworld') + a2 = None + + +class InstAttCls(object): + """Class with documented class and instance attributes.""" + + #: Doc comment for class attribute InstAttCls.ca1. + #: It can have multiple lines. + ca1 = 'a' + + ca2 = 'b' #: Doc comment for InstAttCls.ca2. One line only. + + ca3 = 'c' + """Docstring for class attribute InstAttCls.ca3.""" + + def __init__(self): + #: Doc comment for instance attribute InstAttCls.ia1 + self.ia1 = 'd' + + self.ia2 = 'e' + """Docstring for instance attribute InstAttCls.ia2.""" + + +class EnumCls(enum.Enum): + """ + this is enum class + """ + + #: doc for val1 + val1 = 12 + val2 = 23 #: doc for val2 + val3 = 34 + """doc for val3""" diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index 989c367b6..6bd22df86 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -10,13 +10,12 @@ :license: BSD, see LICENSE for details. """ +import sys from six import PY3 from sphinx.testing.util import SphinxTestApp, Struct # NOQA import pytest -import enum -from six import StringIO, add_metaclass from docutils.statemachine import ViewList from sphinx.ext.autodoc import AutoDirective, add_documenter, \ @@ -27,18 +26,23 @@ app = None @pytest.fixture(scope='module', autouse=True) def setup_module(rootdir, sphinx_test_tempdir): - global app - srcdir = sphinx_test_tempdir / 'autodoc-root' - if not srcdir.exists(): - (rootdir/'test-root').copytree(srcdir) - app = SphinxTestApp(srcdir=srcdir) - app.builder.env.app = app - app.builder.env.temp_data['docname'] = 'dummy' - app.connect('autodoc-process-docstring', process_docstring) - app.connect('autodoc-process-signature', process_signature) - app.connect('autodoc-skip-member', skip_member) - yield - app.cleanup() + try: + global app + srcdir = sphinx_test_tempdir / 'autodoc-root' + if not srcdir.exists(): + (rootdir / 'test-root').copytree(srcdir) + testroot = rootdir / 'test-ext-autodoc' + sys.path.append(testroot) + app = SphinxTestApp(srcdir=srcdir) + app.builder.env.app = app + app.builder.env.temp_data['docname'] = 'dummy' + app.connect('autodoc-process-docstring', process_docstring) + app.connect('autodoc-process-signature', process_signature) + app.connect('autodoc-skip-member', skip_member) + yield + finally: + app.cleanup() + sys.path.remove(testroot) directive = options = None @@ -431,6 +435,8 @@ def test_get_doc(): directive.env.config.autoclass_content = 'both' assert getdocl('class', I) == ['Class docstring', '', 'New docstring'] + from target import Base, Derived + # NOTE: inspect.getdoc seems not to work with locally defined classes directive.env.config.autodoc_inherit_docstrings = False assert getdocl('method', Base.inheritedmeth) == ['Inherited function.'] @@ -508,24 +514,24 @@ def test_docstring_property_processing(): directive.env.config.autodoc_docstring_signature = False results, docstrings = \ - genarate_docstring('attribute', 'test_autodoc.DocstringSig.prop1') + genarate_docstring('attribute', 'target.DocstringSig.prop1') assert '.. py:attribute:: DocstringSig.prop1' in results assert 'First line of docstring' in docstrings assert 'DocstringSig.prop1(self)' in docstrings results, docstrings = \ - genarate_docstring('attribute', 'test_autodoc.DocstringSig.prop2') + genarate_docstring('attribute', 'target.DocstringSig.prop2') assert '.. py:attribute:: DocstringSig.prop2' in results assert 'First line of docstring' in docstrings assert 'Second line of docstring' in docstrings directive.env.config.autodoc_docstring_signature = True results, docstrings = \ - genarate_docstring('attribute', 'test_autodoc.DocstringSig.prop1') + genarate_docstring('attribute', 'target.DocstringSig.prop1') assert '.. py:attribute:: DocstringSig.prop1' in results assert 'First line of docstring' in docstrings assert 'DocstringSig.prop1(self)' not in docstrings results, docstrings = \ - genarate_docstring('attribute', 'test_autodoc.DocstringSig.prop2') + genarate_docstring('attribute', 'target.DocstringSig.prop2') assert '.. py:attribute:: DocstringSig.prop2' in results assert 'First line of docstring' in docstrings assert 'Second line of docstring' in docstrings @@ -556,11 +562,13 @@ def test_new_documenter(): del directive.result[:] options.members = ['integer'] - assert_result_contains('.. py:data:: integer', 'module', 'test_autodoc') + assert_result_contains('.. py:data:: integer', 'module', 'target') @pytest.mark.usefixtures('setup_test') def test_attrgetter_using(): + from target import Class + def assert_getter_works(objtype, name, obj, attrs=[], **kw): getattr_spy = [] @@ -585,10 +593,10 @@ def test_attrgetter_using(): options.members = ALL options.inherited_members = False - assert_getter_works('class', 'test_autodoc.Class', Class, ['meth']) + assert_getter_works('class', 'target.Class', Class, ['meth']) options.inherited_members = True - assert_getter_works('class', 'test_autodoc.Class', Class, ['meth', 'inheritedmeth']) + assert_getter_works('class', 'target.Class', Class, ['meth', 'inheritedmeth']) @pytest.mark.usefixtures('setup_test') @@ -655,11 +663,11 @@ def test_generate(): assert_warns("failed to import function 'foobar' from module 'util'", 'function', 'util.foobar', more_content=None) # method missing - assert_warns("failed to import method 'Class.foobar' from module 'test_autodoc';", - 'method', 'test_autodoc.Class.foobar', more_content=None) + assert_warns("failed to import method 'Class.foobar' from module 'target';", + 'method', 'target.Class.foobar', more_content=None) # test auto and given content mixing - directive.env.ref_context['py:module'] = 'test_autodoc' + directive.env.ref_context['py:module'] = 'target' assert_result_contains(' Function.', 'method', 'Class.meth') add_content = ViewList() add_content.append('Content.', '', 0) @@ -674,63 +682,63 @@ def test_generate(): assert len(directive.result) == 0 # assert that exceptions can be documented - assert_works('exception', 'test_autodoc.CustomEx', all_members=True) - assert_works('exception', 'test_autodoc.CustomEx') + assert_works('exception', 'target.CustomEx', all_members=True) + assert_works('exception', 'target.CustomEx') # test diverse inclusion settings for members - should = [('class', 'test_autodoc.Class')] + should = [('class', 'target.Class')] assert_processes(should, 'class', 'Class') - should.extend([('method', 'test_autodoc.Class.meth')]) + should.extend([('method', 'target.Class.meth')]) options.members = ['meth'] options.exclude_members = set(['excludemeth']) assert_processes(should, 'class', 'Class') - should.extend([('attribute', 'test_autodoc.Class.prop'), - ('attribute', 'test_autodoc.Class.descr'), - ('attribute', 'test_autodoc.Class.attr'), - ('attribute', 'test_autodoc.Class.docattr'), - ('attribute', 'test_autodoc.Class.udocattr'), - ('attribute', 'test_autodoc.Class.mdocattr'), - ('attribute', 'test_autodoc.Class.inst_attr_comment'), - ('attribute', 'test_autodoc.Class.inst_attr_inline'), - ('attribute', 'test_autodoc.Class.inst_attr_string'), - ('method', 'test_autodoc.Class.moore'), + should.extend([('attribute', 'target.Class.prop'), + ('attribute', 'target.Class.descr'), + ('attribute', 'target.Class.attr'), + ('attribute', 'target.Class.docattr'), + ('attribute', 'target.Class.udocattr'), + ('attribute', 'target.Class.mdocattr'), + ('attribute', 'target.Class.inst_attr_comment'), + ('attribute', 'target.Class.inst_attr_inline'), + ('attribute', 'target.Class.inst_attr_string'), + ('method', 'target.Class.moore'), ]) options.members = ALL assert_processes(should, 'class', 'Class') options.undoc_members = True - should.extend((('attribute', 'test_autodoc.Class.skipattr'), - ('method', 'test_autodoc.Class.undocmeth'), - ('method', 'test_autodoc.Class.roger'))) + should.extend((('attribute', 'target.Class.skipattr'), + ('method', 'target.Class.undocmeth'), + ('method', 'target.Class.roger'))) assert_processes(should, 'class', 'Class') options.inherited_members = True - should.append(('method', 'test_autodoc.Class.inheritedmeth')) + should.append(('method', 'target.Class.inheritedmeth')) assert_processes(should, 'class', 'Class') # test special members options.special_members = ['__special1__'] - should.append(('method', 'test_autodoc.Class.__special1__')) + should.append(('method', 'target.Class.__special1__')) assert_processes(should, 'class', 'Class') options.special_members = ALL - should.append(('method', 'test_autodoc.Class.__special2__')) + should.append(('method', 'target.Class.__special2__')) assert_processes(should, 'class', 'Class') options.special_members = False options.members = [] # test module flags - assert_result_contains('.. py:module:: test_autodoc', - 'module', 'test_autodoc') + assert_result_contains('.. py:module:: target', + 'module', 'target') options.synopsis = 'Synopsis' - assert_result_contains(' :synopsis: Synopsis', 'module', 'test_autodoc') + assert_result_contains(' :synopsis: Synopsis', 'module', 'target') options.deprecated = True - assert_result_contains(' :deprecated:', 'module', 'test_autodoc') + assert_result_contains(' :deprecated:', 'module', 'target') options.platform = 'Platform' - assert_result_contains(' :platform: Platform', 'module', 'test_autodoc') + assert_result_contains(' :platform: Platform', 'module', 'target') # test if __all__ is respected for modules options.members = ALL - assert_result_contains('.. py:class:: Class(arg)', 'module', 'test_autodoc') + assert_result_contains('.. py:class:: Class(arg)', 'module', 'target') try: assert_result_contains('.. py:exception:: CustomEx', - 'module', 'test_autodoc') + 'module', 'target') except AssertionError: pass else: @@ -739,7 +747,7 @@ def test_generate(): # test noindex flag options.members = [] options.noindex = True - assert_result_contains(' :noindex:', 'module', 'test_autodoc') + assert_result_contains(' :noindex:', 'module', 'target') assert_result_contains(' :noindex:', 'class', 'Base') # okay, now let's get serious about mixing Python and C signature stuff @@ -747,14 +755,14 @@ def test_generate(): all_members=True) # test inner class handling - assert_processes([('class', 'test_autodoc.Outer'), - ('class', 'test_autodoc.Outer.Inner'), - ('method', 'test_autodoc.Outer.Inner.meth')], + assert_processes([('class', 'target.Outer'), + ('class', 'target.Outer.Inner'), + ('method', 'target.Outer.Inner.meth')], 'class', 'Outer', all_members=True) # test descriptor docstrings assert_result_contains(' Descriptor instance docstring.', - 'attribute', 'test_autodoc.Class.descr') + 'attribute', 'target.Class.descr') # test generation for C modules (which have no source file) directive.env.ref_context['py:module'] = 'time' @@ -762,7 +770,7 @@ def test_generate(): assert_processes([('function', 'time.asctime')], 'function', 'asctime') # test autodoc_member_order == 'source' - directive.env.ref_context['py:module'] = 'test_autodoc' + directive.env.ref_context['py:module'] = 'target' options.private_members = True if PY3: roger_line = ' .. py:classmethod:: Class.roger(a, *, b=2, c=3, d=4, e=5, f=6)' @@ -788,7 +796,7 @@ def test_generate(): del directive.env.ref_context['py:module'] # test attribute initialized to class instance from other module - directive.env.temp_data['autodoc:class'] = 'test_autodoc.Class' + directive.env.temp_data['autodoc:class'] = 'target.Class' assert_result_contains(u' should be documented as well - s\xfc\xdf', 'attribute', 'mdocattr') del directive.env.temp_data['autodoc:class'] @@ -796,25 +804,25 @@ def test_generate(): # test autodoc_docstring_signature assert_result_contains( '.. py:method:: DocstringSig.meth(FOO, BAR=1) -> BAZ', 'method', - 'test_autodoc.DocstringSig.meth') + 'target.DocstringSig.meth') assert_result_contains( - ' rest of docstring', 'method', 'test_autodoc.DocstringSig.meth') + ' rest of docstring', 'method', 'target.DocstringSig.meth') assert_result_contains( '.. py:method:: DocstringSig.meth2()', 'method', - 'test_autodoc.DocstringSig.meth2') + 'target.DocstringSig.meth2') assert_result_contains( ' indented line', 'method', - 'test_autodoc.DocstringSig.meth2') + 'target.DocstringSig.meth2') assert_result_contains( '.. py:classmethod:: Class.moore(a, e, f) -> happiness', 'method', - 'test_autodoc.Class.moore') + 'target.Class.moore') # test new attribute documenter behavior - directive.env.ref_context['py:module'] = 'test_autodoc' + directive.env.ref_context['py:module'] = 'target' options.undoc_members = True - assert_processes([('class', 'test_autodoc.AttCls'), - ('attribute', 'test_autodoc.AttCls.a1'), - ('attribute', 'test_autodoc.AttCls.a2'), + assert_processes([('class', 'target.AttCls'), + ('attribute', 'target.AttCls.a1'), + ('attribute', 'target.AttCls.a2'), ], 'class', 'AttCls') assert_result_contains( ' :annotation: = hello world', 'attribute', 'AttCls.a1') @@ -824,40 +832,40 @@ def test_generate(): # test explicit members with instance attributes del directive.env.temp_data['autodoc:class'] del directive.env.temp_data['autodoc:module'] - directive.env.ref_context['py:module'] = 'test_autodoc' + directive.env.ref_context['py:module'] = 'target' options.inherited_members = False options.undoc_members = False options.members = ALL assert_processes([ - ('class', 'test_autodoc.InstAttCls'), - ('attribute', 'test_autodoc.InstAttCls.ca1'), - ('attribute', 'test_autodoc.InstAttCls.ca2'), - ('attribute', 'test_autodoc.InstAttCls.ca3'), - ('attribute', 'test_autodoc.InstAttCls.ia1'), - ('attribute', 'test_autodoc.InstAttCls.ia2'), + ('class', 'target.InstAttCls'), + ('attribute', 'target.InstAttCls.ca1'), + ('attribute', 'target.InstAttCls.ca2'), + ('attribute', 'target.InstAttCls.ca3'), + ('attribute', 'target.InstAttCls.ia1'), + ('attribute', 'target.InstAttCls.ia2'), ], 'class', 'InstAttCls') del directive.env.temp_data['autodoc:class'] del directive.env.temp_data['autodoc:module'] options.members = ['ca1', 'ia1'] assert_processes([ - ('class', 'test_autodoc.InstAttCls'), - ('attribute', 'test_autodoc.InstAttCls.ca1'), - ('attribute', 'test_autodoc.InstAttCls.ia1'), + ('class', 'target.InstAttCls'), + ('attribute', 'target.InstAttCls.ca1'), + ('attribute', 'target.InstAttCls.ia1'), ], 'class', 'InstAttCls') del directive.env.temp_data['autodoc:class'] del directive.env.temp_data['autodoc:module'] del directive.env.ref_context['py:module'] # test members with enum attributes - directive.env.ref_context['py:module'] = 'test_autodoc' + directive.env.ref_context['py:module'] = 'target' options.inherited_members = False options.undoc_members = False options.members = ALL assert_processes([ - ('class', 'test_autodoc.EnumCls'), - ('attribute', 'test_autodoc.EnumCls.val1'), - ('attribute', 'test_autodoc.EnumCls.val2'), - ('attribute', 'test_autodoc.EnumCls.val3'), + ('class', 'target.EnumCls'), + ('attribute', 'target.EnumCls.val1'), + ('attribute', 'target.EnumCls.val2'), + ('attribute', 'target.EnumCls.val3'), ], 'class', 'EnumCls') assert_result_contains( ' :annotation: = 12', 'attribute', 'EnumCls.val1') @@ -871,11 +879,11 @@ def test_generate(): # test descriptor class documentation options.members = ['CustomDataDescriptor', 'CustomDataDescriptor2'] assert_result_contains('.. py:class:: CustomDataDescriptor(doc)', - 'module', 'test_autodoc') + 'module', 'target') assert_result_contains(' .. py:method:: CustomDataDescriptor.meth()', - 'module', 'test_autodoc') + 'module', 'target') assert_result_contains('.. py:class:: CustomDataDescriptor2(doc)', - 'module', 'test_autodoc') + 'module', 'target') # test mocked module imports options.members = ['TestAutodoc'] @@ -887,224 +895,3 @@ def test_generate(): options.members = ['decoratedFunction'] assert_result_contains('.. py:function:: decoratedFunction()', 'module', 'autodoc_missing_imports') - - -# --- generate fodder ------------ -__all__ = ['Class'] - -#: documentation for the integer -integer = 1 - - -def raises(exc, func, *args, **kwds): - """Raise AssertionError if ``func(*args, **kwds)`` does not raise *exc*.""" - pass - - -class CustomEx(Exception): - """My custom exception.""" - - def f(self): - """Exception method.""" - - -class CustomDataDescriptor(object): - """Descriptor class docstring.""" - - def __init__(self, doc): - self.__doc__ = doc - - def __get__(self, obj, type=None): - if obj is None: - return self - return 42 - - def meth(self): - """Function.""" - return "The Answer" - - -class CustomDataDescriptorMeta(type): - """Descriptor metaclass docstring.""" - - -@add_metaclass(CustomDataDescriptorMeta) -class CustomDataDescriptor2(CustomDataDescriptor): - """Descriptor class with custom metaclass docstring.""" - - -def _funky_classmethod(name, b, c, d, docstring=None): - """Generates a classmethod for a class from a template by filling out - some arguments.""" - def template(cls, a, b, c, d=4, e=5, f=6): - return a, b, c, d, e, f - from functools import partial - function = partial(template, b=b, c=c, d=d) - function.__name__ = name - function.__doc__ = docstring - return classmethod(function) - - -class Base(object): - def inheritedmeth(self): - """Inherited function.""" - - -class Derived(Base): - def inheritedmeth(self): - # no docstring here - pass - - -class Class(Base): - """Class to document.""" - - descr = CustomDataDescriptor("Descriptor instance docstring.") - - def meth(self): - """Function.""" - - def undocmeth(self): - pass - - def skipmeth(self): - """Method that should be skipped.""" - - def excludemeth(self): - """Method that should be excluded.""" - - # should not be documented - skipattr = 'foo' - - #: should be documented -- süß - attr = 'bar' - - @property - def prop(self): - """Property.""" - - docattr = 'baz' - """should likewise be documented -- süß""" - - udocattr = 'quux' - u"""should be documented as well - süß""" - - # initialized to any class imported from another module - mdocattr = StringIO() - """should be documented as well - süß""" - - roger = _funky_classmethod("roger", 2, 3, 4) - - moore = _funky_classmethod("moore", 9, 8, 7, - docstring="moore(a, e, f) -> happiness") - - def __init__(self, arg): - self.inst_attr_inline = None #: an inline documented instance attr - #: a documented instance attribute - self.inst_attr_comment = None - self.inst_attr_string = None - """a documented instance attribute""" - self._private_inst_attr = None #: a private instance attribute - - def __special1__(self): - """documented special method""" - - def __special2__(self): - # undocumented special method - pass - - -class CustomDict(dict): - """Docstring.""" - - -def function(foo, *args, **kwds): - """ - Return spam. - """ - pass - - -class Outer(object): - """Foo""" - - class Inner(object): - """Foo""" - - def meth(self): - """Foo""" - - # should be documented as an alias - factory = dict - - -class DocstringSig(object): - def meth(self): - """meth(FOO, BAR=1) -> BAZ -First line of docstring - - rest of docstring - """ - - def meth2(self): - """First line, no signature - Second line followed by indentation:: - - indented line - """ - - @property - def prop1(self): - """DocstringSig.prop1(self) - First line of docstring - """ - return 123 - - @property - def prop2(self): - """First line of docstring - Second line of docstring - """ - return 456 - - -class StrRepr(str): - def __repr__(self): - return self - - -class AttCls(object): - a1 = StrRepr('hello\nworld') - a2 = None - - -class InstAttCls(object): - """Class with documented class and instance attributes.""" - - #: Doc comment for class attribute InstAttCls.ca1. - #: It can have multiple lines. - ca1 = 'a' - - ca2 = 'b' #: Doc comment for InstAttCls.ca2. One line only. - - ca3 = 'c' - """Docstring for class attribute InstAttCls.ca3.""" - - def __init__(self): - #: Doc comment for instance attribute InstAttCls.ia1 - self.ia1 = 'd' - - self.ia2 = 'e' - """Docstring for instance attribute InstAttCls.ia2.""" - - -class EnumCls(enum.Enum): - """ - this is enum class - """ - - #: doc for val1 - val1 = 12 - val2 = 23 #: doc for val2 - val3 = 34 - """doc for val3""" diff --git a/tests/test_build_html.py b/tests/test_build_html.py index b4fec18ba..2d56ba5c6 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -182,8 +182,8 @@ def test_html_warnings(app, warning): r'-| |-'), ], 'autodoc.html': [ - (".//dt[@id='test_autodoc.Class']", ''), - (".//dt[@id='test_autodoc.function']/em", r'\*\*kwds'), + (".//dt[@id='autodoc_target.Class']", ''), + (".//dt[@id='autodoc_target.function']/em", r'\*\*kwds'), (".//dd/p", r'Return spam\.'), ], 'extapi.html': [ diff --git a/tests/test_build_html5.py b/tests/test_build_html5.py index 39b064b1c..6128af843 100644 --- a/tests/test_build_html5.py +++ b/tests/test_build_html5.py @@ -90,8 +90,8 @@ def cached_etree_parse(): r'-| |-'), ], 'autodoc.html': [ - (".//dt[@id='test_autodoc.Class']", ''), - (".//dt[@id='test_autodoc.function']/em", r'\*\*kwds'), + (".//dt[@id='autodoc_target.Class']", ''), + (".//dt[@id='autodoc_target.function']/em", r'\*\*kwds'), (".//dd/p", r'Return spam\.'), ], 'extapi.html': [ diff --git a/tests/test_ext_coverage.py b/tests/test_ext_coverage.py index ff3fb4c02..ed1f2e787 100644 --- a/tests/test_ext_coverage.py +++ b/tests/test_ext_coverage.py @@ -21,9 +21,9 @@ def test_build(app, status, warning): py_undoc = (app.outdir / 'python.txt').text() assert py_undoc.startswith('Undocumented Python objects\n' '===========================\n') - assert 'test_autodoc\n------------\n' in py_undoc + assert 'autodoc_target\n--------------\n' in py_undoc assert ' * Class -- missing methods:\n' in py_undoc - assert ' * process_docstring\n' in py_undoc + assert ' * raises\n' in py_undoc assert ' * function\n' not in py_undoc # these two are documented assert ' * Class\n' not in py_undoc # in autodoc.txt @@ -40,9 +40,9 @@ def test_build(app, status, warning): # the key is the full path to the header file, which isn't testable assert list(undoc_c.values())[0] == set([('function', 'Py_SphinxTest')]) - assert 'test_autodoc' in undoc_py - assert 'funcs' in undoc_py['test_autodoc'] - assert 'process_docstring' in undoc_py['test_autodoc']['funcs'] - assert 'classes' in undoc_py['test_autodoc'] - assert 'Class' in undoc_py['test_autodoc']['classes'] - assert 'undocmeth' in undoc_py['test_autodoc']['classes']['Class'] + assert 'autodoc_target' in undoc_py + assert 'funcs' in undoc_py['autodoc_target'] + assert 'raises' in undoc_py['autodoc_target']['funcs'] + assert 'classes' in undoc_py['autodoc_target'] + assert 'Class' in undoc_py['autodoc_target']['classes'] + assert 'undocmeth' in undoc_py['autodoc_target']['classes']['Class'] From 201c59126fc7e4083f83acdcffd4c4ca7ceeddc0 Mon Sep 17 00:00:00 2001 From: jfbu Date: Thu, 21 Dec 2017 09:21:07 +0100 Subject: [PATCH 169/275] Set LaTeX default tocdepth to 2 for howto documents (fixes #4330) Memo: for Japanese documents, jreport.cls already does that, so this commit changes nothing. However as the class uses ``\chapter``, this means that by default howto documents table of contents in PDF have three levels, whereas manual documents only have two. --- sphinx/texinputs/sphinxhowto.cls | 1 + 1 file changed, 1 insertion(+) diff --git a/sphinx/texinputs/sphinxhowto.cls b/sphinx/texinputs/sphinxhowto.cls index 90680fdee..11a49a205 100644 --- a/sphinx/texinputs/sphinxhowto.cls +++ b/sphinx/texinputs/sphinxhowto.cls @@ -25,6 +25,7 @@ % reset these counters in your preamble. % \setcounter{secnumdepth}{2} +\setcounter{tocdepth}{2}% i.e. section and subsection % Change the title page to look a bit better, and fit in with the fncychap % ``Bjarne'' style a bit better. From 3bb61e909476798bbbf303a8e957b4f1a0a5a87c Mon Sep 17 00:00:00 2001 From: jfbu Date: Thu, 21 Dec 2017 12:23:20 +0100 Subject: [PATCH 170/275] Let LaTeX obey :confval:`math_numfig` for equation numbering --- doc/ext/math.rst | 6 +++++- sphinx/texinputs/sphinx.sty | 28 ++++++++++++++++++++++++++- sphinx/writers/latex.py | 5 +++++ tests/roots/test-latex-numfig/conf.py | 2 ++ tests/test_build_latex.py | 21 ++++++++++++++++---- 5 files changed, 56 insertions(+), 6 deletions(-) diff --git a/doc/ext/math.rst b/doc/ext/math.rst index 10a26ccf4..635d48a3e 100644 --- a/doc/ext/math.rst +++ b/doc/ext/math.rst @@ -47,12 +47,16 @@ or use Python raw strings (``r"raw"``). .. confval:: math_numfig If ``True``, displayed math equations are numbered across pages in html and - related (epub, ...) output when :confval:`numfig` is enabled. + related (epub, ...) output (also with latex) when :confval:`numfig` is enabled. :confval:`numfig_secnum_depth` is respected. The :rst:role:`eq` role must be used to reference equation numbers, not the :rst:role:`numref` role. Default is ``True``. .. versionadded:: 1.7 + If ``False``, latex behaves as in former releases i.e. for ``'manual'`` + docclass (and ``'howto'`` for Japanese) it resets by default the + equation numbers per each toplevel section, and for ``'howto'`` it uses + continuous numbering across entire PDF. :mod:`.mathbase` defines these new markup elements: diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index f890b40f8..890ef60f7 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -249,6 +249,7 @@ \DeclareStringOption[0]{maxlistdepth}% \newcommand*\spx@opt@maxlistdepth{0} \DeclareStringOption[-1]{numfigreset} \DeclareBoolOption[false]{nonumfigreset} +\DeclareBoolOption[false]{mathnumfig} % \DeclareBoolOption[false]{usespart}% not used % dimensions, we declare the \dimen registers here. \newdimen\sphinxverbatimsep @@ -353,6 +354,7 @@ \DisableKeyvalOption{sphinx}{maxlistdepth} \DisableKeyvalOption{sphinx}{numfigreset} \DisableKeyvalOption{sphinx}{nonumfigreset} +\DisableKeyvalOption{sphinx}{mathnumfig} % user interface: options can be changed midway in a document! \newcommand\sphinxsetup[1]{\setkeys{sphinx}{#1}} @@ -682,11 +684,16 @@ \@removefromreset{figure}{chapter}% \@removefromreset{table}{chapter}% \@removefromreset{literalblock}{chapter}% + \ifspx@opt@mathnumfig + \@removefromreset{equation}{chapter}% + \fi }% \def\thefigure{\arabic{figure}}% \def\thetable {\arabic{table}}% \def\theliteralblock{\arabic{literalblock}}% - %\let\theHliteralblock\theliteralblock + \ifspx@opt@mathnumfig + \def\theequation{\arabic{equation}}% + \fi \else \let\spx@preAthefigure\@empty \let\spx@preBthefigure\@empty @@ -709,6 +716,9 @@ \@addtoreset{figure}{section}% \@addtoreset{table}{section}% \@addtoreset{literalblock}{section}% + \ifspx@opt@mathnumfig + \@addtoreset{equation}{section}% + \fi \g@addto@macro\spx@preAthefigure{\ifnum\c@section>\z@\arabic{section}.}% \g@addto@macro\spx@preBthefigure{\fi}% \fi @@ -716,6 +726,9 @@ \@addtoreset{figure}{subsection}% \@addtoreset{table}{subsection}% \@addtoreset{literalblock}{subsection}% + \ifspx@opt@mathnumfig + \@addtoreset{equation}{subsection}% + \fi \g@addto@macro\spx@preAthefigure{\ifnum\c@subsection>\z@\arabic{subsection}.}% \g@addto@macro\spx@preBthefigure{\fi}% \fi @@ -723,6 +736,9 @@ \@addtoreset{figure}{subsubsection}% \@addtoreset{table}{subsubsection}% \@addtoreset{literalblock}{subsubsection}% + \ifspx@opt@mathnumfig + \@addtoreset{equation}{subsubsection}% + \fi \g@addto@macro\spx@preAthefigure{\ifnum\c@subsubsection>\z@\arabic{subsubsection}.}% \g@addto@macro\spx@preBthefigure{\fi}% \fi @@ -730,6 +746,9 @@ \@addtoreset{figure}{paragraph}% \@addtoreset{table}{paragraph}% \@addtoreset{literalblock}{paragraph}% + \ifspx@opt@mathnumfig + \@addtoreset{equation}{paragraph}% + \fi \g@addto@macro\spx@preAthefigure{\ifnum\c@subparagraph>\z@\arabic{subparagraph}.}% \g@addto@macro\spx@preBthefigure{\fi}% \fi @@ -737,6 +756,9 @@ \@addtoreset{figure}{subparagraph}% \@addtoreset{table}{subparagraph}% \@addtoreset{literalblock}{subparagraph}% + \ifspx@opt@mathnumfig + \@addtoreset{equation}{subparagraph}% + \fi \g@addto@macro\spx@preAthefigure{\ifnum\c@subsubparagraph>\z@\arabic{subsubparagraph}.}% \g@addto@macro\spx@preBthefigure{\fi}% \fi @@ -748,6 +770,10 @@ \g@addto@macro\thefigure{\arabic{figure}}% \g@addto@macro\thetable{\arabic{table}}% \g@addto@macro\theliteralblock{\arabic{literalblock}}% + \ifspx@opt@mathnumfig + \let\theequation\spx@preAthefigure + \g@addto@macro\theequation{\arabic{equation}}% + \fi \fi diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 70d394623..3ef336520 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -601,6 +601,11 @@ class LaTeXTranslator(nodes.NodeVisitor): (',numfigreset=%s' % self.numfig_secnum_depth) else: self.elements['sphinxpkgoptions'] += ',nonumfigreset' + try: + if builder.config.math_numfig: + self.elements['sphinxpkgoptions'] += ',mathnumfig' + except: + pass if builder.config.latex_logo: # no need for \\noindent here, used in flushright diff --git a/tests/roots/test-latex-numfig/conf.py b/tests/roots/test-latex-numfig/conf.py index 61ea52b42..506186b26 100644 --- a/tests/roots/test-latex-numfig/conf.py +++ b/tests/roots/test-latex-numfig/conf.py @@ -2,6 +2,8 @@ master_doc = 'index' +extensions = ['sphinx.ext.imgmath'] # for math_numfig + latex_documents = [ ('indexmanual', 'SphinxManual.tex', 'Test numfig manual', 'Sphinx', 'manual'), diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index ca96d10ec..bf0e84c57 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -353,10 +353,10 @@ def test_latex_obey_numfig_secnum_depth_is_zero(app, status, warning): app.builder.build_all() result = (app.outdir / 'SphinxManual.tex').text(encoding='utf8') - assert '\\usepackage[,nonumfigreset]{sphinx}' in result + assert '\\usepackage[,nonumfigreset,mathnumfig]{sphinx}' in result result = (app.outdir / 'SphinxHowTo.tex').text(encoding='utf8') - assert '\\usepackage[,nonumfigreset]{sphinx}' in result + assert '\\usepackage[,nonumfigreset,mathnumfig]{sphinx}' in result @pytest.mark.sphinx( @@ -366,10 +366,23 @@ def test_latex_obey_numfig_secnum_depth_is_two(app, status, warning): app.builder.build_all() result = (app.outdir / 'SphinxManual.tex').text(encoding='utf8') - assert '\\usepackage[,numfigreset=2]{sphinx}' in result + assert '\\usepackage[,numfigreset=2,mathnumfig]{sphinx}' in result result = (app.outdir / 'SphinxHowTo.tex').text(encoding='utf8') - assert '\\usepackage[,numfigreset=3]{sphinx}' in result + assert '\\usepackage[,numfigreset=3,mathnumfig]{sphinx}' in result + + +@pytest.mark.sphinx( + 'latex', testroot='latex-numfig', + confoverrides={'numfig': True, 'math_numfig': False}) +def test_latex_obey_numfig_but_math_numfig_false(app, status, warning): + app.builder.build_all() + + result = (app.outdir / 'SphinxManual.tex').text(encoding='utf8') + assert '\\usepackage[,numfigreset=1]{sphinx}' in result + + result = (app.outdir / 'SphinxHowTo.tex').text(encoding='utf8') + assert '\\usepackage[,numfigreset=2]{sphinx}' in result @pytest.mark.sphinx('latex') From 7ec3a237628675b8421a57b7c87106d8c10e098c Mon Sep 17 00:00:00 2001 From: jfbu Date: Thu, 21 Dec 2017 12:43:53 +0100 Subject: [PATCH 171/275] Avoid using bare except --- sphinx/writers/latex.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 3ef336520..c93fd197e 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -604,7 +604,7 @@ class LaTeXTranslator(nodes.NodeVisitor): try: if builder.config.math_numfig: self.elements['sphinxpkgoptions'] += ',mathnumfig' - except: + except AttributeError: pass if builder.config.latex_logo: From e2e907b3ee68baada5d47aabe3f507cc0b8fa6df Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Fri, 22 Dec 2017 00:53:53 +0900 Subject: [PATCH 172/275] Fix broken test_autodoc --- tests/test_autodoc.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index cf3eb3926..d3c0a1f50 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -747,9 +747,8 @@ def test_generate(): # test ignore-module-all options.ignore_module_all = True - assert_result_contains('.. py:class:: Class(arg)', 'module', 'test_autodoc') - assert_result_contains('.. py:exception:: CustomEx', 'module', - 'test_autodoc') + assert_result_contains('.. py:class:: Class(arg)', 'module', 'target') + assert_result_contains('.. py:exception:: CustomEx', 'module', 'target') # test noindex flag options.members = [] From 5ca9d0578b726a9c4a921a448e5c114f5cd446ab Mon Sep 17 00:00:00 2001 From: jfbu Date: Thu, 21 Dec 2017 18:37:45 +0100 Subject: [PATCH 173/275] Update CHANGES for PR #4331 --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 9cddb98e0..b617835f5 100644 --- a/CHANGES +++ b/CHANGES @@ -96,6 +96,8 @@ Bugs fixed * C++, do not add index entries for declarations inside concepts. * #4314: For PDF 'howto' documents, numbering of code-blocks differs from the one of figures and tables +* #4330: PDF 'howto' documents have an incoherent default LaTeX tocdepth counter + setting Testing -------- From 8cbd66f8221cb1e8c5a93059631baf09c82e58c7 Mon Sep 17 00:00:00 2001 From: jfbu Date: Thu, 21 Dec 2017 18:47:35 +0100 Subject: [PATCH 174/275] Trim docs about math_numfig --- doc/ext/math.rst | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/doc/ext/math.rst b/doc/ext/math.rst index 635d48a3e..4097bb29e 100644 --- a/doc/ext/math.rst +++ b/doc/ext/math.rst @@ -46,17 +46,12 @@ or use Python raw strings (``r"raw"``). .. confval:: math_numfig - If ``True``, displayed math equations are numbered across pages in html and - related (epub, ...) output (also with latex) when :confval:`numfig` is enabled. - :confval:`numfig_secnum_depth` is respected. The :rst:role:`eq` role must - be used to reference equation numbers, not the :rst:role:`numref` role. - Default is ``True``. + If ``True``, displayed math equations are numbered across pages when + :confval:`numfig` is enabled. The :confval:`numfig_secnum_depth` setting + is respected. The :rst:role:`eq`, not :rst:role:`numref`, role + must be used to reference equation numbers. Default is ``True``. .. versionadded:: 1.7 - If ``False``, latex behaves as in former releases i.e. for ``'manual'`` - docclass (and ``'howto'`` for Japanese) it resets by default the - equation numbers per each toplevel section, and for ``'howto'`` it uses - continuous numbering across entire PDF. :mod:`.mathbase` defines these new markup elements: From 2d99648e9982325bbd670da11df5f809e3134284 Mon Sep 17 00:00:00 2001 From: Christer Bystrom Date: Thu, 21 Dec 2017 19:06:17 +0100 Subject: [PATCH 175/275] Closes #4334: sphinx-apidoc: Don't generate references to non-existing files in TOC --- CHANGES | 1 + sphinx/apidoc.py | 7 +- .../test-apidoc-toc/mypackage/__init__.py | 0 tests/roots/test-apidoc-toc/mypackage/main.py | 16 ++++ .../test-apidoc-toc/mypackage/no_init/foo.py | 1 + .../mypackage/resource/__init__.py | 0 .../mypackage/resource/resource.txt | 1 + .../mypackage/something/__init__.py | 1 + tests/test_apidoc.py | 77 +++++++++++++++++++ 9 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 tests/roots/test-apidoc-toc/mypackage/__init__.py create mode 100755 tests/roots/test-apidoc-toc/mypackage/main.py create mode 100644 tests/roots/test-apidoc-toc/mypackage/no_init/foo.py create mode 100644 tests/roots/test-apidoc-toc/mypackage/resource/__init__.py create mode 100644 tests/roots/test-apidoc-toc/mypackage/resource/resource.txt create mode 100644 tests/roots/test-apidoc-toc/mypackage/something/__init__.py diff --git a/CHANGES b/CHANGES index b7a16af4f..5b3600d1d 100644 --- a/CHANGES +++ b/CHANGES @@ -21,6 +21,7 @@ Features added Bugs fixed ---------- +* #4334: sphinx-apidoc: Don't generate references to non-existing files in TOC * #4206: latex: reST label between paragraphs loses paragraph break * #4231: html: Apply fixFirefoxAnchorBug only under Firefox * #4221: napoleon depends on autodoc, but users need to load it manually diff --git a/sphinx/apidoc.py b/sphinx/apidoc.py index 24ed874b0..335abe344 100644 --- a/sphinx/apidoc.py +++ b/sphinx/apidoc.py @@ -116,7 +116,12 @@ def create_package_file(root, master_package, subroot, py_files, opts, subs, is_ text += '\n' # build a list of directories that are szvpackages (contain an INITPY file) - subs = [sub for sub in subs if path.isfile(path.join(root, sub, INITPY))] + # and also checks the INITPY file is not empty, or there are other python + # source files in that folder. + # (depending on settings - but shall_skip() takes care of that) + subs = [sub for sub in subs if not + shall_skip(path.join(root, sub, INITPY), opts)] + # if there are some package directories, add a TOC for theses subpackages if subs: text += format_heading(2, 'Subpackages') diff --git a/tests/roots/test-apidoc-toc/mypackage/__init__.py b/tests/roots/test-apidoc-toc/mypackage/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/roots/test-apidoc-toc/mypackage/main.py b/tests/roots/test-apidoc-toc/mypackage/main.py new file mode 100755 index 000000000..5d3da04b9 --- /dev/null +++ b/tests/roots/test-apidoc-toc/mypackage/main.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python +import os + +import mod_resource + +import mod_something + + +if __name__ == "__main__": + print("Hello, world! -> something returns: {}".format(mod_something.something())) + + res_path = \ + os.path.join(os.path.dirname(mod_resource.__file__), 'resource.txt') + with open(res_path) as f: + text = f.read() + print("From mod_resource:resource.txt -> {}".format(text)) diff --git a/tests/roots/test-apidoc-toc/mypackage/no_init/foo.py b/tests/roots/test-apidoc-toc/mypackage/no_init/foo.py new file mode 100644 index 000000000..ce059b276 --- /dev/null +++ b/tests/roots/test-apidoc-toc/mypackage/no_init/foo.py @@ -0,0 +1 @@ +MESSAGE="There's no __init__.py in this folder, hence we should be left out" diff --git a/tests/roots/test-apidoc-toc/mypackage/resource/__init__.py b/tests/roots/test-apidoc-toc/mypackage/resource/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/roots/test-apidoc-toc/mypackage/resource/resource.txt b/tests/roots/test-apidoc-toc/mypackage/resource/resource.txt new file mode 100644 index 000000000..5b64c924d --- /dev/null +++ b/tests/roots/test-apidoc-toc/mypackage/resource/resource.txt @@ -0,0 +1 @@ +This is a text resource to be included in this otherwise empty module. No python contents here. \ No newline at end of file diff --git a/tests/roots/test-apidoc-toc/mypackage/something/__init__.py b/tests/roots/test-apidoc-toc/mypackage/something/__init__.py new file mode 100644 index 000000000..259184ba3 --- /dev/null +++ b/tests/roots/test-apidoc-toc/mypackage/something/__init__.py @@ -0,0 +1 @@ +"Subpackage Something" \ No newline at end of file diff --git a/tests/test_apidoc.py b/tests/test_apidoc.py index 20582e9fc..faceb715f 100644 --- a/tests/test_apidoc.py +++ b/tests/test_apidoc.py @@ -188,3 +188,80 @@ def test_extension_parsed(make_app, apidoc): with open(outdir / 'conf.py') as f: rst = f.read() assert "sphinx.ext.mathjax" in rst + + +@pytest.mark.apidoc( + coderoot='test-apidoc-toc', + options=["--implicit-namespaces"], +) +def test_toc_all_references_should_exist_pep420_enabled(make_app, apidoc): + """All references in toc should exist. This test doesn't say if + directories with empty __init__.py and and nothing else should be + skipped, just ensures consistency between what's referenced in the toc + and what is created. This is the variant with pep420 enabled. + """ + outdir = apidoc.outdir + assert (outdir / 'conf.py').isfile() + + toc = extract_toc(outdir / 'mypackage.rst') + + refs = [l.strip() for l in toc.splitlines() if l.strip()] + found_refs = [] + missing_files = [] + for ref in refs: + if ref and ref[0] in (':', '#'): + continue + found_refs.append(ref) + filename = "{}.rst".format(ref) + if not (outdir / filename).isfile(): + missing_files.append(filename) + + assert len(missing_files) == 0, \ + 'File(s) referenced in TOC not found: {}\n' \ + 'TOC:\n{}'.format(", ".join(missing_files), toc) + + +@pytest.mark.apidoc( + coderoot='test-apidoc-toc', +) +def test_toc_all_references_should_exist_pep420_disabled(make_app, apidoc): + """All references in toc should exist. This test doesn't say if + directories with empty __init__.py and and nothing else should be + skipped, just ensures consistency between what's referenced in the toc + and what is created. This is the variant with pep420 disabled. + """ + outdir = apidoc.outdir + assert (outdir / 'conf.py').isfile() + + toc = extract_toc(outdir / 'mypackage.rst') + + refs = [l.strip() for l in toc.splitlines() if l.strip()] + found_refs = [] + missing_files = [] + for ref in refs: + if ref and ref[0] in (':', '#'): + continue + filename = "{}.rst".format(ref) + found_refs.append(ref) + if not (outdir / filename).isfile(): + missing_files.append(filename) + + assert len(missing_files) == 0, \ + 'File(s) referenced in TOC not found: {}\n' \ + 'TOC:\n{}'.format(", ".join(missing_files), toc) + + +def extract_toc(path): + """Helper: Extract toc section from package rst file""" + with open(path) as f: + rst = f.read() + + # Read out the part containing the toctree + toctree_start = "\n.. toctree::\n" + toctree_end = "\nSubmodules" + + start_idx = rst.index(toctree_start) + end_idx = rst.index(toctree_end, start_idx) + toctree = rst[start_idx + len(toctree_start):end_idx] + + return toctree From 2e04c2a0588d1b9e7b1cf0d1b67e1a5496704960 Mon Sep 17 00:00:00 2001 From: jfbu Date: Thu, 21 Dec 2017 19:33:47 +0100 Subject: [PATCH 176/275] Update CHANGES for PR #4332 --- CHANGES | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index b617835f5..3b3bb7c17 100644 --- a/CHANGES +++ b/CHANGES @@ -51,8 +51,10 @@ Features added * #4212: autosummary: catch all exceptions when importing modules * #4166: Add :confval:`math_numfig` for equation numbering by section (refs: #3991, #4080). Thanks to Oliver Jahn. -* #4311: Let LaTeX obey :confval:`numfig_secnum_depth` for figures, tables, ... +* #4311: Let LaTeX obey :confval:`numfig_secnum_depth` for figures, tables, and + code-blocks * #947: autodoc now supports ignore-module-all to ignore a module's ``__all__`` +* #4332: Let LaTeX obey :confval:`math_numfig` for equation numbering Features removed From a9efb2517a0ccbd932f7e6be3e8984d78dc763b8 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 23 Dec 2017 21:20:32 +0900 Subject: [PATCH 177/275] Fix flake8 violations --- tests/test_autodoc.py | 2 +- tests/test_build.py | 4 +- tests/test_build_epub.py | 2 - tests/test_build_html.py | 1 - tests/test_build_latex.py | 11 +- tests/test_docutilsconf.py | 2 +- tests/test_domain_cpp.py | 438 +++++++++++++++++----------------- tests/test_environment.py | 2 +- tests/test_ext_autosummary.py | 3 +- tests/test_ext_graphviz.py | 2 + tests/test_ext_intersphinx.py | 1 - tests/test_ext_todo.py | 4 +- tests/test_intl.py | 1 + tests/test_quickstart.py | 1 - tests/test_util.py | 1 - tests/test_util_images.py | 16 +- tests/test_util_inspect.py | 1 - tests/test_versioning.py | 2 +- 18 files changed, 247 insertions(+), 247 deletions(-) diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index d3c0a1f50..8d67cdb6f 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -425,7 +425,7 @@ def test_get_doc(): # class has __init__ method without docstring and # __new__ method with docstring # class docstring: depends on config value which one is taken - class I: + class I: # NOQA """Class docstring""" def __new__(cls): """New docstring""" diff --git a/tests/test_build.py b/tests/test_build.py index 387e308a8..6892ddfad 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -34,8 +34,8 @@ def nonascii_srcdir(request, rootdir, sphinx_test_tempdir): basedir = sphinx_test_tempdir / request.node.originalname # Windows with versions prior to 3.2 (I think) doesn't support unicode on system path # so we force a non-unicode path in that case - if sys.platform == "win32" and \ - not (sys.version_info.major >= 3 and sys.version_info.minor >= 2): + if (sys.platform == "win32" and + not (sys.version_info.major >= 3 and sys.version_info.minor >= 2)): return basedir / 'all' try: srcdir = basedir / test_name diff --git a/tests/test_build_epub.py b/tests/test_build_epub.py index 397547734..e5d86b0ed 100644 --- a/tests/test_build_epub.py +++ b/tests/test_build_epub.py @@ -245,5 +245,3 @@ def test_epub_writing_mode(app): # vertical / writing-mode (CSS) css = (app.outdir / '_static' / 'epub.css').text() assert 'writing-mode: vertical-rl;' in css - - diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 2d56ba5c6..dafc1f09f 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -15,7 +15,6 @@ from itertools import cycle, chain from six import PY3 -from sphinx import __display_version__ from sphinx.util.inventory import InventoryFile from sphinx.testing.util import remove_unicode_literals, strip_escseq import xml.etree.cElementTree as ElementTree diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index bf0e84c57..5c0450810 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -773,6 +773,7 @@ def test_toctree_maxdepth_manual(app, status, warning): assert '\\setcounter{secnumdepth}' not in result assert '\\chapter{Foo}' in result + @pytest.mark.sphinx( 'latex', testroot='toctree-maxdepth', confoverrides={'latex_documents': [ @@ -789,6 +790,7 @@ def test_toctree_maxdepth_howto(app, status, warning): assert '\\setcounter{secnumdepth}' not in result assert '\\section{Foo}' in result + @pytest.mark.sphinx( 'latex', testroot='toctree-maxdepth', confoverrides={'master_doc': 'foo'}) @@ -802,6 +804,7 @@ def test_toctree_not_found(app, status, warning): assert '\\setcounter{secnumdepth}' not in result assert '\\chapter{Foo A}' in result + @pytest.mark.sphinx( 'latex', testroot='toctree-maxdepth', confoverrides={'master_doc': 'bar'}) @@ -858,8 +861,8 @@ def test_latex_toplevel_sectioning_is_part(app, status, warning): 'latex', testroot='toctree-maxdepth', confoverrides={'latex_toplevel_sectioning': 'part', 'latex_documents': [ - ('index', 'Python.tex', 'Sphinx Tests Documentation', - 'Georg Brandl', 'howto') + ('index', 'Python.tex', 'Sphinx Tests Documentation', + 'Georg Brandl', 'howto') ]}) def test_latex_toplevel_sectioning_is_part_with_howto(app, status, warning): app.builder.build_all() @@ -888,8 +891,8 @@ def test_latex_toplevel_sectioning_is_chapter(app, status, warning): 'latex', testroot='toctree-maxdepth', confoverrides={'latex_toplevel_sectioning': 'chapter', 'latex_documents': [ - ('index', 'Python.tex', 'Sphinx Tests Documentation', - 'Georg Brandl', 'howto') + ('index', 'Python.tex', 'Sphinx Tests Documentation', + 'Georg Brandl', 'howto') ]}) def test_latex_toplevel_sectioning_is_chapter_with_howto(app, status, warning): app.builder.build_all() diff --git a/tests/test_docutilsconf.py b/tests/test_docutilsconf.py index fd5cf7a61..bca41feea 100644 --- a/tests/test_docutilsconf.py +++ b/tests/test_docutilsconf.py @@ -72,7 +72,7 @@ def test_texinfo(app, status, warning): @pytest.mark.sphinx('html', testroot='docutilsconf', docutilsconf='[general]\nsource_link=true\n') -@pytest.mark.skip(sys.platform == "win32" and \ +@pytest.mark.skip(sys.platform == "win32" and not (sys.version_info.major >= 3 and sys.version_info.minor >= 2), reason="Python < 3.2 on Win32 doesn't handle non-ASCII paths right") def test_docutils_source_link_with_nonascii_file(app, status, warning): diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py index e4f3a678b..aed574daf 100644 --- a/tests/test_domain_cpp.py +++ b/tests/test_domain_cpp.py @@ -101,13 +101,13 @@ def test_fundamental_types(): if t == "std::nullptr_t": id = "NSt9nullptr_tE" return "1f%s" % id - check("function", "void f(%s arg)" % t, {1: makeIdV1(), 2:makeIdV2()}) + check("function", "void f(%s arg)" % t, {1: makeIdV1(), 2: makeIdV2()}) def test_expressions(): def exprCheck(expr, id): ids = 'IE1CIA%s_1aE' - check('class', 'template<> C' % expr, {2:ids % expr, 3:ids % id}) + check('class', 'template<> C' % expr, {2: ids % expr, 3: ids % id}) # primary exprCheck('nullptr', 'LDnE') exprCheck('true', 'L1E') @@ -118,9 +118,9 @@ def test_expressions(): for i in ints: for u in unsignedSuffix: for l in longSuffix: - expr = i + u + l; + expr = i + u + l exprCheck(expr, 'L' + expr + 'E') - expr = i + l + u; + expr = i + l + u exprCheck(expr, 'L' + expr + 'E') for suffix in ['', 'f', 'F', 'l', 'L']: expr = '5.0' + suffix @@ -200,55 +200,55 @@ def test_expressions(): # a < expression that starts with something that could be a template exprCheck('A < 42', 'lt1AL42E') check('function', 'template<> void f(A &v)', - {2:"IE1fR1AI1BX2EE", 3:"IE1fR1AI1BXL2EEE"}) + {2: "IE1fR1AI1BX2EE", 3: "IE1fR1AI1BXL2EEE"}) exprCheck('A<1>::value', 'N1AIXL1EEE5valueE') - check('class', "template A", {2:"I_iE1A"}) - check('enumerator', 'A = std::numeric_limits::max()', {2:"1A"}) + check('class', "template A", {2: "I_iE1A"}) + check('enumerator', 'A = std::numeric_limits::max()', {2: "1A"}) def test_type_definitions(): - check("type", "public bool b", {1:"b", 2:"1b"}, "bool b") - check("type", "bool A::b", {1:"A::b", 2:"N1A1bE"}) - check("type", "bool *b", {1:"b", 2:"1b"}) - check("type", "bool *const b", {1:"b", 2:"1b"}) - check("type", "bool *volatile const b", {1:"b", 2:"1b"}) - check("type", "bool *volatile const b", {1:"b", 2:"1b"}) - check("type", "bool *volatile const *b", {1:"b", 2:"1b"}) - check("type", "bool &b", {1:"b", 2:"1b"}) - check("type", "bool b[]", {1:"b", 2:"1b"}) - check("type", "std::pair coord", {1:"coord", 2:"5coord"}) - check("type", "long long int foo", {1:"foo", 2:"3foo"}) + check("type", "public bool b", {1: "b", 2: "1b"}, "bool b") + check("type", "bool A::b", {1: "A::b", 2: "N1A1bE"}) + check("type", "bool *b", {1: "b", 2: "1b"}) + check("type", "bool *const b", {1: "b", 2: "1b"}) + check("type", "bool *volatile const b", {1: "b", 2: "1b"}) + check("type", "bool *volatile const b", {1: "b", 2: "1b"}) + check("type", "bool *volatile const *b", {1: "b", 2: "1b"}) + check("type", "bool &b", {1: "b", 2: "1b"}) + check("type", "bool b[]", {1: "b", 2: "1b"}) + check("type", "std::pair coord", {1: "coord", 2: "5coord"}) + check("type", "long long int foo", {1: "foo", 2: "3foo"}) check("type", 'std::vector> module::blah', - {1:"module::blah", 2:"N6module4blahE"}) - check("type", "std::function F", {1:"F", 2:"1F"}) - check("type", "std::function F", {1:"F", 2:"1F"}) - check("type", "std::function F", {1:"F", 2:"1F"}) - check("type", "std::function F", {1:"F", 2:"1F"}) + {1: "module::blah", 2: "N6module4blahE"}) + check("type", "std::function F", {1: "F", 2: "1F"}) + check("type", "std::function F", {1: "F", 2: "1F"}) + check("type", "std::function F", {1: "F", 2: "1F"}) + check("type", "std::function F", {1: "F", 2: "1F"}) check("type", "MyContainer::const_iterator", - {1:"MyContainer::const_iterator", 2:"N11MyContainer14const_iteratorE"}) + {1: "MyContainer::const_iterator", 2: "N11MyContainer14const_iteratorE"}) check("type", "public MyContainer::const_iterator", - {1:"MyContainer::const_iterator", 2:"N11MyContainer14const_iteratorE"}, + {1: "MyContainer::const_iterator", 2: "N11MyContainer14const_iteratorE"}, output="MyContainer::const_iterator") # test decl specs on right - check("type", "bool const b", {1:"b", 2:"1b"}) + check("type", "bool const b", {1: "b", 2: "1b"}) # test name in global scope - check("type", "bool ::B::b", {1:"B::b", 2:"N1B1bE"}) + check("type", "bool ::B::b", {1: "B::b", 2: "N1B1bE"}) - check('type', 'A = B', {2:'1A'}) - check('type', 'A = decltype(b)', {2:'1A'}) + check('type', 'A = B', {2: '1A'}) + check('type', 'A = decltype(b)', {2: '1A'}) # from breathe#267 (named function parameters for function pointers check('type', 'void (*gpio_callback_t)(struct device *port, uint32_t pin)', - {1:'gpio_callback_t', 2:'15gpio_callback_t'}) - check('type', 'void (*f)(std::function g)', {1:'f', 2:'1f'}) + {1: 'gpio_callback_t', 2: '15gpio_callback_t'}) + check('type', 'void (*f)(std::function g)', {1: 'f', 2: '1f'}) def test_concept_definitions(): check('concept', 'template A::B::Concept', - {2:'I0EN1A1B7ConceptE'}) + {2: 'I0EN1A1B7ConceptE'}) check('concept', 'template Foo', - {2:'I00DpE3Foo'}) + {2: 'I00DpE3Foo'}) with pytest.raises(DefinitionError): parse('concept', 'Foo') with pytest.raises(DefinitionError): @@ -257,269 +257,270 @@ def test_concept_definitions(): def test_member_definitions(): check('member', ' const std::string & name = 42', - {1:"name__ssCR", 2:"4name"}, output='const std::string &name = 42') - check('member', ' const std::string & name', {1:"name__ssCR", 2:"4name"}, + {1: "name__ssCR", 2: "4name"}, output='const std::string &name = 42') + check('member', ' const std::string & name', {1: "name__ssCR", 2: "4name"}, output='const std::string &name') check('member', ' const std::string & name [ n ]', - {1:"name__ssCRA", 2:"4name"}, output='const std::string &name[n]') + {1: "name__ssCRA", 2: "4name"}, output='const std::string &name[n]') check('member', 'const std::vector< unsigned int, long> &name', - {1:"name__std::vector:unsigned-i.l:CR", 2:"4name"}, + {1: "name__std::vector:unsigned-i.l:CR", 2: "4name"}, output='const std::vector &name') - check('member', 'module::myclass foo[n]', {1:"foo__module::myclassA", 2:"3foo"}) - check('member', 'int *const p', {1:'p__iPC', 2:'1p'}) - check('member', 'extern int myInt', {1:'myInt__i', 2:'5myInt'}) - check('member', 'thread_local int myInt', {1:'myInt__i', 2:'5myInt'}) - check('member', 'extern thread_local int myInt', {1:'myInt__i', 2:'5myInt'}) - check('member', 'thread_local extern int myInt', {1:'myInt__i', 2:'5myInt'}, + check('member', 'module::myclass foo[n]', {1: "foo__module::myclassA", 2: "3foo"}) + check('member', 'int *const p', {1: 'p__iPC', 2: '1p'}) + check('member', 'extern int myInt', {1: 'myInt__i', 2: '5myInt'}) + check('member', 'thread_local int myInt', {1: 'myInt__i', 2: '5myInt'}) + check('member', 'extern thread_local int myInt', {1: 'myInt__i', 2: '5myInt'}) + check('member', 'thread_local extern int myInt', {1: 'myInt__i', 2: '5myInt'}, 'extern thread_local int myInt') def test_function_definitions(): - check('function', 'operator bool() const', {1:"castto-b-operatorC", 2:"NKcvbEv"}) + check('function', 'operator bool() const', {1: "castto-b-operatorC", 2: "NKcvbEv"}) check('function', 'A::operator bool() const', - {1:"A::castto-b-operatorC", 2:"NK1AcvbEv"}) + {1: "A::castto-b-operatorC", 2: "NK1AcvbEv"}) check('function', 'A::operator bool() volatile const &', - {1:"A::castto-b-operatorVCR", 2:"NVKR1AcvbEv"}) + {1: "A::castto-b-operatorVCR", 2: "NVKR1AcvbEv"}) check('function', 'A::operator bool() volatile const &&', - {1:"A::castto-b-operatorVCO", 2:"NVKO1AcvbEv"}) + {1: "A::castto-b-operatorVCO", 2: "NVKO1AcvbEv"}) check('function', 'bool namespaced::theclass::method(arg1, arg2)', - {1:"namespaced::theclass::method__arg1.arg2", - 2:"N10namespaced8theclass6methodE4arg14arg2"}) + {1: "namespaced::theclass::method__arg1.arg2", + 2: "N10namespaced8theclass6methodE4arg14arg2"}) x = 'std::vector> &module::test(register int ' \ 'foo, bar, std::string baz = "foobar, blah, bleh") const = 0' - check('function', x, {1:"module::test__i.bar.ssC", - 2:"NK6module4testEi3barNSt6stringE"}) + check('function', x, {1: "module::test__i.bar.ssC", + 2: "NK6module4testEi3barNSt6stringE"}) check('function', 'void f(std::pair)', - {1:"f__std::pair:A.B:", 2:"1fNSt4pairI1A1BEE"}) + {1: "f__std::pair:A.B:", 2: "1fNSt4pairI1A1BEE"}) check('function', 'explicit module::myclass::foo::foo()', - {1:"module::myclass::foo::foo", 2:"N6module7myclass3foo3fooEv"}) + {1: "module::myclass::foo::foo", 2: "N6module7myclass3foo3fooEv"}) check('function', 'module::myclass::foo::~foo()', - {1:"module::myclass::foo::~foo", 2:"N6module7myclass3fooD0Ev"}) + {1: "module::myclass::foo::~foo", 2: "N6module7myclass3fooD0Ev"}) check('function', 'int printf(const char *fmt, ...)', - {1:"printf__cCP.z", 2:"6printfPKcz"}) + {1: "printf__cCP.z", 2: "6printfPKcz"}) check('function', 'int foo(const unsigned int j)', - {1:"foo__unsigned-iC", 2:"3fooKj"}) + {1: "foo__unsigned-iC", 2: "3fooKj"}) check('function', 'int foo(const int *const ptr)', - {1:"foo__iCPC", 2:"3fooPCKi"}) + {1: "foo__iCPC", 2: "3fooPCKi"}) check('function', 'module::myclass::operator std::vector()', - {1:"module::myclass::castto-std::vector:ss:-operator", - 2:"N6module7myclasscvNSt6vectorINSt6stringEEEEv"}) + {1: "module::myclass::castto-std::vector:ss:-operator", + 2: "N6module7myclasscvNSt6vectorINSt6stringEEEEv"}) check('function', 'void operator()(const boost::array &v) const', - {1:"call-operator__boost::array:VertexID.2:CRC", - 2:"NKclERKN5boost5arrayI8VertexIDX2EEE", - 3:"NKclERKN5boost5arrayI8VertexIDXL2EEEE"}) + {1: "call-operator__boost::array:VertexID.2:CRC", + 2: "NKclERKN5boost5arrayI8VertexIDX2EEE", + 3: "NKclERKN5boost5arrayI8VertexIDXL2EEEE"}) check('function', 'void operator()(const boost::array &v) const', - {1:'call-operator__boost::array:VertexID.2."foo,--bar":CRC', - 2:'NKclERKN5boost5arrayI8VertexIDX2EX"foo, bar"EEE', - 3:'NKclERKN5boost5arrayI8VertexIDXL2EEXLA9_KcEEEE'}) + {1: 'call-operator__boost::array:VertexID.2."foo,--bar":CRC', + 2: 'NKclERKN5boost5arrayI8VertexIDX2EX"foo, bar"EEE', + 3: 'NKclERKN5boost5arrayI8VertexIDXL2EEXLA9_KcEEEE'}) check('function', 'MyClass::MyClass(MyClass::MyClass&&)', - {1:"MyClass::MyClass__MyClass::MyClassRR", - 2:"N7MyClass7MyClassERRN7MyClass7MyClassE"}) - check('function', 'constexpr int get_value()', {1:"get_valueCE", 2:"9get_valuev"}) + {1: "MyClass::MyClass__MyClass::MyClassRR", + 2: "N7MyClass7MyClassERRN7MyClass7MyClassE"}) + check('function', 'constexpr int get_value()', {1: "get_valueCE", 2: "9get_valuev"}) check('function', 'static constexpr int get_value()', - {1:"get_valueCE", 2:"9get_valuev"}) + {1: "get_valueCE", 2: "9get_valuev"}) check('function', 'int get_value() const noexcept', - {1:"get_valueC", 2:"NK9get_valueEv"}) + {1: "get_valueC", 2: "NK9get_valueEv"}) check('function', 'int get_value() const noexcept = delete', - {1:"get_valueC", 2:"NK9get_valueEv"}) + {1: "get_valueC", 2: "NK9get_valueEv"}) check('function', 'int get_value() volatile const', - {1:"get_valueVC", 2:"NVK9get_valueEv"}) + {1: "get_valueVC", 2: "NVK9get_valueEv"}) check('function', 'MyClass::MyClass(MyClass::MyClass&&) = default', - {1:"MyClass::MyClass__MyClass::MyClassRR", - 2:"N7MyClass7MyClassERRN7MyClass7MyClassE"}) + {1: "MyClass::MyClass__MyClass::MyClassRR", + 2: "N7MyClass7MyClassERRN7MyClass7MyClassE"}) check('function', 'virtual MyClass::a_virtual_function() const override', - {1:"MyClass::a_virtual_functionC", 2:"NK7MyClass18a_virtual_functionEv"}) - check('function', 'A B() override', {1:"B", 2:"1Bv"}) - check('function', 'A B() final', {1:"B", 2:"1Bv"}) - check('function', 'A B() final override', {1:"B", 2:"1Bv"}) - check('function', 'A B() override final', {1:"B", 2:"1Bv"}, + {1: "MyClass::a_virtual_functionC", 2: "NK7MyClass18a_virtual_functionEv"}) + check('function', 'A B() override', {1: "B", 2: "1Bv"}) + check('function', 'A B() final', {1: "B", 2: "1Bv"}) + check('function', 'A B() final override', {1: "B", 2: "1Bv"}) + check('function', 'A B() override final', {1: "B", 2: "1Bv"}, output='A B() final override') check('function', 'MyClass::a_member_function() volatile', - {1:"MyClass::a_member_functionV", 2:"NV7MyClass17a_member_functionEv"}) + {1: "MyClass::a_member_functionV", 2: "NV7MyClass17a_member_functionEv"}) check('function', 'MyClass::a_member_function() volatile const', - {1:"MyClass::a_member_functionVC", 2:"NVK7MyClass17a_member_functionEv"}) + {1: "MyClass::a_member_functionVC", 2: "NVK7MyClass17a_member_functionEv"}) check('function', 'MyClass::a_member_function() &&', - {1:"MyClass::a_member_functionO", 2:"NO7MyClass17a_member_functionEv"}) + {1: "MyClass::a_member_functionO", 2: "NO7MyClass17a_member_functionEv"}) check('function', 'MyClass::a_member_function() &', - {1:"MyClass::a_member_functionR", 2:"NR7MyClass17a_member_functionEv"}) + {1: "MyClass::a_member_functionR", 2: "NR7MyClass17a_member_functionEv"}) check('function', 'MyClass::a_member_function() const &', - {1:"MyClass::a_member_functionCR", 2:"NKR7MyClass17a_member_functionEv"}) + {1: "MyClass::a_member_functionCR", 2: "NKR7MyClass17a_member_functionEv"}) check('function', 'int main(int argc, char *argv[])', - {1:"main__i.cPA", 2:"4mainiA_Pc"}) + {1: "main__i.cPA", 2: "4mainiA_Pc"}) check('function', 'MyClass &MyClass::operator++()', - {1:"MyClass::inc-operator", 2:"N7MyClassppEv"}) + {1: "MyClass::inc-operator", 2: "N7MyClassppEv"}) check('function', 'MyClass::pointer MyClass::operator->()', - {1:"MyClass::pointer-operator", 2:"N7MyClassptEv"}) + {1: "MyClass::pointer-operator", 2: "N7MyClassptEv"}) x = 'std::vector> &module::test(register int ' \ 'foo, bar[n], std::string baz = "foobar, blah, bleh") const = 0' - check('function', x, {1:"module::test__i.barA.ssC", - 2:"NK6module4testEiAn_3barNSt6stringE", - 3:"NK6module4testEiA1n_3barNSt6stringE"}) + check('function', x, {1: "module::test__i.barA.ssC", + 2: "NK6module4testEiAn_3barNSt6stringE", + 3: "NK6module4testEiA1n_3barNSt6stringE"}) check('function', 'int foo(Foo f = Foo(double(), std::make_pair(int(2), double(3.4))))', - {1:"foo__Foo", 2:"3foo3Foo"}) - check('function', 'int foo(A a = x(a))', {1:"foo__A", 2:"3foo1A"}) + {1: "foo__Foo", 2: "3foo3Foo"}) + check('function', 'int foo(A a = x(a))', {1: "foo__A", 2: "3foo1A"}) with pytest.raises(DefinitionError): parse('function', 'int foo(B b=x(a)') with pytest.raises(DefinitionError): parse('function', 'int foo)C c=x(a))') with pytest.raises(DefinitionError): parse('function', 'int foo(D d=x(a') - check('function', 'int foo(const A&... a)', {1:"foo__ACRDp", 2:"3fooDpRK1A"}) - check('function', 'virtual void f()', {1:"f", 2:"1fv"}) + check('function', 'int foo(const A&... a)', {1: "foo__ACRDp", 2: "3fooDpRK1A"}) + check('function', 'virtual void f()', {1: "f", 2: "1fv"}) # test for ::nestedName, from issue 1738 check("function", "result(int val, ::std::error_category const &cat)", - {1:"result__i.std::error_categoryCR", 2:"6resultiRNSt14error_categoryE"}) - check("function", "int *f()", {1:"f", 2:"1fv"}) + {1: "result__i.std::error_categoryCR", 2: "6resultiRNSt14error_categoryE"}) + check("function", "int *f()", {1: "f", 2: "1fv"}) # tests derived from issue #1753 (skip to keep sanity) - check("function", "f(int (&array)[10])", {2:"1fRA10_i", 3:"1fRAL10E_i"}) - check("function", "void f(int (&array)[10])", {2:"1fRA10_i", 3:"1fRAL10E_i"}) - check("function", "void f(float *q(double))", {2:"1fFPfdE"}) - check("function", "void f(float *(*q)(double))", {2:"1fPFPfdE"}) - check("function", "void f(float (*q)(double))", {2:"1fPFfdE"}) - check("function", "int (*f(double d))(float)", {1:"f__double", 2:"1fd"}) - check("function", "int (*f(bool b))[5]", {1:"f__b", 2:"1fb"}) + check("function", "f(int (&array)[10])", {2: "1fRA10_i", 3: "1fRAL10E_i"}) + check("function", "void f(int (&array)[10])", {2: "1fRA10_i", 3: "1fRAL10E_i"}) + check("function", "void f(float *q(double))", {2: "1fFPfdE"}) + check("function", "void f(float *(*q)(double))", {2: "1fPFPfdE"}) + check("function", "void f(float (*q)(double))", {2: "1fPFfdE"}) + check("function", "int (*f(double d))(float)", {1: "f__double", 2: "1fd"}) + check("function", "int (*f(bool b))[5]", {1: "f__b", 2: "1fb"}) check("function", "int (*A::f(double d) const)(float)", - {1:"A::f__doubleC", 2:"NK1A1fEd"}) + {1: "A::f__doubleC", 2: "NK1A1fEd"}) check("function", "void f(std::shared_ptr ptr)", - {2:"1fNSt10shared_ptrIFidEEE"}) - check("function", "void f(int *const p)", {1:"f__iPC", 2:"1fPCi"}) - check("function", "void f(int *volatile const p)", {1:"f__iPVC", 2:"1fPVCi"}) + {2: "1fNSt10shared_ptrIFidEEE"}) + check("function", "void f(int *const p)", {1: "f__iPC", 2: "1fPCi"}) + check("function", "void f(int *volatile const p)", {1: "f__iPVC", 2: "1fPVCi"}) - check('function', 'extern int f()', {1:'f', 2:'1fv'}) + check('function', 'extern int f()', {1: 'f', 2: '1fv'}) - check('function', 'decltype(auto) f()', {1: 'f', 2:"1fv"}) + check('function', 'decltype(auto) f()', {1: 'f', 2: "1fv"}) # TODO: make tests for functions in a template, e.g., Test # such that the id generation for function type types is correct. check('function', 'friend std::ostream &f(std::ostream&, int)', - {1:'f__osR.i', 2:'1fRNSt7ostreamEi'}) + {1: 'f__osR.i', 2: '1fRNSt7ostreamEi'}) # from breathe#223 - check('function', 'void f(struct E e)', {1:'f__E', 2:'1f1E'}) - check('function', 'void f(class E e)', {1:'f__E', 2:'1f1E'}) - check('function', 'void f(typename E e)', {1:'f__E', 2:'1f1E'}) - check('function', 'void f(enum E e)', {1:'f__E', 2:'1f1E'}) - check('function', 'void f(union E e)', {1:'f__E', 2:'1f1E'}) + check('function', 'void f(struct E e)', {1: 'f__E', 2: '1f1E'}) + check('function', 'void f(class E e)', {1: 'f__E', 2: '1f1E'}) + check('function', 'void f(typename E e)', {1: 'f__E', 2: '1f1E'}) + check('function', 'void f(enum E e)', {1: 'f__E', 2: '1f1E'}) + check('function', 'void f(union E e)', {1: 'f__E', 2: '1f1E'}) # pointer to member (function) - check('function', 'void f(int C::*)', {2:'1fM1Ci'}) - check('function', 'void f(int C::* p)', {2:'1fM1Ci'}) - check('function', 'void f(int ::C::* p)', {2:'1fM1Ci'}) - check('function', 'void f(int C::* const)', {2:'1fKM1Ci'}) - check('function', 'void f(int C::* const&)', {2:'1fRKM1Ci'}) - check('function', 'void f(int C::* volatile)', {2:'1fVM1Ci'}) - check('function', 'void f(int C::* const volatile)', {2:'1fVKM1Ci'}, + check('function', 'void f(int C::*)', {2: '1fM1Ci'}) + check('function', 'void f(int C::* p)', {2: '1fM1Ci'}) + check('function', 'void f(int ::C::* p)', {2: '1fM1Ci'}) + check('function', 'void f(int C::* const)', {2: '1fKM1Ci'}) + check('function', 'void f(int C::* const&)', {2: '1fRKM1Ci'}) + check('function', 'void f(int C::* volatile)', {2: '1fVM1Ci'}) + check('function', 'void f(int C::* const volatile)', {2: '1fVKM1Ci'}, output='void f(int C::* volatile const)') - check('function', 'void f(int C::* volatile const)', {2:'1fVKM1Ci'}) - check('function', 'void f(int (C::*)(float, double))', {2:'1fM1CFifdE'}) - check('function', 'void f(int (C::* p)(float, double))', {2:'1fM1CFifdE'}) - check('function', 'void f(int (::C::* p)(float, double))', {2:'1fM1CFifdE'}) - check('function', 'void f(void (C::*)() const &)', {2:'1fM1CKRFvvE'}) - check('function', 'int C::* f(int, double)', {2:'1fid'}) - check('function', 'void f(int C::* *)', {2:'1fPM1Ci'}) + check('function', 'void f(int C::* volatile const)', {2: '1fVKM1Ci'}) + check('function', 'void f(int (C::*)(float, double))', {2: '1fM1CFifdE'}) + check('function', 'void f(int (C::* p)(float, double))', {2: '1fM1CFifdE'}) + check('function', 'void f(int (::C::* p)(float, double))', {2: '1fM1CFifdE'}) + check('function', 'void f(void (C::*)() const &)', {2: '1fM1CKRFvvE'}) + check('function', 'int C::* f(int, double)', {2: '1fid'}) + check('function', 'void f(int C::* *)', {2: '1fPM1Ci'}) def test_operators(): check('function', 'void operator new [ ] ()', - {1:"new-array-operator", 2:"nav"}, output='void operator new[]()') + {1: "new-array-operator", 2: "nav"}, output='void operator new[]()') check('function', 'void operator delete ()', - {1:"delete-operator", 2:"dlv"}, output='void operator delete()') + {1: "delete-operator", 2: "dlv"}, output='void operator delete()') check('function', 'operator bool() const', - {1:"castto-b-operatorC", 2:"NKcvbEv"}, output='operator bool() const') + {1: "castto-b-operatorC", 2: "NKcvbEv"}, output='operator bool() const') check('function', 'void operator * ()', - {1:"mul-operator", 2:"mlv"}, output='void operator*()') + {1: "mul-operator", 2: "mlv"}, output='void operator*()') check('function', 'void operator - ()', - {1:"sub-operator", 2:"miv"}, output='void operator-()') + {1: "sub-operator", 2: "miv"}, output='void operator-()') check('function', 'void operator + ()', - {1:"add-operator", 2:"plv"}, output='void operator+()') + {1: "add-operator", 2: "plv"}, output='void operator+()') check('function', 'void operator = ()', - {1:"assign-operator", 2:"aSv"}, output='void operator=()') + {1: "assign-operator", 2: "aSv"}, output='void operator=()') check('function', 'void operator / ()', - {1:"div-operator", 2:"dvv"}, output='void operator/()') + {1: "div-operator", 2: "dvv"}, output='void operator/()') check('function', 'void operator % ()', - {1:"mod-operator", 2:"rmv"}, output='void operator%()') + {1: "mod-operator", 2: "rmv"}, output='void operator%()') check('function', 'void operator ! ()', - {1:"not-operator", 2:"ntv"}, output='void operator!()') + {1: "not-operator", 2: "ntv"}, output='void operator!()') check('function', 'void operator "" _udl()', - {2:'li4_udlv'}, output='void operator""_udl()') + {2: 'li4_udlv'}, output='void operator""_udl()') def test_class_definitions(): - check('class', 'public A', {1:"A", 2:"1A"}, output='A') - check('class', 'private A', {1:"A", 2:"1A"}) - check('class', 'A final', {1:'A', 2:'1A'}) + check('class', 'public A', {1: "A", 2: "1A"}, output='A') + check('class', 'private A', {1: "A", 2: "1A"}) + check('class', 'A final', {1: 'A', 2: '1A'}) # test bases - check('class', 'A', {1:"A", 2:"1A"}) - check('class', 'A::B::C', {1:"A::B::C", 2:"N1A1B1CE"}) - check('class', 'A : B', {1:"A", 2:"1A"}) - check('class', 'A : private B', {1:"A", 2:"1A"}, output='A : B') - check('class', 'A : public B', {1:"A", 2:"1A"}) - check('class', 'A : B, C', {1:"A", 2:"1A"}) - check('class', 'A : B, protected C, D', {1:"A", 2:"1A"}) - check('class', 'A : virtual private B', {1:'A', 2:'1A'}, output='A : virtual B') - check('class', 'A : B, virtual C', {1:'A', 2:'1A'}) - check('class', 'A : public virtual B', {1:'A', 2:'1A'}) - check('class', 'A : B, C...', {1:'A', 2:'1A'}) - check('class', 'A : B..., C', {1:'A', 2:'1A'}) + check('class', 'A', {1: "A", 2: "1A"}) + check('class', 'A::B::C', {1: "A::B::C", 2: "N1A1B1CE"}) + check('class', 'A : B', {1: "A", 2: "1A"}) + check('class', 'A : private B', {1: "A", 2: "1A"}, output='A : B') + check('class', 'A : public B', {1: "A", 2: "1A"}) + check('class', 'A : B, C', {1: "A", 2: "1A"}) + check('class', 'A : B, protected C, D', {1: "A", 2: "1A"}) + check('class', 'A : virtual private B', {1: 'A', 2: '1A'}, output='A : virtual B') + check('class', 'A : B, virtual C', {1: 'A', 2: '1A'}) + check('class', 'A : public virtual B', {1: 'A', 2: '1A'}) + check('class', 'A : B, C...', {1: 'A', 2: '1A'}) + check('class', 'A : B..., C', {1: 'A', 2: '1A'}) # from #4094 - check('class', 'template> has_var', {2:'I00E7has_var'}) - check('class', 'template has_var>', {2:'I0E7has_varI1TNSt6void_tIDTadN1T3varEEEEE'}) + check('class', 'template> has_var', {2: 'I00E7has_var'}) + check('class', 'template has_var>', + {2: 'I0E7has_varI1TNSt6void_tIDTadN1T3varEEEEE'}) def test_enum_definitions(): - check('enum', 'A', {2:"1A"}) - check('enum', 'A : std::underlying_type::type', {2:"1A"}) - check('enum', 'A : unsigned int', {2:"1A"}) - check('enum', 'public A', {2:"1A"}, output='A') - check('enum', 'private A', {2:"1A"}) + check('enum', 'A', {2: "1A"}) + check('enum', 'A : std::underlying_type::type', {2: "1A"}) + check('enum', 'A : unsigned int', {2: "1A"}) + check('enum', 'public A', {2: "1A"}, output='A') + check('enum', 'private A', {2: "1A"}) - check('enumerator', 'A', {2:"1A"}) - check('enumerator', 'A = std::numeric_limits::max()', {2:"1A"}) + check('enumerator', 'A', {2: "1A"}) + check('enumerator', 'A = std::numeric_limits::max()', {2: "1A"}) def test_templates(): - check('class', "A", {2:"IE1AI1TE"}, output="template<> A") + check('class', "A", {2: "IE1AI1TE"}, output="template<> A") # first just check which objects support templating - check('class', "template<> A", {2:"IE1A"}) - check('function', "template<> void A()", {2:"IE1Av"}) - check('member', "template<> A a", {2:"IE1a"}) - check('type', "template<> a = A", {2:"IE1a"}) + check('class', "template<> A", {2: "IE1A"}) + check('function', "template<> void A()", {2: "IE1Av"}) + check('member', "template<> A a", {2: "IE1a"}) + check('type', "template<> a = A", {2: "IE1a"}) with pytest.raises(DefinitionError): parse('enum', "template<> A") with pytest.raises(DefinitionError): parse('enumerator', "template<> A") # then all the real tests - check('class', "template A", {2:"I00E1A"}) - check('type', "template<> a", {2:"IE1a"}) + check('class', "template A", {2: "I00E1A"}) + check('type', "template<> a", {2: "IE1a"}) - check('class', "template A", {2:"I0E1A"}) - check('class', "template A", {2:"I0E1A"}) - check('class', "template A", {2:"IDpE1A"}) - check('class', "template A", {2:"IDpE1A"}) - check('class', "template A", {2:"I0E1A"}) - check('class', "template A", {2:"I0E1A"}) + check('class', "template A", {2: "I0E1A"}) + check('class', "template A", {2: "I0E1A"}) + check('class', "template A", {2: "IDpE1A"}) + check('class', "template A", {2: "IDpE1A"}) + check('class', "template A", {2: "I0E1A"}) + check('class', "template A", {2: "I0E1A"}) - check('class', "template typename T> A", {2:"II0E0E1A"}) + check('class', "template typename T> A", {2: "II0E0E1A"}) check('class', "template typename> A", {2: "II0E0E1A"}) - check('class', "template typename ...T> A", {2:"II0EDpE1A"}) + check('class', "template typename ...T> A", {2: "II0EDpE1A"}) check('class', "template typename...> A", {2: "II0EDpE1A"}) - check('class', "template A", {2:"I_iE1A"}) - check('class', "template A", {2:"I_iE1A"}) - check('class', "template A", {2:"I_DpiE1A"}) - check('class', "template A", {2:"I_iE1A"}) - check('class', "template A", {2:"I_iE1A"}) + check('class', "template A", {2: "I_iE1A"}) + check('class', "template A", {2: "I_iE1A"}) + check('class', "template A", {2: "I_DpiE1A"}) + check('class', "template A", {2: "I_iE1A"}) + check('class', "template A", {2: "I_iE1A"}) - check('class', "template<> A>", {2:"IE1AIN2NS1BIEEE"}) + check('class', "template<> A>", {2: "IE1AIN2NS1BIEEE"}) # from #2058 check('function', @@ -527,8 +528,8 @@ def test_templates(): "inline std::basic_ostream &operator<<(" "std::basic_ostream &os, " "const c_string_view_base &str)", - {2:"I00ElsRNSt13basic_ostreamI4Char6TraitsEE" - "RK18c_string_view_baseIK4Char6TraitsE"}) + {2: "I00ElsRNSt13basic_ostreamI4Char6TraitsEE" + "RK18c_string_view_baseIK4Char6TraitsE"}) # template introductions with pytest.raises(DefinitionError): @@ -536,42 +537,42 @@ def test_templates(): with pytest.raises(DefinitionError): parse('enumerator', 'abc::ns::foo{id_0, id_1, id_2} A') check('class', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar', - {2:'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'}) + {2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'}) check('class', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar', - {2:'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'}) + {2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'}) check('class', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar', - {2:'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barI4id_04id_14id_2EE'}) + {2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barI4id_04id_14id_2EE'}) check('class', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar', - {2:'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barI4id_04id_1Dp4id_2EE'}) + {2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barI4id_04id_1Dp4id_2EE'}) - check('class', 'template<> Concept{U} A::B', {2:'IEI0EX7ConceptI1UEEN1AIiE1BE'}) + check('class', 'template<> Concept{U} A::B', {2: 'IEI0EX7ConceptI1UEEN1AIiE1BE'}) check('type', 'abc::ns::foo{id_0, id_1, id_2} xyz::bar = ghi::qux', - {2:'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'}) + {2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'}) check('type', 'abc::ns::foo{id_0, id_1, ...id_2} xyz::bar = ghi::qux', - {2:'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'}) + {2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'}) check('function', 'abc::ns::foo{id_0, id_1, id_2} void xyz::bar()', - {2:'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barEv'}) + {2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barEv'}) check('function', 'abc::ns::foo{id_0, id_1, ...id_2} void xyz::bar()', - {2:'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barEv'}) + {2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barEv'}) check('member', 'abc::ns::foo{id_0, id_1, id_2} ghi::qux xyz::bar', - {2:'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'}) + {2: 'I000EXN3abc2ns3fooEI4id_04id_14id_2EEN3xyz3barE'}) check('member', 'abc::ns::foo{id_0, id_1, ...id_2} ghi::qux xyz::bar', - {2:'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'}) - check('concept', 'Iterator{T, U} Another', {2:'I00EX8IteratorI1T1UEE7Another'}) + {2: 'I00DpEXN3abc2ns3fooEI4id_04id_1sp4id_2EEN3xyz3barE'}) + check('concept', 'Iterator{T, U} Another', {2: 'I00EX8IteratorI1T1UEE7Another'}) check('concept', 'template Numerics = (... && Numeric)', - {2:'IDpE8Numerics'}) + {2: 'IDpE8Numerics'}) # explicit specializations of members - check('member', 'template<> int A::a', {2:'IEN1AIiE1aE'}) + check('member', 'template<> int A::a', {2: 'IEN1AIiE1aE'}) check('member', 'template int A::a', {2: 'IEN1AIiE1aE'}, output='template<> int A::a') # same as above - check('member', 'template<> template<> int A::B::b', {2:'IEIEN1AIiE1BIiE1bE'}) + check('member', 'template<> template<> int A::B::b', {2: 'IEIEN1AIiE1BIiE1bE'}) check('member', 'template int A::B::b', {2: 'IEIEN1AIiE1BIiE1bE'}, output='template<> template<> int A::B::b') # same as above # defaulted constrained type parameters - check('type', 'template A', {2:'I_1CE1A'}) + check('type', 'template A', {2: 'I_1CE1A'}) def test_template_args(): @@ -579,33 +580,32 @@ def test_template_args(): check('function', "template " "void allow(F *f, typename func::type tt)", - {2:"I0E5allowP1FN4funcI1F1BXG != 1EE4typeE", - 3:"I0E5allowP1FN4funcI1F1BXne1GL1EEE4typeE"}) + {2: "I0E5allowP1FN4funcI1F1BXG != 1EE4typeE", + 3: "I0E5allowP1FN4funcI1F1BXne1GL1EEE4typeE"}) # from #3542 check('type', "template " "enable_if_not_array_t = std::enable_if_t::value, int>", - {2:"I0E21enable_if_not_array_t"}) - + {2: "I0E21enable_if_not_array_t"}) def test_attributes(): # style: C++ - check('member', '[[]] int f', {1:'f__i', 2:'1f'}) - check('member', '[ [ ] ] int f', {1:'f__i', 2:'1f'}, + check('member', '[[]] int f', {1: 'f__i', 2: '1f'}) + check('member', '[ [ ] ] int f', {1: 'f__i', 2: '1f'}, # this will fail when the proper grammar is implemented output='[[ ]] int f') - check('member', '[[a]] int f', {1:'f__i', 2:'1f'}) + check('member', '[[a]] int f', {1: 'f__i', 2: '1f'}) # style: GNU - check('member', '__attribute__(()) int f', {1:'f__i', 2:'1f'}) - check('member', '__attribute__((a)) int f', {1:'f__i', 2:'1f'}) - check('member', '__attribute__((a, b)) int f', {1:'f__i', 2:'1f'}) + check('member', '__attribute__(()) int f', {1: 'f__i', 2: '1f'}) + check('member', '__attribute__((a)) int f', {1: 'f__i', 2: '1f'}) + check('member', '__attribute__((a, b)) int f', {1: 'f__i', 2: '1f'}) # style: user-defined id - check('member', 'id_attr int f', {1:'f__i', 2:'1f'}) + check('member', 'id_attr int f', {1: 'f__i', 2: '1f'}) # style: user-defined paren - check('member', 'paren_attr() int f', {1:'f__i', 2:'1f'}) - check('member', 'paren_attr(a) int f', {1:'f__i', 2:'1f'}) - check('member', 'paren_attr("") int f', {1:'f__i', 2:'1f'}) - check('member', 'paren_attr(()[{}][]{}) int f', {1:'f__i', 2:'1f'}) + check('member', 'paren_attr() int f', {1: 'f__i', 2: '1f'}) + check('member', 'paren_attr(a) int f', {1: 'f__i', 2: '1f'}) + check('member', 'paren_attr("") int f', {1: 'f__i', 2: '1f'}) + check('member', 'paren_attr(()[{}][]{}) int f', {1: 'f__i', 2: '1f'}) with pytest.raises(DefinitionError): parse('member', 'paren_attr(() int f') with pytest.raises(DefinitionError): @@ -621,7 +621,7 @@ def test_attributes(): # position: decl specs check('function', 'static inline __attribute__(()) void f()', - {1:'f', 2:'1fv'}, + {1: 'f', 2: '1fv'}, output='__attribute__(()) static inline void f()') diff --git a/tests/test_environment.py b/tests/test_environment.py index 611d34577..64089b7c8 100644 --- a/tests/test_environment.py +++ b/tests/test_environment.py @@ -22,7 +22,7 @@ def setup_module(rootdir, sphinx_test_tempdir): global app, env srcdir = sphinx_test_tempdir / 'root-envtest' if not srcdir.exists(): - (rootdir/'test-root').copytree(srcdir) + (rootdir / 'test-root').copytree(srcdir) app = SphinxTestApp(srcdir=srcdir) env = app.env yield diff --git a/tests/test_ext_autosummary.py b/tests/test_ext_autosummary.py index b59f0cbc8..b0b34f8f1 100644 --- a/tests/test_ext_autosummary.py +++ b/tests/test_ext_autosummary.py @@ -163,7 +163,8 @@ def test_import_by_name(): assert parent is sphinx.ext.autosummary assert modname == 'sphinx.ext.autosummary' - prefixed_name, obj, parent, modname = import_by_name('sphinx.ext.autosummary.Autosummary.get_items') + prefixed_name, obj, parent, modname = \ + import_by_name('sphinx.ext.autosummary.Autosummary.get_items') assert prefixed_name == 'sphinx.ext.autosummary.Autosummary.get_items' assert obj == sphinx.ext.autosummary.Autosummary.get_items assert parent is sphinx.ext.autosummary.Autosummary diff --git a/tests/test_ext_graphviz.py b/tests/test_ext_graphviz.py index 1d2a3ab2f..118e6abe2 100644 --- a/tests/test_ext_graphviz.py +++ b/tests/test_ext_graphviz.py @@ -40,6 +40,7 @@ def test_graphviz_png_html(app, status, warning): r'}\" />\n
') assert re.search(html, content, re.S) + @pytest.mark.sphinx('html', testroot='ext-graphviz', confoverrides={'graphviz_output_format': 'svg'}) @pytest.mark.usefixtures('if_graphviz_found') @@ -80,6 +81,7 @@ def test_graphviz_svg_html(app, status, warning): r'') assert re.search(html, content, re.S) + @pytest.mark.sphinx('latex', testroot='ext-graphviz') @pytest.mark.usefixtures('if_graphviz_found') def test_graphviz_latex(app, status, warning): diff --git a/tests/test_ext_intersphinx.py b/tests/test_ext_intersphinx.py index 594aa81b8..c1e1dae93 100644 --- a/tests/test_ext_intersphinx.py +++ b/tests/test_ext_intersphinx.py @@ -240,7 +240,6 @@ def test_missing_reference_cppdomain(tempdir, app, status, warning): ' title="(in foo v2.0)">bartype' in html) - def test_missing_reference_jsdomain(tempdir, app, status, warning): inv_file = tempdir / 'inventory' inv_file.write_bytes(inventory_v2) diff --git a/tests/test_ext_todo.py b/tests/test_ext_todo.py index 4f01a07ab..19225bea8 100644 --- a/tests/test_ext_todo.py +++ b/tests/test_ext_todo.py @@ -85,6 +85,7 @@ def test_todo_not_included(app, status, warning): assert len(todos) == 2 assert set(todo[1].astext() for todo in todos) == set(['todo in foo', 'todo in bar']) + @pytest.mark.sphinx('latex', testroot='ext-todo', freshenv=True, confoverrides={'todo_include_todos': True, 'todo_emit_warnings': True}) def test_todo_valid_link(app, status, warning): @@ -107,8 +108,7 @@ def test_todo_valid_link(app, status, warning): target = m[0] # Look for the targets of this link. - labels = [m for m in re.findall(r'\\label\{([^}]*)}', content) - if m == target] + labels = [m for m in re.findall(r'\\label\{([^}]*)}', content) if m == target] # If everything is correct we should have exactly one target. assert len(labels) == 1 diff --git a/tests/test_intl.py b/tests/test_intl.py index 6b72438bd..fd2bcd5b5 100644 --- a/tests/test_intl.py +++ b/tests/test_intl.py @@ -222,6 +222,7 @@ def test_text_inconsistency_warnings(app, warning): u'.*/refs_inconsistency.txt:\\d+: WARNING: citation not found: ref3') assert_re_search(expected_citation_warning_expr, warnings) + @sphinx_intl @pytest.mark.sphinx('text') @pytest.mark.test_params(shared_result='test_intl_basic') diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py index f69a0a58e..160e2df32 100644 --- a/tests/test_quickstart.py +++ b/tests/test_quickstart.py @@ -96,7 +96,6 @@ def test_do_prompt_inputstrip(): def test_do_prompt_with_nonascii(): - d = {} answers = { 'Q1': u'\u30c9\u30a4\u30c4', } diff --git a/tests/test_util.py b/tests/test_util.py index aae54eaf0..db1a28869 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -95,7 +95,6 @@ def test_parselinenos(): parselinenos('3-1', 10) - def test_xmlname_check(): checker = xmlname_checker() assert checker.match('id-pub') diff --git a/tests/test_util_images.py b/tests/test_util_images.py index 6f67dcc82..fbee12a61 100644 --- a/tests/test_util_images.py +++ b/tests/test_util_images.py @@ -44,22 +44,22 @@ def test_guess_mimetype(testroot): assert guess_mimetype('IMG.PNG') == 'image/png' # guess by content - assert guess_mimetype(content=(testroot/GIF_FILENAME).bytes()) == 'image/gif' - assert guess_mimetype(content=(testroot/PNG_FILENAME).bytes()) == 'image/png' - assert guess_mimetype(content=(testroot/PDF_FILENAME).bytes()) is None - assert guess_mimetype(content=(testroot/TXT_FILENAME).bytes()) is None - assert guess_mimetype(content=(testroot/TXT_FILENAME).bytes(), + assert guess_mimetype(content=(testroot / GIF_FILENAME).bytes()) == 'image/gif' + assert guess_mimetype(content=(testroot / PNG_FILENAME).bytes()) == 'image/png' + assert guess_mimetype(content=(testroot / PDF_FILENAME).bytes()) is None + assert guess_mimetype(content=(testroot / TXT_FILENAME).bytes()) is None + assert guess_mimetype(content=(testroot / TXT_FILENAME).bytes(), default='text/plain') == 'text/plain' # the priority of params: filename > content > default assert guess_mimetype('img.png', - content=(testroot/GIF_FILENAME).bytes(), + content=(testroot / GIF_FILENAME).bytes(), default='text/plain') == 'image/png' assert guess_mimetype('no_extension', - content=(testroot/GIF_FILENAME).bytes(), + content=(testroot / GIF_FILENAME).bytes(), default='text/plain') == 'image/gif' assert guess_mimetype('no_extension', - content=(testroot/TXT_FILENAME).bytes(), + content=(testroot / TXT_FILENAME).bytes(), default='text/plain') == 'text/plain' diff --git a/tests/test_util_inspect.py b/tests/test_util_inspect.py index 63e04ee76..e5a9ed730 100644 --- a/tests/test_util_inspect.py +++ b/tests/test_util_inspect.py @@ -113,7 +113,6 @@ def test_getargspec_bound_methods(): assert expected_bound == inspect.getargspec(wrapped_bound_method) - def test_Signature(): # literals with pytest.raises(TypeError): diff --git a/tests/test_versioning.py b/tests/test_versioning.py index b73c00fa6..2832a12e4 100644 --- a/tests/test_versioning.py +++ b/tests/test_versioning.py @@ -28,7 +28,7 @@ def setup_module(rootdir, sphinx_test_tempdir): global app, original, original_uids srcdir = sphinx_test_tempdir / 'test-versioning' if not srcdir.exists(): - (rootdir/'test-versioning').copytree(srcdir) + (rootdir / 'test-versioning').copytree(srcdir) app = SphinxTestApp(srcdir=srcdir) app.builder.env.app = app app.connect('doctree-resolved', on_doctree_resolved) From 411055905cd0a24ad21ee4701770f362d341ea8d Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sun, 24 Dec 2017 14:47:31 +0000 Subject: [PATCH 178/275] tox: Add 'PERL5LIB' to 'passenv' list This is required by 'makeinfo'. Signed-off-by: Stephen Finucane Fixes #4339 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 4b462d612..b7934f8fd 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ envlist = docs,flake8,mypy,coverage,py{27,34,35,36,py},du{11,12,13,14} [testenv] passenv = - https_proxy http_proxy no_proxy + https_proxy http_proxy no_proxy PERL PERL5LIB description = py{27,34,35,36,py}: Run unit tests against {envname}. du{11,12,13,14}: Run unit tests with the given version of docutils. From 9766c2f339b2f5f16e1e66458d35651c8a7d6272 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Sun, 24 Dec 2017 16:31:10 +0100 Subject: [PATCH 179/275] C++, support the template disambiguator for dependent names. --- CHANGES | 1 + sphinx/domains/cpp.py | 56 +++++++++++++++++++++++++++------------- tests/test_domain_cpp.py | 2 ++ 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/CHANGES b/CHANGES index 3b3bb7c17..100831a3f 100644 --- a/CHANGES +++ b/CHANGES @@ -96,6 +96,7 @@ Bugs fixed * #4094: C++, allow empty template argument lists. * C++, also hyperlink types in the name of declarations with qualified names. * C++, do not add index entries for declarations inside concepts. +* C++, support the template disambiguator for dependent names. * #4314: For PDF 'howto' documents, numbering of code-blocks differs from the one of figures and tables * #4330: PDF 'howto' documents have an incoherent default LaTeX tocdepth counter diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index a1d8fe909..271832908 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -1285,7 +1285,7 @@ class ASTTemplateParamType(ASTBase): def name(self): # type: () -> ASTNestedName id = self.get_identifier() - return ASTNestedName([ASTNestedNameElement(id, None)], rooted=False) + return ASTNestedName([ASTNestedNameElement(id, None)], [False], rooted=False) @property def isPack(self): @@ -1364,7 +1364,7 @@ class ASTTemplateParamTemplateType(ASTBase): def name(self): # type: () -> ASTNestedName id = self.get_identifier() - return ASTNestedName([ASTNestedNameElement(id, None)], rooted=False) + return ASTNestedName([ASTNestedNameElement(id, None)], [False], rooted=False) def get_identifier(self): # type: () -> unicode @@ -1401,7 +1401,7 @@ class ASTTemplateParamNonType(ASTBase): def name(self): # type: () -> ASTNestedName id = self.get_identifier() - return ASTNestedName([ASTNestedNameElement(id, None)], rooted=False) + return ASTNestedName([ASTNestedNameElement(id, None)], [False], rooted=False) def get_identifier(self): # type: () -> unicode @@ -1494,7 +1494,7 @@ class ASTTemplateIntroductionParameter(ASTBase): def name(self): # type: () -> ASTNestedName id = self.get_identifier() - return ASTNestedName([ASTNestedNameElement(id, None)], rooted=False) + return ASTNestedName([ASTNestedNameElement(id, None)], [False], rooted=False) @property def isPack(self): @@ -1820,10 +1820,12 @@ class ASTNestedNameElement(ASTBase): class ASTNestedName(ASTBase): - def __init__(self, names, rooted): - # type: (List[Any], bool) -> None + def __init__(self, names, templates, rooted): + # type: (List[Any], List[bool], bool) -> None assert len(names) > 0 self.names = names + self.templates = templates + assert len(self.names) == len(self.templates) self.rooted = rooted @property @@ -1864,8 +1866,13 @@ class ASTNestedName(ASTBase): res = [] # type: List[unicode] if self.rooted: res.append('') - for n in self.names: - res.append(text_type(n)) + for i in range(len(self.names)): + n = self.names[i] + t = self.templates[i] + if t: + res.append("template " + text_type(n)) + else: + res.append(text_type(n)) return '::'.join(res) def describe_signature(self, signode, mode, env, symbol): @@ -1892,10 +1899,14 @@ class ASTNestedName(ASTBase): prefix = '' # type: unicode first = True names = self.names[:-1] if mode == 'lastIsName' else self.names - for name in names: + for i in range(len(names)): + name = names[i] + template = self.templates[i] if not first: signode += nodes.Text('::') prefix += '::' + if template: + signode += nodes.Text("template ") first = False if name != '': if (name.templateArgs and # type: ignore @@ -1908,6 +1919,8 @@ class ASTNestedName(ASTBase): if mode == 'lastIsName': if len(self.names) > 1: signode += addnodes.desc_addname('::', '::') + if self.templates[-1]: + signode += nodes.Text("template ") self.names[-1].describe_signature(signode, mode, env, '', symbol) else: raise Exception('Unknown description mode: %s' % mode) @@ -3338,7 +3351,7 @@ class Symbol(object): else: decl = None nne = ASTNestedNameElement(p.get_identifier(), None) - nn = ASTNestedName([nne], rooted=False) + nn = ASTNestedName([nne], [False], rooted=False) self._add_symbols(nn, [], decl, docname) # add symbols for function parameters, if any if declaration is not None and declaration.function_params is not None: @@ -3413,9 +3426,11 @@ class Symbol(object): def get_full_nested_name(self): # type: () -> ASTNestedName names = [] + templates = [] for nne, templateParams in self.get_lookup_key(): names.append(nne) - return ASTNestedName(names, rooted=False) + templates.append(False) + return ASTNestedName(names, templates, rooted=False) def _find_named_symbol(self, identifier, templateParams, templateArgs, operator, @@ -4531,7 +4546,8 @@ class DefinitionParser(object): def _parse_nested_name(self, memberPointer=False): # type: (bool) -> ASTNestedName - names = [] + names = [] # type: List[Any] + templates = [] # type: List[bool] self.skip_ws() rooted = False @@ -4539,14 +4555,18 @@ class DefinitionParser(object): rooted = True while 1: self.skip_ws() - if self.skip_word_and_ws('template'): - self.fail("'template' in nested name not implemented.") - elif self.skip_word_and_ws('operator'): + if len(names) > 0: + template = self.skip_word_and_ws('template') + else: + template = False + templates.append(template) + if self.skip_word_and_ws('operator'): op = self._parse_operator() names.append(op) else: if not self.match(_identifier_re): if memberPointer and len(names) > 0: + templates.pop() break self.fail("Expected identifier in nested name.") identifier = self.matched_text @@ -4571,7 +4591,7 @@ class DefinitionParser(object): if memberPointer: self.fail("Expected '::' in pointer to member (function).") break - return ASTNestedName(names, rooted) + return ASTNestedName(names, templates, rooted) def _parse_trailing_type_spec(self): # type: () -> Any @@ -4836,7 +4856,7 @@ class DefinitionParser(object): if self.match(_identifier_re): identifier = ASTIdentifier(self.matched_text) nne = ASTNestedNameElement(identifier, None) - declId = ASTNestedName([nne], rooted=False) + declId = ASTNestedName([nne], [False], rooted=False) # if it's a member pointer, we may have '::', which should be an error self.skip_ws() if self.current_char == ':': @@ -5477,7 +5497,7 @@ class DefinitionParser(object): def _make_phony_error_name(): # type: () -> ASTNestedName nne = ASTNestedNameElement(ASTIdentifier("PhonyNameDueToError"), None) - return ASTNestedName([nne], rooted=False) + return ASTNestedName([nne], [False], rooted=False) class CPPObject(ObjectDescription): diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py index aed574daf..aa398370d 100644 --- a/tests/test_domain_cpp.py +++ b/tests/test_domain_cpp.py @@ -243,6 +243,8 @@ def test_type_definitions(): {1: 'gpio_callback_t', 2: '15gpio_callback_t'}) check('type', 'void (*f)(std::function g)', {1: 'f', 2: '1f'}) + check('type', 'T = A::template B::template C', {2: '1T'}) + def test_concept_definitions(): check('concept', 'template A::B::Concept', From a3f9935d958197a3c0963cec97755db1ff32a3a3 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sat, 21 Oct 2017 15:52:46 +0100 Subject: [PATCH 180/275] travis: Enable codecov coverage This necessitates adding some basic coverage-py configuration [1] and making sure the pytest-cov plugin uses said configuration [2]. Badges are included. Note that we do not run the 'coverage' tox target, which is reserved for users. [1] https://github.com/codecov/example-python [2] https://bitbucket.org/ned/coveragepy/issues/512/ Signed-off-by: Stephen Finucane --- .travis.yml | 13 ++++++++++--- README.rst | 4 ++++ setup.cfg | 14 ++++++++++++++ tox.ini | 2 +- 4 files changed, 29 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 900853cf7..f05d6a3b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,13 +14,17 @@ matrix: - python: 'pypy' env: TOXENV=pypy - python: '2.7' - env: TOXENV=du13 + env: + - TOXENV=du13 + - PYTEST_ADDOPTS = --cov sphinx --cov-append --cov-config setup.cfg - python: '3.4' env: TOXENV=py34 - python: '3.5' env: TOXENV=py35 - python: '3.6' - env: TOXENV=py36 + env: + - TOXENV=py36 + - PYTEST_ADDOPTS = --cov sphinx --cov-append --cov-config setup.cfg - python: 'nightly' env: TOXENV=py37 - python: '3.6' @@ -35,7 +39,10 @@ addons: - imagemagick install: - - pip install -U tox + - pip install -U tox codecov script: - tox -- -v + +after_success: + - codecov diff --git a/README.rst b/README.rst index 6419503e4..2d841f78e 100644 --- a/README.rst +++ b/README.rst @@ -22,6 +22,10 @@ :target: https://circleci.com/gh/sphinx-doc/sphinx :alt: Build Status (CircleCI) +.. image:: https://codecov.io/gh/sphinx-doc/sphinx/branch/master/graph/badge.svg + :target: https://codecov.io/gh/sphinx-doc/sphinx + :alt: Code Coverage Status (Codecov) + Sphinx is a tool that makes it easy to create intelligent and beautiful documentation for Python projects (or other documents consisting of multiple reStructuredText sources), written by Georg Brandl. It was originally created diff --git a/setup.cfg b/setup.cfg index 00e7833d3..0ce6282dc 100644 --- a/setup.cfg +++ b/setup.cfg @@ -43,3 +43,17 @@ follow_imports = skip incremental = True check_untyped_defs = True warn_unused_ignores = True + +[coverage:run] +branch = True +source = sphinx + +[coverage:report] +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + # Don't complain if tests don't hit defensive assertion code: + raise NotImplementedError + # Don't complain if non-runnable code isn't run: + if __name__ == .__main__.: +ignore_errors = True diff --git a/tox.ini b/tox.ini index 4b462d612..5ff3e9f33 100644 --- a/tox.ini +++ b/tox.ini @@ -22,7 +22,7 @@ deps = du14: docutils==0.14 setenv = SPHINX_TEST_TEMPDIR = {envdir}/testbuild - coverage: PYTEST_ADDOPTS = --cov sphinx + coverage: PYTEST_ADDOPTS = --cov sphinx --cov-config {toxinidir}/setup.cfg commands= {envpython} -Wall tests/run.py --durations 25 {posargs} From 77ca8947236c1b8e42c0bd47567c87ddede9b1b3 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 22 Dec 2017 18:00:25 +0000 Subject: [PATCH 181/275] tox: Report coverage to user Run 'coverage report' after a successful coverage run. There's enough coverage-related stuff here at this point to warrant its own section. Signed-off-by: Stephen Finucane --- tox.ini | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tox.ini b/tox.ini index 5ff3e9f33..a4497a5c8 100644 --- a/tox.ini +++ b/tox.ini @@ -8,7 +8,6 @@ passenv = description = py{27,34,35,36,py}: Run unit tests against {envname}. du{11,12,13,14}: Run unit tests with the given version of docutils. - coverage: Run code coverage checks. # TODO(stephenfin) Replace this with the 'extras' config option when tox 2.4 is # widely available, likely some time after the Ubuntu 18.04 release @@ -22,7 +21,6 @@ deps = du14: docutils==0.14 setenv = SPHINX_TEST_TEMPDIR = {envdir}/testbuild - coverage: PYTEST_ADDOPTS = --cov sphinx --cov-config {toxinidir}/setup.cfg commands= {envpython} -Wall tests/run.py --durations 25 {posargs} @@ -41,6 +39,15 @@ deps = commands = pylint --rcfile utils/pylintrc sphinx +[testenv:coverage] +description = + Run code coverage checks. +setenv = + PYTEST_ADDOPTS = --cov sphinx --cov-config {toxinidir}/setup.cfg +commands = + {[testenv]commands} + coverage report + [testenv:mypy] description = Run type checks. From f06862717663fe19c651c8fadbf8037cbb7d5b03 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 22 Dec 2017 18:01:51 +0000 Subject: [PATCH 182/275] gitignore: Ignore 'htmlcov' directory This is generated if you run 'coverage html'. Hide it from Git. Signed-off-by: Stephen Finucane --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f1dc3167c..5d1026c5e 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ TAGS .tox .venv .coverage +htmlcov .DS_Store sphinx/pycode/Grammar*pickle distribute-* From b094c401de702e5811c8a195db3a5f7a9d6ed435 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 27 Dec 2017 14:59:59 +0900 Subject: [PATCH 183/275] docs: make explicitly :meth: reference (refs: #4344) --- doc/markup/inline.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/markup/inline.rst b/doc/markup/inline.rst index 8be34f22c..4d14a653d 100644 --- a/doc/markup/inline.rst +++ b/doc/markup/inline.rst @@ -63,7 +63,7 @@ Cross-referencing anything by :rst:role:`doc`, :rst:role:`ref` or :rst:role:`option`. Custom objects added to the standard domain by extensions (see - :meth:`.add_object_type`) are also searched. + :meth:`Sphinx.add_object_type`) are also searched. * Then, it looks for objects (targets) in all loaded domains. It is up to the domains how specific a match must be. For example, in the Python From 90acaa82f64ca2a3665a9fd560dd3a9b04dd8312 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 27 Dec 2017 15:04:30 +0900 Subject: [PATCH 184/275] Diet tests on appveyor --- .appveyor.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index a3f83394f..cfc8d884f 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -6,19 +6,12 @@ environment: matrix: - PYTHON: 27 - DOCUTILS: 0.13.1 - TEST_IGNORE: --ignore py35 - - PYTHON: 27 - DOCUTILS: 0.14 TEST_IGNORE: --ignore py35 - PYTHON: 36 - DOCUTILS: 0.14 - PYTHON: 36-x64 - DOCUTILS: 0.14 install: - C:\Python%PYTHON%\python.exe -m pip install -U pip setuptools - - C:\Python%PYTHON%\python.exe -m pip install docutils==%DOCUTILS% mock - C:\Python%PYTHON%\python.exe -m pip install .[test,websupport] # No automatic build, just run python tests From 0cc6cdd7cce9418b27e46ae9d1238aea932e15a5 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 28 Dec 2017 10:48:29 +0900 Subject: [PATCH 185/275] travis: Build own docs as a test --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index f05d6a3b8..2bd437436 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,8 @@ matrix: - PYTEST_ADDOPTS = --cov sphinx --cov-append --cov-config setup.cfg - python: 'nightly' env: TOXENV=py37 + - python: '3.6' + env: TOXENV=docs - python: '3.6' env: TOXENV=mypy - python: '2.7' From f3c05adebc6f42eed3ccdc498f5deb45bf4f9885 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Thu, 28 Dec 2017 16:50:32 +0100 Subject: [PATCH 186/275] C++, fix handling of (templated) operators --- sphinx/domains/cpp.py | 181 +++++++++----------------- tests/roots/test-domain-cpp/index.rst | 6 + tests/test_domain_cpp.py | 7 + 3 files changed, 77 insertions(+), 117 deletions(-) diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 271832908..5f644255a 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -1408,9 +1408,9 @@ class ASTTemplateParamNonType(ASTBase): name = self.param.name if name: assert len(name.names) == 1 - assert name.names[0].identifier + assert name.names[0].identOrOp assert not name.names[0].templateArgs - return name.names[0].identifier + return name.names[0].identOrOp else: return None @@ -1650,8 +1650,8 @@ class ASTOperatorBuildIn(ASTBase): else: return u'operator' + self.op - def describe_signature(self, signode, mode, env, prefix, symbol): - # type: (addnodes.desc_signature, unicode, BuildEnvironment, unicode, Symbol) -> None + def describe_signature(self, signode, mode, env, prefix, templateArgs, symbol): + # type: (addnodes.desc_signature, unicode, Any, unicode, unicode, Symbol) -> None _verify_description_mode(mode) identifier = text_type(self) if mode == 'lastIsName': @@ -1684,7 +1684,7 @@ class ASTOperatorType(ASTBase): # type: () -> unicode return text_type(self) - def describe_signature(self, signode, mode, env, prefix, symbol): + def describe_signature(self, signode, mode, env, prefix, templateArgs, symbol): # type: (addnodes.desc_signature, unicode, BuildEnvironment, unicode, Symbol) -> None _verify_description_mode(mode) identifier = text_type(self) @@ -1714,7 +1714,7 @@ class ASTOperatorLiteral(ASTBase): # type: () -> unicode return u'operator""' + text_type(self.identifier) - def describe_signature(self, signode, mode, env, prefix, symbol): + def describe_signature(self, signode, mode, env, prefix, templateArgs, symbol): # type: (addnodes.desc_signature, unicode, BuildEnvironment, unicode, Symbol) -> None _verify_description_mode(mode) identifier = text_type(self) @@ -1788,9 +1788,9 @@ class ASTTemplateArgs(ASTBase): class ASTNestedNameElement(ASTBase): - def __init__(self, identifier, templateArgs): + def __init__(self, identOrOp, templateArgs): # type: (Any, Any) -> None - self.identifier = identifier + self.identOrOp = identOrOp self.templateArgs = templateArgs def is_operator(self): @@ -1799,14 +1799,14 @@ class ASTNestedNameElement(ASTBase): def get_id(self, version): # type: (int) -> unicode - res = self.identifier.get_id(version) + res = self.identOrOp.get_id(version) if self.templateArgs: res += self.templateArgs.get_id(version) return res def __unicode__(self): # type: () -> unicode - res = text_type(self.identifier) + res = text_type(self.identOrOp) if self.templateArgs: res += text_type(self.templateArgs) return res @@ -1814,7 +1814,7 @@ class ASTNestedNameElement(ASTBase): def describe_signature(self, signode, mode, env, prefix, symbol): # type: (addnodes.desc_signature, unicode, BuildEnvironment, unicode, Symbol) -> None tArgs = text_type(self.templateArgs) if self.templateArgs is not None else '' - self.identifier.describe_signature(signode, mode, env, prefix, tArgs, symbol) + self.identOrOp.describe_signature(signode, mode, env, prefix, tArgs, symbol) if self.templateArgs is not None: self.templateArgs.describe_signature(signode, mode, env, symbol) @@ -3310,23 +3310,20 @@ class Symbol(object): # type: () -> None if not self.parent: # parent == None means global scope, so declaration means a parent - assert not self.identifier + assert not self.identOrOp assert not self.templateParams assert not self.templateArgs assert not self.declaration assert not self.docname else: - if not self.identifier: - # in case it's an operator - assert self.declaration if self.declaration: assert self.docname - def __init__(self, parent, identifier, + def __init__(self, parent, identOrOp, templateParams, templateArgs, declaration, docname): # type: (Any, Any, Any, Any, Any, unicode) -> None self.parent = parent - self.identifier = identifier + self.identOrOp = identOrOp self.templateParams = templateParams # template self.templateArgs = templateArgs # identifier self.declaration = declaration @@ -3365,8 +3362,8 @@ class Symbol(object): decl = ASTDeclaration('functionParam', None, None, p) assert not nn.rooted assert len(nn.names) == 1 - identifier = nn.names[0].identifier - Symbol(parent=self, identifier=identifier, + identOrOp = nn.names[0].identOrOp + Symbol(parent=self, identOrOp=identOrOp, templateParams=None, templateArgs=None, declaration=decl, docname=docname) @@ -3390,12 +3387,7 @@ class Symbol(object): if sChild.declaration and sChild.docname == docname: sChild.declaration = None sChild.docname = None - # Just remove operators, because there is no identification if - # they got removed. - # Don't remove other symbols because they may be used in namespace - # directives. - if sChild.identifier or sChild.declaration: - newChildren.append(sChild) + newChildren.append(sChild) self.children = newChildren def get_all_symbols(self): @@ -3415,11 +3407,7 @@ class Symbol(object): symbols.reverse() key = [] for s in symbols: - if s.identifier: - nne = ASTNestedNameElement(s.identifier, s.templateArgs) - else: - assert s.declaration - nne = s.declaration.name.names[-1] + nne = ASTNestedNameElement(s.identOrOp, s.templateArgs) key.append((nne, s.templateParams)) return key @@ -3432,11 +3420,9 @@ class Symbol(object): templates.append(False) return ASTNestedName(names, templates, rooted=False) - def _find_named_symbol(self, identifier, templateParams, - templateArgs, operator, + def _find_named_symbol(self, identOrOp, templateParams, templateArgs, templateShorthand, matchSelf): - # type: (Any, Any, Any, Any, Any, bool) -> Symbol - assert (identifier is None) != (operator is None) + # type: (Any, Any, Any, Any, bool) -> Symbol def isSpecialization(): # the names of the template parameters must be given exactly as args @@ -3464,17 +3450,8 @@ class Symbol(object): templateArgs = None def matches(s): - if s.identifier != identifier: + if s.identOrOp != identOrOp: return False - if not s.identifier: - if not s.declaration: - return False - assert operator - name = s.declaration.name.names[-1] - if not name.is_operator(): - return False - if text_type(name) != text_type(operator): - return False if (s.templateParams is None) != (templateParams is None): if templateParams is not None: # we query with params, they must match params @@ -3515,10 +3492,7 @@ class Symbol(object): names = nestedName.names iTemplateDecl = 0 for name in names[:-1]: - # there shouldn't be anything inside an operator - # (other than template parameters, which are not added this way, right?) - assert not name.is_operator() - identifier = name.identifier + identOrOp = name.identOrOp templateArgs = name.templateArgs if templateArgs: assert iTemplateDecl < len(templateDecls) @@ -3526,27 +3500,20 @@ class Symbol(object): iTemplateDecl += 1 else: templateParams = None - symbol = parentSymbol._find_named_symbol(identifier, + symbol = parentSymbol._find_named_symbol(identOrOp, templateParams, templateArgs, - operator=None, templateShorthand=False, matchSelf=False) if symbol is None: - symbol = Symbol(parent=parentSymbol, identifier=identifier, + symbol = Symbol(parent=parentSymbol, identOrOp=identOrOp, templateParams=templateParams, templateArgs=templateArgs, declaration=None, docname=None) parentSymbol = symbol name = names[-1] - if name.is_operator(): - identifier = None - templateArgs = None - operator = name - else: - identifier = name.identifier - templateArgs = name.templateArgs - operator = None + identOrOp = name.identOrOp + templateArgs = name.templateArgs if iTemplateDecl < len(templateDecls): if iTemplateDecl + 1 != len(templateDecls): print(text_type(templateDecls)) @@ -3556,10 +3523,9 @@ class Symbol(object): else: assert iTemplateDecl == len(templateDecls) templateParams = None - symbol = parentSymbol._find_named_symbol(identifier, + symbol = parentSymbol._find_named_symbol(identOrOp, templateParams, templateArgs, - operator, templateShorthand=False, matchSelf=False) if symbol: @@ -3576,7 +3542,7 @@ class Symbol(object): return symbol # It may simply be a function overload, so let's compare ids. isRedeclaration = True - candSymbol = Symbol(parent=parentSymbol, identifier=identifier, + candSymbol = Symbol(parent=parentSymbol, identOrOp=identOrOp, templateParams=templateParams, templateArgs=templateArgs, declaration=declaration, @@ -3596,7 +3562,7 @@ class Symbol(object): candSymbol.isRedeclaration = True raise _DuplicateSymbolError(symbol, declaration) else: - symbol = Symbol(parent=parentSymbol, identifier=identifier, + symbol = Symbol(parent=parentSymbol, identOrOp=identOrOp, templateParams=templateParams, templateArgs=templateArgs, declaration=declaration, @@ -3667,12 +3633,12 @@ class Symbol(object): templateDecls = [] return self._add_symbols(nestedName, templateDecls, declaration, docname) - def find_identifier(self, identifier, matchSelf): + def find_identifier(self, identOrOp, matchSelf): # type: (Any, bool) -> Symbol - if matchSelf and self.identifier and self.identifier == identifier: + if matchSelf and self.identOrOp == identOrOp: return self for s in self.children: - if s.identifier and s.identifier == identifier: + if s.identOrOp == identOrOp: return s return None @@ -3680,16 +3646,10 @@ class Symbol(object): # type: (List[Tuple[Any, Any]]) -> Symbol s = self for name, templateParams in key: - if name.is_operator(): - identifier = None - templateArgs = None - operator = name - else: - identifier = name.identifier - templateArgs = name.templateArgs - operator = None - s = s._find_named_symbol(identifier, templateParams, - templateArgs, operator, + identOrOp = name.identOrOp + templateArgs = name.templateArgs + s = s._find_named_symbol(identOrOp, + templateParams, templateArgs, templateShorthand=False, matchSelf=False) if not s: @@ -3713,13 +3673,13 @@ class Symbol(object): firstName = names[0] if not firstName.is_operator(): while parentSymbol.parent: - if parentSymbol.find_identifier(firstName.identifier, + if parentSymbol.find_identifier(firstName.identOrOp, matchSelf=matchSelf): # if we are in the scope of a constructor but wants to reference the class # we need to walk one extra up if (len(names) == 1 and typ == 'class' and matchSelf and - parentSymbol.parent and parentSymbol.parent.identifier and - parentSymbol.parent.identifier == firstName.identifier): + parentSymbol.parent and + parentSymbol.parent.identOrOp == firstName.identOrOp): pass else: break @@ -3728,48 +3688,36 @@ class Symbol(object): for iName in range(len(names)): name = names[iName] if iName + 1 == len(names): - if name.is_operator(): - identifier = None - templateArgs = None - operator = name - else: - identifier = name.identifier - templateArgs = name.templateArgs - operator = None + identOrOp = name.identOrOp + templateArgs = name.templateArgs if iTemplateDecl < len(templateDecls): assert iTemplateDecl + 1 == len(templateDecls) templateParams = templateDecls[iTemplateDecl] else: assert iTemplateDecl == len(templateDecls) templateParams = None - symbol = parentSymbol._find_named_symbol(identifier, + symbol = parentSymbol._find_named_symbol(identOrOp, templateParams, templateArgs, - operator, templateShorthand=templateShorthand, matchSelf=matchSelf) if symbol is not None: return symbol # try without template params and args - symbol = parentSymbol._find_named_symbol(identifier, + symbol = parentSymbol._find_named_symbol(identOrOp, None, None, - operator, templateShorthand=templateShorthand, matchSelf=matchSelf) return symbol else: - # there shouldn't be anything inside an operator - assert not name.is_operator() - identifier = name.identifier + identOrOp = name.identOrOp templateArgs = name.templateArgs if templateArgs and iTemplateDecl < len(templateDecls): templateParams = templateDecls[iTemplateDecl] iTemplateDecl += 1 else: templateParams = None - symbol = parentSymbol._find_named_symbol(identifier, - templateParams, - templateArgs, - operator=None, + symbol = parentSymbol._find_named_symbol(identOrOp, + templateParams, templateArgs, templateShorthand=templateShorthand, matchSelf=matchSelf) if symbol is None: @@ -3792,8 +3740,8 @@ class Symbol(object): res.append(text_type(self.templateParams)) res.append('\n') res.append('\t' * indent) - if self.identifier: - res.append(text_type(self.identifier)) + if self.identOrOp: + res.append(text_type(self.identOrOp)) else: res.append(text_type(self.declaration)) if self.templateArgs: @@ -4561,8 +4509,7 @@ class DefinitionParser(object): template = False templates.append(template) if self.skip_word_and_ws('operator'): - op = self._parse_operator() - names.append(op) + identOrOp = self._parse_operator() else: if not self.match(_identifier_re): if memberPointer and len(names) > 0: @@ -4574,17 +4521,17 @@ class DefinitionParser(object): if identifier in _keywords: self.fail("Expected identifier in nested name, " "got keyword: %s" % identifier) - # try greedily to get template parameters, - # but otherwise a < might be because we are in an expression - pos = self.pos - try: - templateArgs = self._parse_template_argument_list() - except DefinitionError as ex: - self.pos = pos - templateArgs = None - self.otherErrors.append(ex) - identifier = ASTIdentifier(identifier) # type: ignore - names.append(ASTNestedNameElement(identifier, templateArgs)) + identOrOp = ASTIdentifier(identifier) # type: ignore + # try greedily to get template arguments, + # but otherwise a < might be because we are in an expression + pos = self.pos + try: + templateArgs = self._parse_template_argument_list() + except DefinitionError as ex: + self.pos = pos + templateArgs = None + self.otherErrors.append(ex) + names.append(ASTNestedNameElement(identOrOp, templateArgs)) self.skip_ws() if not self.skip_string('::'): @@ -5532,7 +5479,7 @@ class CPPObject(ObjectDescription): # then add the name to the parent scope symbol = ast.symbol assert symbol - assert symbol.identifier is not None + assert symbol.identOrOp is not None assert symbol.templateParams is None assert symbol.templateArgs is None parentSymbol = symbol.parent @@ -5545,7 +5492,7 @@ class CPPObject(ObjectDescription): if parentDecl is None: # the parent is not explicitly declared # TODO: we could warn, but it could be a style to just assume - # enumerator parnets to be scoped + # enumerator parents to be scoped return if parentDecl.objectType != 'enum': # TODO: maybe issue a warning, enumerators in non-enums is weird, @@ -5555,13 +5502,13 @@ class CPPObject(ObjectDescription): return targetSymbol = parentSymbol.parent - s = targetSymbol.find_identifier(symbol.identifier, matchSelf=False) + s = targetSymbol.find_identifier(symbol.identOrOp, matchSelf=False) if s is not None: # something is already declared with that name return declClone = symbol.declaration.clone() declClone.enumeratorScopedSymbol = symbol - Symbol(parent=targetSymbol, identifier=symbol.identifier, + Symbol(parent=targetSymbol, identOrOp=symbol.identOrOp, templateParams=None, templateArgs=None, declaration=declClone, docname=self.env.docname) diff --git a/tests/roots/test-domain-cpp/index.rst b/tests/roots/test-domain-cpp/index.rst index 618e51037..2df5ec848 100644 --- a/tests/roots/test-domain-cpp/index.rst +++ b/tests/roots/test-domain-cpp/index.rst @@ -28,14 +28,20 @@ directives An unscoped enum. + .. cpp:enumerator:: A + .. cpp:enum-class:: MyScopedEnum A scoped enum. + .. cpp:enumerator:: B + .. cpp:enum-struct:: protected MyScopedVisibilityEnum : std::underlying_type::type A scoped enum with non-default visibility, and with a specified underlying type. + .. cpp:enumerator:: B + .. cpp:function:: void paren_1(int, float) .. cpp:function:: void paren_2(int, float) diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py index aa398370d..0b31d8aed 100644 --- a/tests/test_domain_cpp.py +++ b/tests/test_domain_cpp.py @@ -205,6 +205,9 @@ def test_expressions(): check('class', "template A", {2: "I_iE1A"}) check('enumerator', 'A = std::numeric_limits::max()', {2: "1A"}) + exprCheck('operator()()', 'clclE') + exprCheck('operator()()', 'clclIiEE') + def test_type_definitions(): check("type", "public bool b", {1: "b", 2: "1b"}, "bool b") @@ -245,6 +248,10 @@ def test_type_definitions(): check('type', 'T = A::template B::template C', {2: '1T'}) + check('type', 'T = Q', {2: '1T'}) + check('type', 'T = Q>', {2: '1T'}) + check('type', 'T = Q', {2: '1T'}) + def test_concept_definitions(): check('concept', 'template A::B::Concept', From 217c5f385635e4aa965bf6e8de37953219336704 Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Thu, 28 Dec 2017 17:04:21 +0100 Subject: [PATCH 187/275] Fixes for previous commit --- sphinx/domains/cpp.py | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index 5f644255a..c6e87fd7a 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -1685,7 +1685,7 @@ class ASTOperatorType(ASTBase): return text_type(self) def describe_signature(self, signode, mode, env, prefix, templateArgs, symbol): - # type: (addnodes.desc_signature, unicode, BuildEnvironment, unicode, Symbol) -> None + # type: (addnodes.desc_signature, unicode, Any, unicode, unicode, Symbol) -> None _verify_description_mode(mode) identifier = text_type(self) if mode == 'lastIsName': @@ -1715,7 +1715,7 @@ class ASTOperatorLiteral(ASTBase): return u'operator""' + text_type(self.identifier) def describe_signature(self, signode, mode, env, prefix, templateArgs, symbol): - # type: (addnodes.desc_signature, unicode, BuildEnvironment, unicode, Symbol) -> None + # type: (addnodes.desc_signature, unicode, Any, unicode, unicode, Symbol) -> None _verify_description_mode(mode) identifier = text_type(self) if mode == 'lastIsName': @@ -3573,22 +3573,9 @@ class Symbol(object): # type: (Any, List[unicode], BuildEnvironment) -> None assert other is not None for otherChild in other.children: - if not otherChild.identifier: - if not otherChild.declaration: - print("Problem in symbol tree merging") - print("OtherChild.dump:") - print(otherChild.dump(0)) - print("Other.dump:") - print(other.dump(0)) - assert otherChild.declaration - operator = otherChild.declaration.name.names[-1] - assert operator.is_operator() - else: - operator = None - ourChild = self._find_named_symbol(otherChild.identifier, + ourChild = self._find_named_symbol(otherChild.identOrOp, otherChild.templateParams, otherChild.templateArgs, - operator, templateShorthand=False, matchSelf=False) if ourChild is None: @@ -4521,7 +4508,7 @@ class DefinitionParser(object): if identifier in _keywords: self.fail("Expected identifier in nested name, " "got keyword: %s" % identifier) - identOrOp = ASTIdentifier(identifier) # type: ignore + identOrOp = ASTIdentifier(identifier) # try greedily to get template arguments, # but otherwise a < might be because we are in an expression pos = self.pos From e5ba527dd5d5d2620ab03b0bdd552f380242fafa Mon Sep 17 00:00:00 2001 From: Jakob Lykke Andersen Date: Thu, 28 Dec 2017 17:16:53 +0100 Subject: [PATCH 188/275] Fix missing metainfo for sphinx.io --- sphinx/io.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/sphinx/io.py b/sphinx/io.py index 804932863..cfdaafb9c 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -285,3 +285,9 @@ def read_doc(app, env, filename): def setup(app): app.registry.add_source_input('*', SphinxFileInput) app.registry.add_source_input('restructuredtext', SphinxRSTFileInput) + + return { + 'version': 'builtin', + 'parallel_read_safe': True, + 'parallel_write_safe': True, + } From f4f677c8f714a68f1152afcc40e3441a79f8913c Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 28 Dec 2017 21:18:23 +0000 Subject: [PATCH 189/275] templates: Remove 'epub3' targets This appears to have been missed in commit 69d1dfaa. One could add an alias for this to restore behavior, but no one has reported the issue since Sphinx meaning this seems unnecessary. Signed-off-by: Stephen Finucane --- sphinx/templates/quickstart/Makefile_t | 7 ------- sphinx/templates/quickstart/make.bat_t | 9 --------- 2 files changed, 16 deletions(-) diff --git a/sphinx/templates/quickstart/Makefile_t b/sphinx/templates/quickstart/Makefile_t index 4639a982b..2858d9bf7 100644 --- a/sphinx/templates/quickstart/Makefile_t +++ b/sphinx/templates/quickstart/Makefile_t @@ -27,7 +27,6 @@ help: @echo " applehelp to make an Apple Help Book" @echo " devhelp to make HTML files and a Devhelp project" @echo " epub to make an epub" - @echo " epub3 to make an epub3" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " latexpdf to make LaTeX files and run them through pdflatex" @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" @@ -122,12 +121,6 @@ epub: @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." -.PHONY: epub3 -epub3: - $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 - @echo - @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." - .PHONY: latex latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex diff --git a/sphinx/templates/quickstart/make.bat_t b/sphinx/templates/quickstart/make.bat_t index 8438b5f7e..230977488 100644 --- a/sphinx/templates/quickstart/make.bat_t +++ b/sphinx/templates/quickstart/make.bat_t @@ -29,7 +29,6 @@ if "%1" == "help" ( echo. qthelp to make HTML files and a qthelp project echo. devhelp to make HTML files and a Devhelp project echo. epub to make an epub - echo. epub3 to make an epub3 echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. text to make text files echo. man to make manual pages @@ -153,14 +152,6 @@ if "%1" == "epub" ( goto end ) -if "%1" == "epub3" ( - %SPHINXBUILD% -b epub3 %ALLSPHINXOPTS% %BUILDDIR%/epub3 - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The epub3 file is in %BUILDDIR%/epub3. - goto end -) - if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 From f048d668e558f1674ebed6547b71968b47763444 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 28 Dec 2017 21:28:55 +0000 Subject: [PATCH 190/275] doc: Remove invalid note for epub3 builder This doesn't appear to be true any more, based on the code. Signed-off-by: Stephen Finucane --- doc/config.rst | 4 ---- 1 file changed, 4 deletions(-) diff --git a/doc/config.rst b/doc/config.rst index 881387b48..1ef455803 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -1458,10 +1458,6 @@ the `Dublin Core metadata `_. a chapter, but can be confusing because it mixes entries of different depth in one list. The default value is ``True``. - .. note:: - - ``epub3`` builder ignores ``epub_tocdup`` option(always ``False``) - .. confval:: epub_tocscope This setting control the scope of the epub table of contents. The setting From 35ad6910a9bb1d8f80c3d12cd3dfd1ebc06ba6dc Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 28 Dec 2017 21:37:07 +0000 Subject: [PATCH 191/275] epub: Remove dead templates These are no longer used since 'f2c93b31'. Signed-off-by: Stephen Finucane --- sphinx/templates/epub2/container.xml | 6 ----- sphinx/templates/epub2/content.opf_t | 37 ---------------------------- sphinx/templates/epub2/mimetype | 1 - sphinx/templates/epub2/toc.ncx_t | 15 ----------- 4 files changed, 59 deletions(-) delete mode 100644 sphinx/templates/epub2/container.xml delete mode 100644 sphinx/templates/epub2/content.opf_t delete mode 100644 sphinx/templates/epub2/mimetype delete mode 100644 sphinx/templates/epub2/toc.ncx_t diff --git a/sphinx/templates/epub2/container.xml b/sphinx/templates/epub2/container.xml deleted file mode 100644 index 326cf15fa..000000000 --- a/sphinx/templates/epub2/container.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/sphinx/templates/epub2/content.opf_t b/sphinx/templates/epub2/content.opf_t deleted file mode 100644 index 5169d0551..000000000 --- a/sphinx/templates/epub2/content.opf_t +++ /dev/null @@ -1,37 +0,0 @@ - - - - {{ lang }} - {{ title }} - {{ author }} - {{ publisher }} - {{ copyright }} - {{ id }} - {{ date }} - {%- if cover %} - - {%- endif %} - - - - {%- for item in manifest_items %} - - {%- endfor %} - - - {%- for spine in spines %} - {%- if spine.linear %} - - {%- else %} - - {%- endif %} - {%- endfor %} - - - {%- for guide in guides %} - - {%- endfor %} - - diff --git a/sphinx/templates/epub2/mimetype b/sphinx/templates/epub2/mimetype deleted file mode 100644 index 57ef03f24..000000000 --- a/sphinx/templates/epub2/mimetype +++ /dev/null @@ -1 +0,0 @@ -application/epub+zip \ No newline at end of file diff --git a/sphinx/templates/epub2/toc.ncx_t b/sphinx/templates/epub2/toc.ncx_t deleted file mode 100644 index 9bb701908..000000000 --- a/sphinx/templates/epub2/toc.ncx_t +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - {{ title }} - - -{{ navpoints }} - - From 9f7f5f2a44436d0c0779d8417781882b189263a7 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 28 Dec 2017 22:54:23 +0000 Subject: [PATCH 192/275] doc: Add missing sphinx-apidocs opt, envvar Add docs for '--module-first' option and 'SPHINX_APIDOC_OPTIONS' environment variable. Per the closest thing we have to official man page guidelines [1]: ENVIRONMENT lists all environment variables that affect the program or function and how they affect it. [1] https://linux.die.net/man/7/man-pages Signed-off-by: Stephen Finucane Fixes #2250 --- doc/man/sphinx-apidoc.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/man/sphinx-apidoc.rst b/doc/man/sphinx-apidoc.rst index 803466040..9a13f1401 100644 --- a/doc/man/sphinx-apidoc.rst +++ b/doc/man/sphinx-apidoc.rst @@ -91,7 +91,7 @@ Options Interpret paths recursively according to PEP-0420. -.. option:: -M +.. option:: -M, --module-first Put module documentation before submodule documentation. @@ -118,6 +118,14 @@ These options are used when :option:`--full` is specified: Sets the project release to put in generated files (see :confval:`release`). +Environment +----------- + +.. envvar:: SPHINX_APIDOC_OPTIONS + + A comma-separated list of option to append to generated ``automodule`` + directives. Defaults to ``members,undoc-members,show-inheritance``. + See also -------- From 4fd217ce88c596093887895197ccf75a7e99368c Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sun, 24 Dec 2017 15:24:10 +0000 Subject: [PATCH 193/275] circleci: Install packages ourselves Start installing Python dependencies and Sphinx itself as part of the CircleCI job rather than expecting it to be done in the Docker container. This ensures we will use the version of the packages for a given commit. This is the other half of sphinx-doc/docker-ci#1. Signed-off-by: Stephen Finucane --- .circleci/config.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1bbcb4884..f4d4415f1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -6,4 +6,6 @@ jobs: working_directory: /sphinx steps: - checkout + - run: /python3.4/bin/pip install -U pip setuptools + - run: /python3.4/bin/pip install -U .[test,websupport] - run: make test PYTHON=/python3.4/bin/python From 9348c4bea1bf75184bb4fe2af25c5990d6dcf2c1 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 22 Dec 2017 18:50:47 +0000 Subject: [PATCH 194/275] tests: Stop explicitly checking for modules This will have already been handled by setuptools. If the user isn't using this then they've dug their own grave. Signed-off-by: Stephen Finucane --- tests/run.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/tests/run.py b/tests/run.py index 2116e345c..217f8bea2 100755 --- a/tests/run.py +++ b/tests/run.py @@ -27,19 +27,6 @@ warnings.filterwarnings('ignore', category=ImportWarning, module='pkgutil') warnings.filterwarnings('ignore', category=ImportWarning, module='pytest_cov') warnings.filterwarnings('ignore', category=PendingDeprecationWarning, module=r'_pytest\..*') -# check dependencies before testing -print('Checking dependencies...') -for modname in ('pytest', 'mock', 'six', 'docutils', 'jinja2', 'pygments', - 'snowballstemmer', 'babel', 'html5lib'): - try: - __import__(modname) - except ImportError as err: - if modname == 'mock' and sys.version_info[0] == 3: - continue - traceback.print_exc() - print('The %r package is needed to run the Sphinx test suite.' % modname) - sys.exit(1) - # find a temp dir for testing and clean it up now os.environ['SPHINX_TEST_TEMPDIR'] = \ os.path.abspath(os.path.join(testroot, 'build')) \ From c33ecd1f8f1ea6eb7e410e91aec754bdd1d1f20a Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 22 Dec 2017 18:50:49 +0000 Subject: [PATCH 195/275] tests: Use 'pytest_report_header' This is the recommended way to print extra headers [1]. [1] https://docs.pytest.org/en/latest/example/simple.html#adding-info-to-test-report-header Signed-off-by: Stephen Finucane --- tests/conftest.py | 5 +++++ tests/run.py | 3 --- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 9ea99dbd9..d50d76df0 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -26,3 +26,8 @@ if sys.version_info < (3, 5): @pytest.fixture(scope='session') def rootdir(): return path(os.path.dirname(__file__) or '.').abspath() / 'roots' + + +def pytest_report_header(config): + return 'Running Sphinx test suite (with Python %s)...' % ( + sys.version.split()[0]) diff --git a/tests/run.py b/tests/run.py index 217f8bea2..aa797dbdb 100755 --- a/tests/run.py +++ b/tests/run.py @@ -39,8 +39,5 @@ if os.path.exists(tempdir): shutil.rmtree(tempdir) os.makedirs(tempdir) -print('Running Sphinx test suite (with Python %s)...' % sys.version.split()[0]) -sys.stdout.flush() - import pytest # NOQA sys.exit(pytest.main(sys.argv[1:])) From 529c96a3c991d167edd3f7181284b1f21315a486 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sun, 24 Dec 2017 20:28:46 +0000 Subject: [PATCH 196/275] tests: Use 'pytest_sessionstart' This is the recommended way to do pre-session configuration in pytest if not using session fixtures [1]. With this, we're able to remove the custom 'test/run.py' script in its entirety and run 'pytest' like everyone else does. We'll do this separately to keep things simple. [1] https://stackoverflow.com/a/12600154/613428 Signed-off-by: Stephen Finucane --- tests/conftest.py | 31 +++++++++++++++++++++++++++++++ tests/run.py | 29 +---------------------------- 2 files changed, 32 insertions(+), 28 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index d50d76df0..336484bcc 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,7 +8,9 @@ """ import os +import shutil import sys +import warnings import pytest from sphinx.testing.path import path @@ -31,3 +33,32 @@ def rootdir(): def pytest_report_header(config): return 'Running Sphinx test suite (with Python %s)...' % ( sys.version.split()[0]) + + +def _filter_warnings(): + def ignore(**kwargs): warnings.filterwarnings('ignore', **kwargs) + + ignore(category=DeprecationWarning, module='site') # virtualenv + ignore(category=PendingDeprecationWarning, module=r'_pytest\..*') + ignore(category=ImportWarning, module='backports') + ignore(category=ImportWarning, module='pkgutil') + ignore(category=ImportWarning, module='pytest_cov') + + +def _initialize_test_directory(session): + testroot = os.path.join(str(session.config.rootdir), 'tests') + tempdir = os.path.abspath(os.getenv('SPHINX_TEST_TEMPDIR', + os.path.join(testroot, 'build'))) + os.environ['SPHINX_TEST_TEMPDIR'] = tempdir + + print('Temporary files will be placed in %s.' % tempdir) + + if os.path.exists(tempdir): + shutil.rmtree(tempdir) + + os.makedirs(tempdir) + + +def pytest_sessionstart(session): + _filter_warnings() + _initialize_test_directory(session) diff --git a/tests/run.py b/tests/run.py index aa797dbdb..6c82db782 100755 --- a/tests/run.py +++ b/tests/run.py @@ -9,35 +9,8 @@ :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ -from __future__ import print_function - -import os import sys -import warnings -import traceback -import shutil -testroot = os.path.dirname(__file__) or '.' -sys.path.insert(0, os.path.abspath(os.path.join(testroot, os.path.pardir))) +import pytest -# filter warnings of test dependencies -warnings.filterwarnings('ignore', category=DeprecationWarning, module='site') # virtualenv -warnings.filterwarnings('ignore', category=ImportWarning, module='backports') -warnings.filterwarnings('ignore', category=ImportWarning, module='pkgutil') -warnings.filterwarnings('ignore', category=ImportWarning, module='pytest_cov') -warnings.filterwarnings('ignore', category=PendingDeprecationWarning, module=r'_pytest\..*') - -# find a temp dir for testing and clean it up now -os.environ['SPHINX_TEST_TEMPDIR'] = \ - os.path.abspath(os.path.join(testroot, 'build')) \ - if 'SPHINX_TEST_TEMPDIR' not in os.environ \ - else os.path.abspath(os.environ['SPHINX_TEST_TEMPDIR']) - -tempdir = os.environ['SPHINX_TEST_TEMPDIR'] -print('Temporary files will be placed in %s.' % tempdir) -if os.path.exists(tempdir): - shutil.rmtree(tempdir) -os.makedirs(tempdir) - -import pytest # NOQA sys.exit(pytest.main(sys.argv[1:])) From 7c0723fd46825ea44a98ae22ac45d08ca0ddd88b Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 22 Dec 2017 18:50:51 +0000 Subject: [PATCH 197/275] tests: Remove 'tests/run.py' This is no longer necessary. One test needs to be modified to deal with how 'python -m pytest' modifies the PATH. Signed-off-by: Stephen Finucane --- .appveyor.yml | 2 +- CONTRIBUTING.rst | 19 +++++++++++-------- Makefile | 4 ++-- tests/run.py | 16 ---------------- tests/test_pycode.py | 3 ++- tox.ini | 2 +- 6 files changed, 17 insertions(+), 29 deletions(-) delete mode 100755 tests/run.py diff --git a/.appveyor.yml b/.appveyor.yml index a3f83394f..d2c5d0d95 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -39,7 +39,7 @@ test_script: if (-not $test_ignore) { $test_ignore = '' } $tests = $env:TEST if (-not $tests) { $tests = '' } - & "C:\Python$($env:PYTHON)\python.exe" run.py $test_ignore.Split(' ') --junitxml .junit.xml $tests.Split(' ') + & "C:\Python$($env:PYTHON)\python.exe" -m pytest $test_ignore.Split(' ') --junitxml .junit.xml $tests.Split(' ') Pop-Location if ($LastExitCode -eq 1) { Write-Host "Test Failures Occurred, leaving for test result parsing" } elseif ($LastExitCode -ne 0) { Write-Host "Other Error Occurred, aborting"; exit $LastExitCode } diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index c4b8569b0..03d26c001 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -317,14 +317,17 @@ There are a couple reasons that code in Sphinx might be deprecated: no longer needs to support the older version of Python that doesn't include the library, the library will be deprecated in Sphinx. -As the :ref:`deprecation-policy` describes, -the first release of Sphinx that deprecates a feature (``A.B``) should raise a -``RemovedInSphinxXXWarning`` (where XX is the Sphinx version where the feature -will be removed) when the deprecated feature is invoked. Assuming we have good -test coverage, these warnings are converted to errors when running the test -suite with warnings enabled: ``python -Wall tests/run.py``. Thus, when adding -a ``RemovedInSphinxXXWarning`` you need to eliminate or silence any warnings -generated when running the tests. +As the :ref:`deprecation-policy` describes, the first release of Sphinx that +deprecates a feature (``A.B``) should raise a ``RemovedInSphinxXXWarning`` +(where ``XX`` is the Sphinx version where the feature will be removed) when the +deprecated feature is invoked. Assuming we have good test coverage, these +warnings are converted to errors when running the test suite with warnings +enabled:: + + pytest -Wall + +Thus, when adding a ``RemovedInSphinxXXWarning`` you need to eliminate or +silence any warnings generated when running the tests. .. _deprecation-policy: diff --git a/Makefile b/Makefile index e4abba088..67699363f 100644 --- a/Makefile +++ b/Makefile @@ -69,7 +69,7 @@ reindent: .PHONY: test test: - @cd tests; $(PYTHON) run.py -v $(TEST) + @$(PYTHON) -m pytest -v $(TEST) .PHONY: test-async test-async: @@ -77,7 +77,7 @@ test-async: .PHONY: covertest covertest: - @cd tests; $(PYTHON) run.py -v --cov=sphinx --junitxml=.junit.xml $(TEST) + @$(PYTHON) -m pytest -v --cov=sphinx --junitxml=.junit.xml $(TEST) .PHONY: build build: diff --git a/tests/run.py b/tests/run.py deleted file mode 100755 index 6c82db782..000000000 --- a/tests/run.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -""" - Sphinx unit test driver - ~~~~~~~~~~~~~~~~~~~~~~~ - - This script runs the Sphinx unit test suite. - - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. -""" -import sys - -import pytest - -sys.exit(pytest.main(sys.argv[1:])) diff --git a/tests/test_pycode.py b/tests/test_pycode.py index 2b5ae1514..400c47dc5 100644 --- a/tests/test_pycode.py +++ b/tests/test_pycode.py @@ -41,7 +41,8 @@ def test_ModuleAnalyzer_for_file(): def test_ModuleAnalyzer_for_module(): analyzer = ModuleAnalyzer.for_module('sphinx') assert analyzer.modname == 'sphinx' - assert analyzer.srcname == SPHINX_MODULE_PATH + assert analyzer.srcname in (SPHINX_MODULE_PATH, + os.path.abspath(SPHINX_MODULE_PATH)) assert analyzer.encoding == 'utf-8' diff --git a/tox.ini b/tox.ini index 36fdf83f4..0d19225f8 100644 --- a/tox.ini +++ b/tox.ini @@ -22,7 +22,7 @@ deps = setenv = SPHINX_TEST_TEMPDIR = {envdir}/testbuild commands= - {envpython} -Wall tests/run.py --durations 25 {posargs} + pytest -Wall --durations 25 {posargs} [testenv:flake8] description = From 9a3ebaaff5a24ed9f9ae9481acc0dbfd46281096 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 22 Dec 2017 18:50:53 +0000 Subject: [PATCH 198/275] Resolve warning filter issues There's an issue with 'pkgutils' and namespace packages. This has been reported against setuptools [1], but until this is resolved, we simply need to live with it. Ensure said warnings are filtered from tox too and remove some unnecessary ones. [1] https://github.com/pypa/setuptools/issues/1111 Signed-off-by: Stephen Finucane --- tests/conftest.py | 2 -- tox.ini | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 336484bcc..0d6b39681 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -40,9 +40,7 @@ def _filter_warnings(): ignore(category=DeprecationWarning, module='site') # virtualenv ignore(category=PendingDeprecationWarning, module=r'_pytest\..*') - ignore(category=ImportWarning, module='backports') ignore(category=ImportWarning, module='pkgutil') - ignore(category=ImportWarning, module='pytest_cov') def _initialize_test_directory(session): diff --git a/tox.ini b/tox.ini index 0d19225f8..99e243ad6 100644 --- a/tox.ini +++ b/tox.ini @@ -20,6 +20,7 @@ deps = du13: docutils==0.13.1 du14: docutils==0.14 setenv = + PYTHONWARNINGS = all,ignore::ImportWarning:pkgutil SPHINX_TEST_TEMPDIR = {envdir}/testbuild commands= pytest -Wall --durations 25 {posargs} From 60e25090a3d40f2883701df22aa778a2623d50a2 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sun, 24 Dec 2017 20:05:13 +0000 Subject: [PATCH 199/275] tox: Enable 'skipsdist' Given that we install Sphinx as part of the dependencies, there's no reason to do it twice. Skip that step. Signed-off-by: Stephen Finucane --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index 99e243ad6..ae6b2a4b3 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,7 @@ [tox] minversion = 2.0 envlist = docs,flake8,mypy,coverage,py{27,34,35,36,py},du{11,12,13,14} +skipsdist = True [testenv] passenv = From 54699dd263950527b55cfafc115b8d5ee7cfeacf Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 30 Dec 2017 00:38:17 +0900 Subject: [PATCH 200/275] Fix parallel_write_safe check was wrong --- sphinx/extension.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/extension.py b/sphinx/extension.py index 0520bf564..acbe0d865 100644 --- a/sphinx/extension.py +++ b/sphinx/extension.py @@ -38,7 +38,7 @@ class Extension(object): # The extension supports parallel write or not. The default value # is ``True``. Sphinx writes parallelly documents even if # the extension does not tell its status. - self.parallel_write_safe = kwargs.pop('parallel_read_safe', True) + self.parallel_write_safe = kwargs.pop('parallel_write_safe', True) def verify_required_extensions(app, requirements): From 1d3362425b95151d8ecfacbd53667b2663013580 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 30 Dec 2017 00:54:55 +0900 Subject: [PATCH 201/275] Add app.is_parallel_allowed() --- sphinx/application.py | 30 +++++++++++++++- sphinx/builders/__init__.py | 11 ++---- sphinx/environment/__init__.py | 17 ++------- tests/roots/test-extensions/conf.py | 4 +++ tests/roots/test-extensions/read_parallel.py | 4 +++ tests/roots/test-extensions/read_serial.py | 4 +++ tests/roots/test-extensions/write_parallel.py | 4 +++ tests/roots/test-extensions/write_serial.py | 4 +++ tests/test_application.py | 36 +++++++++++++++++++ 9 files changed, 91 insertions(+), 23 deletions(-) create mode 100644 tests/roots/test-extensions/conf.py create mode 100644 tests/roots/test-extensions/read_parallel.py create mode 100644 tests/roots/test-extensions/read_serial.py create mode 100644 tests/roots/test-extensions/write_parallel.py create mode 100644 tests/roots/test-extensions/write_serial.py diff --git a/sphinx/application.py b/sphinx/application.py index b6fd7feef..2a084ff0c 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -19,7 +19,7 @@ import posixpath from os import path from collections import deque -from six import iteritems +from six import iteritems, itervalues from six.moves import cStringIO from docutils import nodes @@ -673,6 +673,34 @@ class Sphinx(object): logger.debug('[app] adding HTML theme: %r, %r', name, theme_path) self.html_themes[name] = theme_path + # ---- other methods ------------------------------------------------- + def is_parallel_allowed(self, typ): + # type: (unicode) -> bool + """Check parallel processing is allowed or not. + + ``typ`` is a type of processing; ``'read'`` or ``'write'``. + """ + if typ == 'read': + attrname = 'parallel_read_safe' + elif typ == 'write': + attrname = 'parallel_write_safe' + else: + raise ValueError('parallel type %s is not supported' % typ) + + for ext in itervalues(self.extensions): + allowed = getattr(ext, attrname, None) + if allowed is None: + logger.warning(__("the %s extension does not declare if it is safe " + "for parallel %sing, assuming it isn't - please " + "ask the extension author to check and make it " + "explicit"), ext.name, typ) + logger.warning('doing serial %s', typ) + return False + elif not allowed: + return False + + return True + class TemplateBridge(object): """ diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index 8acd91729..d096ee4d7 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -371,15 +371,10 @@ class Builder(object): docnames = set(docnames) & self.env.found_docs # determine if we can write in parallel - self.parallel_ok = False if parallel_available and self.app.parallel > 1 and self.allow_parallel: - self.parallel_ok = True - for extension in itervalues(self.app.extensions): - if not extension.parallel_write_safe: - logger.warning('the %s extension is not safe for parallel ' - 'writing, doing serial write', extension.name) - self.parallel_ok = False - break + self.parallel_ok = self.app.is_parallel_allowed('write') + else: + self.parallel_ok = False # create a task executor to use for misc. "finish-up" tasks # if self.parallel_ok: diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index b4c40b608..583d41c1a 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -558,21 +558,10 @@ class BuildEnvironment(object): self.app.emit('env-before-read-docs', self, docnames) # check if we should do parallel or serial read - par_ok = False if parallel_available and len(docnames) > 5 and self.app.parallel > 1: - for ext in itervalues(self.app.extensions): - if ext.parallel_read_safe is None: - logger.warning(__('the %s extension does not declare if it is safe ' - 'for parallel reading, assuming it isn\'t - please ' - 'ask the extension author to check and make it ' - 'explicit'), ext.name) - logger.warning('doing serial read') - break - elif ext.parallel_read_safe is False: - break - else: - # all extensions support parallel-read - par_ok = True + par_ok = self.app.is_parallel_allowed('read') + else: + par_ok = False if par_ok: self._read_parallel(docnames, self.app, nproc=self.app.parallel) diff --git a/tests/roots/test-extensions/conf.py b/tests/roots/test-extensions/conf.py new file mode 100644 index 000000000..9a3cbc844 --- /dev/null +++ b/tests/roots/test-extensions/conf.py @@ -0,0 +1,4 @@ +import os +import sys + +sys.path.insert(0, os.path.abspath('.')) diff --git a/tests/roots/test-extensions/read_parallel.py b/tests/roots/test-extensions/read_parallel.py new file mode 100644 index 000000000..a3e052f95 --- /dev/null +++ b/tests/roots/test-extensions/read_parallel.py @@ -0,0 +1,4 @@ +def setup(app): + return { + 'parallel_read_safe': True + } diff --git a/tests/roots/test-extensions/read_serial.py b/tests/roots/test-extensions/read_serial.py new file mode 100644 index 000000000..c55570a5c --- /dev/null +++ b/tests/roots/test-extensions/read_serial.py @@ -0,0 +1,4 @@ +def setup(app): + return { + 'parallel_read_safe': False + } diff --git a/tests/roots/test-extensions/write_parallel.py b/tests/roots/test-extensions/write_parallel.py new file mode 100644 index 000000000..ebc48ef9b --- /dev/null +++ b/tests/roots/test-extensions/write_parallel.py @@ -0,0 +1,4 @@ +def setup(app): + return { + 'parallel_write_safe': True, + } diff --git a/tests/roots/test-extensions/write_serial.py b/tests/roots/test-extensions/write_serial.py new file mode 100644 index 000000000..75494ce77 --- /dev/null +++ b/tests/roots/test-extensions/write_serial.py @@ -0,0 +1,4 @@ +def setup(app): + return { + 'parallel_write_safe': False + } diff --git a/tests/test_application.py b/tests/test_application.py index 785a78878..1a4b22e3e 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -12,6 +12,7 @@ from docutils import nodes from sphinx.application import ExtensionError from sphinx.domains import Domain +from sphinx.util import logging from sphinx.testing.util import strip_escseq import pytest @@ -86,3 +87,38 @@ def test_add_source_parser(app, status, warning): assert set(app.registry.get_source_parsers().keys()) == set(['*', '.md', '.test']) assert app.registry.get_source_parsers()['.md'].__name__ == 'DummyMarkdownParser' assert app.registry.get_source_parsers()['.test'].__name__ == 'TestSourceParser' + + +@pytest.mark.sphinx(testroot='extensions') +def test_add_is_parallel_allowed(app, status, warning): + logging.setup(app, status, warning) + + assert app.is_parallel_allowed('read') is True + assert app.is_parallel_allowed('write') is True + assert warning.getvalue() == '' + + app.setup_extension('read_parallel') + assert app.is_parallel_allowed('read') is True + assert app.is_parallel_allowed('write') is True + assert warning.getvalue() == '' + app.extensions.pop('read_parallel') + + app.setup_extension('write_parallel') + assert app.is_parallel_allowed('read') is False + assert app.is_parallel_allowed('write') is True + assert 'the write_parallel extension does not declare' in warning.getvalue() + app.extensions.pop('write_parallel') + warning.truncate(0) # reset warnings + + app.setup_extension('read_serial') + assert app.is_parallel_allowed('read') is False + assert app.is_parallel_allowed('write') is True + assert warning.getvalue() == '' + app.extensions.pop('read_serial') + + app.setup_extension('write_serial') + assert app.is_parallel_allowed('read') is False + assert app.is_parallel_allowed('write') is False + assert 'the write_serial extension does not declare' in warning.getvalue() + app.extensions.pop('write_serial') + warning.truncate(0) # reset warnings From d7aa98aed7d5e5f361d76768c1abf12f912c3609 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 30 Dec 2017 01:21:22 +0900 Subject: [PATCH 202/275] Fix flake8 violations --- sphinx/builders/__init__.py | 1 - sphinx/environment/__init__.py | 1 - 2 files changed, 2 deletions(-) diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index d096ee4d7..6bba5c788 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -17,7 +17,6 @@ try: except ImportError: multiprocessing = None -from six import itervalues from docutils import nodes from sphinx.deprecation import RemovedInSphinx20Warning diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index 583d41c1a..2cbee2523 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -40,7 +40,6 @@ from sphinx.util.matching import compile_matchers from sphinx.util.parallel import ParallelTasks, parallel_available, make_chunks from sphinx.util.websupport import is_commentable from sphinx.errors import SphinxError, ExtensionError -from sphinx.locale import __ from sphinx.transforms import SphinxTransformer from sphinx.deprecation import RemovedInSphinx20Warning from sphinx.environment.adapters.indexentries import IndexEntries From 0059c05a857f4144e4eea8b3d2908e906cf7de49 Mon Sep 17 00:00:00 2001 From: jfbu Date: Sat, 30 Dec 2017 11:03:43 +0100 Subject: [PATCH 203/275] Rename smartquotable to notsmartquotable for intelligibility --- sphinx/transforms/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sphinx/transforms/__init__.py b/sphinx/transforms/__init__.py index 0ceced214..c5fe7864e 100644 --- a/sphinx/transforms/__init__.py +++ b/sphinx/transforms/__init__.py @@ -346,5 +346,5 @@ class SphinxSmartQuotes(SmartQuotes): texttype = {True: 'literal', # "literal" text is not changed: False: 'plain'} for txtnode in txtnodes: - smartquotable = not is_smartquotable(txtnode) - yield (texttype[smartquotable], txtnode.astext()) + notsmartquotable = not is_smartquotable(txtnode) + yield (texttype[notsmartquotable], txtnode.astext()) From 2426cedb8b12b7a59270e55f2f26d63d0014a28f Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 1 Jan 2018 01:06:58 +0900 Subject: [PATCH 204/275] A happy new year! --- LICENSE | 2 +- doc/_themes/sphinx13/layout.html | 2 +- doc/_themes/sphinx13/static/sphinx13.css | 2 +- doc/conf.py | 2 +- sphinx-apidoc.py | 2 +- sphinx-autogen.py | 2 +- sphinx-build.py | 2 +- sphinx-quickstart.py | 2 +- sphinx/__init__.py | 2 +- sphinx/__main__.py | 2 +- sphinx/addnodes.py | 2 +- sphinx/apidoc.py | 2 +- sphinx/application.py | 2 +- sphinx/builders/__init__.py | 2 +- sphinx/builders/_epub_base.py | 2 +- sphinx/builders/applehelp.py | 2 +- sphinx/builders/changes.py | 2 +- sphinx/builders/devhelp.py | 2 +- sphinx/builders/gettext.py | 2 +- sphinx/builders/html.py | 2 +- sphinx/builders/htmlhelp.py | 2 +- sphinx/builders/latex.py | 2 +- sphinx/builders/linkcheck.py | 2 +- sphinx/builders/manpage.py | 2 +- sphinx/builders/qthelp.py | 2 +- sphinx/builders/texinfo.py | 2 +- sphinx/builders/text.py | 2 +- sphinx/builders/websupport.py | 2 +- sphinx/builders/xml.py | 2 +- sphinx/cmdline.py | 2 +- sphinx/config.py | 2 +- sphinx/deprecation.py | 2 +- sphinx/directives/__init__.py | 2 +- sphinx/directives/code.py | 2 +- sphinx/directives/other.py | 2 +- sphinx/directives/patches.py | 2 +- sphinx/domains/__init__.py | 2 +- sphinx/domains/c.py | 2 +- sphinx/domains/cpp.py | 2 +- sphinx/domains/javascript.py | 2 +- sphinx/domains/python.py | 2 +- sphinx/domains/rst.py | 2 +- sphinx/domains/std.py | 2 +- sphinx/environment/__init__.py | 2 +- sphinx/environment/adapters/__init__.py | 2 +- sphinx/environment/adapters/asset.py | 2 +- sphinx/environment/adapters/indexentries.py | 2 +- sphinx/environment/adapters/toctree.py | 2 +- sphinx/environment/collectors/__init__.py | 2 +- sphinx/environment/collectors/asset.py | 2 +- sphinx/environment/collectors/dependencies.py | 2 +- sphinx/environment/collectors/indexentries.py | 2 +- sphinx/environment/collectors/metadata.py | 2 +- sphinx/environment/collectors/title.py | 2 +- sphinx/environment/collectors/toctree.py | 2 +- sphinx/errors.py | 2 +- sphinx/events.py | 2 +- sphinx/ext/__init__.py | 2 +- sphinx/ext/autodoc.py | 2 +- sphinx/ext/autosectionlabel.py | 2 +- sphinx/ext/autosummary/__init__.py | 2 +- sphinx/ext/autosummary/generate.py | 2 +- sphinx/ext/coverage.py | 2 +- sphinx/ext/doctest.py | 2 +- sphinx/ext/extlinks.py | 2 +- sphinx/ext/githubpages.py | 2 +- sphinx/ext/graphviz.py | 2 +- sphinx/ext/ifconfig.py | 2 +- sphinx/ext/imgconverter.py | 2 +- sphinx/ext/imgmath.py | 2 +- sphinx/ext/inheritance_diagram.py | 2 +- sphinx/ext/intersphinx.py | 2 +- sphinx/ext/jsmath.py | 2 +- sphinx/ext/linkcode.py | 2 +- sphinx/ext/mathbase.py | 2 +- sphinx/ext/mathjax.py | 2 +- sphinx/ext/napoleon/__init__.py | 2 +- sphinx/ext/napoleon/docstring.py | 2 +- sphinx/ext/napoleon/iterators.py | 2 +- sphinx/ext/pngmath.py | 2 +- sphinx/ext/todo.py | 2 +- sphinx/ext/viewcode.py | 2 +- sphinx/extension.py | 2 +- sphinx/highlighting.py | 2 +- sphinx/io.py | 2 +- sphinx/jinja2glue.py | 2 +- sphinx/make_mode.py | 2 +- sphinx/parsers.py | 2 +- sphinx/pycode/__init__.py | 2 +- sphinx/pycode/nodes.py | 2 +- sphinx/pygments_styles.py | 2 +- sphinx/quickstart.py | 2 +- sphinx/roles.py | 2 +- sphinx/search/__init__.py | 2 +- sphinx/search/en.py | 2 +- sphinx/search/ja.py | 2 +- sphinx/search/jssplitter.py | 2 +- sphinx/search/zh.py | 2 +- sphinx/setup_command.py | 2 +- sphinx/testing/__init__.py | 2 +- sphinx/testing/fixtures.py | 2 +- sphinx/testing/path.py | 2 +- sphinx/testing/util.py | 2 +- sphinx/themes/agogo/layout.html | 2 +- sphinx/themes/agogo/static/agogo.css_t | 2 +- sphinx/themes/basic/defindex.html | 2 +- sphinx/themes/basic/domainindex.html | 2 +- sphinx/themes/basic/genindex-single.html | 2 +- sphinx/themes/basic/genindex-split.html | 2 +- sphinx/themes/basic/genindex.html | 2 +- sphinx/themes/basic/globaltoc.html | 2 +- sphinx/themes/basic/layout.html | 2 +- sphinx/themes/basic/localtoc.html | 2 +- sphinx/themes/basic/page.html | 2 +- sphinx/themes/basic/relations.html | 2 +- sphinx/themes/basic/search.html | 2 +- sphinx/themes/basic/searchbox.html | 2 +- sphinx/themes/basic/searchresults.html | 2 +- sphinx/themes/basic/sourcelink.html | 2 +- sphinx/themes/basic/static/basic.css_t | 2 +- sphinx/themes/basic/static/doctools.js_t | 2 +- sphinx/themes/basic/static/searchtools.js_t | 2 +- sphinx/themes/basic/static/websupport.js | 2 +- sphinx/themes/classic/layout.html | 2 +- sphinx/themes/classic/static/classic.css_t | 2 +- sphinx/themes/classic/static/sidebar.js_t | 2 +- sphinx/themes/epub/epub-cover.html | 2 +- sphinx/themes/epub/layout.html | 2 +- sphinx/themes/epub/static/epub.css_t | 2 +- sphinx/themes/haiku/layout.html | 2 +- sphinx/themes/haiku/static/haiku.css_t | 2 +- sphinx/themes/nature/static/nature.css_t | 2 +- sphinx/themes/nonav/layout.html | 2 +- sphinx/themes/nonav/static/nonav.css | 2 +- sphinx/themes/pyramid/static/epub.css | 2 +- sphinx/themes/pyramid/static/pyramid.css_t | 2 +- sphinx/themes/scrolls/layout.html | 2 +- sphinx/themes/scrolls/static/scrolls.css_t | 2 +- sphinx/themes/sphinxdoc/layout.html | 2 +- sphinx/themes/sphinxdoc/static/sphinxdoc.css_t | 2 +- sphinx/themes/traditional/static/traditional.css_t | 2 +- sphinx/theming.py | 2 +- sphinx/transforms/__init__.py | 2 +- sphinx/transforms/compact_bullet_list.py | 2 +- sphinx/transforms/i18n.py | 2 +- sphinx/transforms/post_transforms/__init__.py | 2 +- sphinx/transforms/post_transforms/images.py | 2 +- sphinx/util/__init__.py | 2 +- sphinx/util/compat.py | 2 +- sphinx/util/console.py | 2 +- sphinx/util/docfields.py | 2 +- sphinx/util/docstrings.py | 2 +- sphinx/util/docutils.py | 2 +- sphinx/util/fileutil.py | 2 +- sphinx/util/i18n.py | 2 +- sphinx/util/images.py | 2 +- sphinx/util/inspect.py | 2 +- sphinx/util/inventory.py | 2 +- sphinx/util/jsdump.py | 2 +- sphinx/util/jsonimpl.py | 2 +- sphinx/util/logging.py | 2 +- sphinx/util/matching.py | 2 +- sphinx/util/nodes.py | 2 +- sphinx/util/osutil.py | 2 +- sphinx/util/parallel.py | 2 +- sphinx/util/png.py | 2 +- sphinx/util/pycompat.py | 2 +- sphinx/util/requests.py | 2 +- sphinx/util/rst.py | 2 +- sphinx/util/stemmer/__init__.py | 2 +- sphinx/util/tags.py | 2 +- sphinx/util/template.py | 2 +- sphinx/util/texescape.py | 2 +- sphinx/util/typing.py | 2 +- sphinx/util/websupport.py | 2 +- sphinx/versioning.py | 2 +- sphinx/websupport/__init__.py | 2 +- sphinx/websupport/errors.py | 2 +- sphinx/websupport/search/__init__.py | 2 +- sphinx/websupport/search/nullsearch.py | 2 +- sphinx/websupport/search/whooshsearch.py | 2 +- sphinx/websupport/search/xapiansearch.py | 2 +- sphinx/websupport/storage/__init__.py | 2 +- sphinx/websupport/storage/differ.py | 2 +- sphinx/websupport/storage/sqlalchemy_db.py | 2 +- sphinx/websupport/storage/sqlalchemystorage.py | 2 +- sphinx/writers/__init__.py | 2 +- sphinx/writers/html.py | 2 +- sphinx/writers/html5.py | 2 +- sphinx/writers/latex.py | 2 +- sphinx/writers/manpage.py | 2 +- sphinx/writers/texinfo.py | 2 +- sphinx/writers/text.py | 2 +- sphinx/writers/websupport.py | 2 +- sphinx/writers/xml.py | 2 +- tests/conftest.py | 2 +- tests/py35/test_autodoc_py35.py | 2 +- tests/run.py | 2 +- tests/test_api_translator.py | 2 +- tests/test_apidoc.py | 2 +- tests/test_application.py | 2 +- tests/test_autodoc.py | 2 +- tests/test_build.py | 2 +- tests/test_build_applehelp.py | 2 +- tests/test_build_gettext.py | 2 +- tests/test_build_html.py | 2 +- tests/test_build_html5.py | 2 +- tests/test_build_latex.py | 2 +- tests/test_build_linkcheck.py | 2 +- tests/test_build_manpage.py | 2 +- tests/test_build_texinfo.py | 2 +- tests/test_build_text.py | 2 +- tests/test_catalogs.py | 2 +- tests/test_config.py | 2 +- tests/test_correct_year.py | 2 +- tests/test_directive_code.py | 2 +- tests/test_directive_only.py | 2 +- tests/test_docutilsconf.py | 2 +- tests/test_domain_cpp.py | 2 +- tests/test_domain_js.py | 2 +- tests/test_domain_py.py | 2 +- tests/test_domain_rst.py | 2 +- tests/test_domain_std.py | 2 +- tests/test_environment.py | 2 +- tests/test_environment_indexentries.py | 2 +- tests/test_environment_toctree.py | 2 +- tests/test_ext_autodoc.py | 2 +- tests/test_ext_autosectionlabel.py | 2 +- tests/test_ext_autosummary.py | 2 +- tests/test_ext_coverage.py | 2 +- tests/test_ext_doctest.py | 2 +- tests/test_ext_githubpages.py | 2 +- tests/test_ext_graphviz.py | 2 +- tests/test_ext_ifconfig.py | 2 +- tests/test_ext_imgconverter.py | 2 +- tests/test_ext_inheritance_diagram.py | 2 +- tests/test_ext_intersphinx.py | 2 +- tests/test_ext_math.py | 2 +- tests/test_ext_napoleon.py | 2 +- tests/test_ext_napoleon_docstring.py | 2 +- tests/test_ext_napoleon_iterators.py | 2 +- tests/test_ext_todo.py | 2 +- tests/test_ext_viewcode.py | 2 +- tests/test_highlighting.py | 2 +- tests/test_intl.py | 2 +- tests/test_markup.py | 2 +- tests/test_metadata.py | 2 +- tests/test_quickstart.py | 2 +- tests/test_search.py | 2 +- tests/test_setup_command.py | 2 +- tests/test_templating.py | 2 +- tests/test_theming.py | 2 +- tests/test_toctree.py | 2 +- tests/test_util.py | 2 +- tests/test_util_fileutil.py | 2 +- tests/test_util_i18n.py | 2 +- tests/test_util_images.py | 2 +- tests/test_util_inspect.py | 2 +- tests/test_util_logging.py | 2 +- tests/test_util_matching.py | 2 +- tests/test_util_nodes.py | 2 +- tests/test_util_rst.py | 2 +- tests/test_versioning.py | 2 +- tests/test_websupport.py | 2 +- tests/test_writer_latex.py | 2 +- utils/check_sources.py | 2 +- utils/jssplitter_generator.py | 2 +- 267 files changed, 267 insertions(+), 267 deletions(-) diff --git a/LICENSE b/LICENSE index a2783ab3f..19f1090fd 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ License for Sphinx ================== -Copyright (c) 2007-2017 by the Sphinx team (see AUTHORS file). +Copyright (c) 2007-2018 by the Sphinx team (see AUTHORS file). All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/doc/_themes/sphinx13/layout.html b/doc/_themes/sphinx13/layout.html index fdac6d0a2..cd870fe7b 100644 --- a/doc/_themes/sphinx13/layout.html +++ b/doc/_themes/sphinx13/layout.html @@ -4,7 +4,7 @@ Sphinx layout template for the sphinxdoc theme. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- extends "basic/layout.html" %} diff --git a/doc/_themes/sphinx13/static/sphinx13.css b/doc/_themes/sphinx13/static/sphinx13.css index d15fbaea4..6bdc5a96c 100644 --- a/doc/_themes/sphinx13/static/sphinx13.css +++ b/doc/_themes/sphinx13/static/sphinx13.css @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- sphinx13 theme. * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/doc/conf.py b/doc/conf.py index 62c5c13d5..1f19b53a2 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -15,7 +15,7 @@ templates_path = ['_templates'] exclude_patterns = ['_build'] project = 'Sphinx' -copyright = '2007-2017, Georg Brandl and the Sphinx team' +copyright = '2007-2018, Georg Brandl and the Sphinx team' version = sphinx.__display_version__ release = version show_authors = True diff --git a/sphinx-apidoc.py b/sphinx-apidoc.py index 0290d6c50..8279feaaa 100755 --- a/sphinx-apidoc.py +++ b/sphinx-apidoc.py @@ -4,7 +4,7 @@ Sphinx - Python documentation toolchain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx-autogen.py b/sphinx-autogen.py index 8320b2c14..6c10f0e64 100755 --- a/sphinx-autogen.py +++ b/sphinx-autogen.py @@ -4,7 +4,7 @@ Sphinx - Python documentation toolchain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx-build.py b/sphinx-build.py index ae60c0724..1b8d14082 100755 --- a/sphinx-build.py +++ b/sphinx-build.py @@ -4,7 +4,7 @@ Sphinx - Python documentation toolchain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx-quickstart.py b/sphinx-quickstart.py index bf8423fa6..81d6b6696 100755 --- a/sphinx-quickstart.py +++ b/sphinx-quickstart.py @@ -4,7 +4,7 @@ Sphinx - Python documentation toolchain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/__init__.py b/sphinx/__init__.py index 4facec53e..b8a62f9e8 100644 --- a/sphinx/__init__.py +++ b/sphinx/__init__.py @@ -5,7 +5,7 @@ The Sphinx documentation toolchain. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/__main__.py b/sphinx/__main__.py index 544505a6c..06b1812f2 100644 --- a/sphinx/__main__.py +++ b/sphinx/__main__.py @@ -5,7 +5,7 @@ The Sphinx documentation toolchain. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import sys diff --git a/sphinx/addnodes.py b/sphinx/addnodes.py index 762dc9bbb..e6999bd16 100644 --- a/sphinx/addnodes.py +++ b/sphinx/addnodes.py @@ -5,7 +5,7 @@ Additional docutils nodes. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/apidoc.py b/sphinx/apidoc.py index b764cfc35..8f9694cdd 100644 --- a/sphinx/apidoc.py +++ b/sphinx/apidoc.py @@ -11,7 +11,7 @@ Copyright 2008 Société des arts technologiques (SAT), http://www.sat.qc.ca/ - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/application.py b/sphinx/application.py index b5705face..d23d97fbd 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -7,7 +7,7 @@ Gracefully adapted from the TextPress system by Armin. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index a1d5c5d22..4b977cbc2 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -5,7 +5,7 @@ Builder superclass for all builders. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/_epub_base.py b/sphinx/builders/_epub_base.py index b68fdbacc..411ea7067 100644 --- a/sphinx/builders/_epub_base.py +++ b/sphinx/builders/_epub_base.py @@ -5,7 +5,7 @@ Base class of epub2/epub3 builders. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/applehelp.py b/sphinx/builders/applehelp.py index f8df9310c..52ba2ce5c 100644 --- a/sphinx/builders/applehelp.py +++ b/sphinx/builders/applehelp.py @@ -5,7 +5,7 @@ Build Apple help books. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/builders/changes.py b/sphinx/builders/changes.py index 5c3072059..f18076700 100644 --- a/sphinx/builders/changes.py +++ b/sphinx/builders/changes.py @@ -5,7 +5,7 @@ Changelog builder. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/devhelp.py b/sphinx/builders/devhelp.py index 9dbbf3c17..88a9be219 100644 --- a/sphinx/builders/devhelp.py +++ b/sphinx/builders/devhelp.py @@ -7,7 +7,7 @@ .. _Devhelp: http://live.gnome.org/devhelp - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import absolute_import diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py index b684104c1..464d574cc 100644 --- a/sphinx/builders/gettext.py +++ b/sphinx/builders/gettext.py @@ -5,7 +5,7 @@ The MessageCatalogBuilder class. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index e50d2abe4..68f38320b 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -5,7 +5,7 @@ Several HTML builders. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/htmlhelp.py b/sphinx/builders/htmlhelp.py index c2e3bbe2c..0b45601e3 100644 --- a/sphinx/builders/htmlhelp.py +++ b/sphinx/builders/htmlhelp.py @@ -6,7 +6,7 @@ Build HTML help support files. Parts adapted from Python's Doc/tools/prechm.py. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/builders/latex.py b/sphinx/builders/latex.py index 03a75caab..d93b0ab99 100644 --- a/sphinx/builders/latex.py +++ b/sphinx/builders/latex.py @@ -5,7 +5,7 @@ LaTeX builder. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py index c52b808cd..ca62b9fe1 100644 --- a/sphinx/builders/linkcheck.py +++ b/sphinx/builders/linkcheck.py @@ -5,7 +5,7 @@ The CheckExternalLinksBuilder class. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/manpage.py b/sphinx/builders/manpage.py index 83e354601..b57a756ee 100644 --- a/sphinx/builders/manpage.py +++ b/sphinx/builders/manpage.py @@ -5,7 +5,7 @@ Manual pages builder. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/qthelp.py b/sphinx/builders/qthelp.py index 12a50d140..07efd02ab 100644 --- a/sphinx/builders/qthelp.py +++ b/sphinx/builders/qthelp.py @@ -5,7 +5,7 @@ Build input files for the Qt collection generator. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/texinfo.py b/sphinx/builders/texinfo.py index 3e6816507..82c6f1b9d 100644 --- a/sphinx/builders/texinfo.py +++ b/sphinx/builders/texinfo.py @@ -5,7 +5,7 @@ Texinfo builder. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/text.py b/sphinx/builders/text.py index 29ceaa855..7b977b1b9 100644 --- a/sphinx/builders/text.py +++ b/sphinx/builders/text.py @@ -5,7 +5,7 @@ Plain-text Sphinx builder. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/websupport.py b/sphinx/builders/websupport.py index 2e416b287..1fe9e2001 100644 --- a/sphinx/builders/websupport.py +++ b/sphinx/builders/websupport.py @@ -5,7 +5,7 @@ Builder for the web support package. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/builders/xml.py b/sphinx/builders/xml.py index d4ebb47ef..599530ac1 100644 --- a/sphinx/builders/xml.py +++ b/sphinx/builders/xml.py @@ -5,7 +5,7 @@ Docutils-native XML and pseudo-XML builders. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/cmdline.py b/sphinx/cmdline.py index 79a69cd7b..c9a0dd4c6 100644 --- a/sphinx/cmdline.py +++ b/sphinx/cmdline.py @@ -5,7 +5,7 @@ sphinx-build command-line handling. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/config.py b/sphinx/config.py index cc5f57e8e..d3468b0a5 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -5,7 +5,7 @@ Build configuration file handling. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/deprecation.py b/sphinx/deprecation.py index 608b23c1b..93395fa7d 100644 --- a/sphinx/deprecation.py +++ b/sphinx/deprecation.py @@ -5,7 +5,7 @@ Sphinx deprecation classes and utilities. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/directives/__init__.py b/sphinx/directives/__init__.py index dc0cc4f6c..dc51810d3 100644 --- a/sphinx/directives/__init__.py +++ b/sphinx/directives/__init__.py @@ -5,7 +5,7 @@ Handlers for additional ReST directives. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py index 41a593aa3..9758cbbe8 100644 --- a/sphinx/directives/code.py +++ b/sphinx/directives/code.py @@ -3,7 +3,7 @@ sphinx.directives.code ~~~~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py index 626218ca2..4ce709a63 100644 --- a/sphinx/directives/other.py +++ b/sphinx/directives/other.py @@ -3,7 +3,7 @@ sphinx.directives.other ~~~~~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/directives/patches.py b/sphinx/directives/patches.py index 880377ff7..c97340a81 100644 --- a/sphinx/directives/patches.py +++ b/sphinx/directives/patches.py @@ -3,7 +3,7 @@ sphinx.directives.patches ~~~~~~~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/domains/__init__.py b/sphinx/domains/__init__.py index 6edc3cdb0..a6d28a06d 100644 --- a/sphinx/domains/__init__.py +++ b/sphinx/domains/__init__.py @@ -6,7 +6,7 @@ Support for domains, which are groupings of description directives and roles describing e.g. constructs of one programming language. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/domains/c.py b/sphinx/domains/c.py index b9afd10c2..3030cff8a 100644 --- a/sphinx/domains/c.py +++ b/sphinx/domains/c.py @@ -5,7 +5,7 @@ The C language domain. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index aa97481ab..fa9eaa5e8 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -5,7 +5,7 @@ The C++ language domain. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/domains/javascript.py b/sphinx/domains/javascript.py index 9ecf4a4b0..81f86f754 100644 --- a/sphinx/domains/javascript.py +++ b/sphinx/domains/javascript.py @@ -5,7 +5,7 @@ The JavaScript domain. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index 6aa00a8b0..432e9b542 100644 --- a/sphinx/domains/python.py +++ b/sphinx/domains/python.py @@ -5,7 +5,7 @@ The Python domain. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/domains/rst.py b/sphinx/domains/rst.py index 2a7dffc4d..936dd1b9f 100644 --- a/sphinx/domains/rst.py +++ b/sphinx/domains/rst.py @@ -5,7 +5,7 @@ The reStructuredText domain. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py index bfaa57c4f..27bb88c96 100644 --- a/sphinx/domains/std.py +++ b/sphinx/domains/std.py @@ -5,7 +5,7 @@ The standard domain. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index 522414ea6..65a73b019 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -5,7 +5,7 @@ Global creation environment. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/environment/adapters/__init__.py b/sphinx/environment/adapters/__init__.py index 9171ac0be..f945c4250 100644 --- a/sphinx/environment/adapters/__init__.py +++ b/sphinx/environment/adapters/__init__.py @@ -5,6 +5,6 @@ Sphinx environment adapters - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/environment/adapters/asset.py b/sphinx/environment/adapters/asset.py index 02557a8c4..91f2cf8eb 100644 --- a/sphinx/environment/adapters/asset.py +++ b/sphinx/environment/adapters/asset.py @@ -5,7 +5,7 @@ Assets adapter for sphinx.environment. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/environment/adapters/indexentries.py b/sphinx/environment/adapters/indexentries.py index 946e635ef..4a39b1bd0 100644 --- a/sphinx/environment/adapters/indexentries.py +++ b/sphinx/environment/adapters/indexentries.py @@ -5,7 +5,7 @@ Index entries adapters for sphinx.environment. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import re diff --git a/sphinx/environment/adapters/toctree.py b/sphinx/environment/adapters/toctree.py index 03c1d8aa9..bf725b619 100644 --- a/sphinx/environment/adapters/toctree.py +++ b/sphinx/environment/adapters/toctree.py @@ -5,7 +5,7 @@ Toctree adapter for sphinx.environment. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/environment/collectors/__init__.py b/sphinx/environment/collectors/__init__.py index 917b34afb..9d9f5347c 100644 --- a/sphinx/environment/collectors/__init__.py +++ b/sphinx/environment/collectors/__init__.py @@ -5,7 +5,7 @@ The data collector components for sphinx.environment. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/environment/collectors/asset.py b/sphinx/environment/collectors/asset.py index 3a0e1fefd..0d7a193e3 100644 --- a/sphinx/environment/collectors/asset.py +++ b/sphinx/environment/collectors/asset.py @@ -5,7 +5,7 @@ The image collector for sphinx.environment. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/environment/collectors/dependencies.py b/sphinx/environment/collectors/dependencies.py index 5e20d1245..bf42b12e9 100644 --- a/sphinx/environment/collectors/dependencies.py +++ b/sphinx/environment/collectors/dependencies.py @@ -5,7 +5,7 @@ The dependencies collector components for sphinx.environment. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/environment/collectors/indexentries.py b/sphinx/environment/collectors/indexentries.py index 0b1c35934..f9fa8bab7 100644 --- a/sphinx/environment/collectors/indexentries.py +++ b/sphinx/environment/collectors/indexentries.py @@ -5,7 +5,7 @@ Index entries collector for sphinx.environment. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/environment/collectors/metadata.py b/sphinx/environment/collectors/metadata.py index ae8a8cb4c..7d54d2fe6 100644 --- a/sphinx/environment/collectors/metadata.py +++ b/sphinx/environment/collectors/metadata.py @@ -5,7 +5,7 @@ The metadata collector components for sphinx.environment. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/environment/collectors/title.py b/sphinx/environment/collectors/title.py index 3335c2cc7..eb23b975f 100644 --- a/sphinx/environment/collectors/title.py +++ b/sphinx/environment/collectors/title.py @@ -5,7 +5,7 @@ The title collector components for sphinx.environment. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/environment/collectors/toctree.py b/sphinx/environment/collectors/toctree.py index 91aa21f2e..53e1045d9 100644 --- a/sphinx/environment/collectors/toctree.py +++ b/sphinx/environment/collectors/toctree.py @@ -5,7 +5,7 @@ Toctree collector for sphinx.environment. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/errors.py b/sphinx/errors.py index 7662c95a3..eef1a157a 100644 --- a/sphinx/errors.py +++ b/sphinx/errors.py @@ -6,7 +6,7 @@ Contains SphinxError and a few subclasses (in an extra module to avoid circular import problems). - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/events.py b/sphinx/events.py index 99decfff5..097f61fc6 100644 --- a/sphinx/events.py +++ b/sphinx/events.py @@ -7,7 +7,7 @@ Gracefully adapted from the TextPress system by Armin. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/ext/__init__.py b/sphinx/ext/__init__.py index e529ee9e5..440c01a15 100644 --- a/sphinx/ext/__init__.py +++ b/sphinx/ext/__init__.py @@ -5,6 +5,6 @@ Contains Sphinx features not activated by default. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index 3cc87904a..e04b4a09d 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -7,7 +7,7 @@ the doctree, thus avoiding duplication between docstrings and documentation for those who like elaborate docstrings. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/autosectionlabel.py b/sphinx/ext/autosectionlabel.py index 69b8c6873..fbb7d037f 100644 --- a/sphinx/ext/autosectionlabel.py +++ b/sphinx/ext/autosectionlabel.py @@ -5,7 +5,7 @@ Allow reference sections by :ref: role using its title. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 67bbf6d91..08776badc 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -49,7 +49,7 @@ resolved to a Python object, and otherwise it becomes simple emphasis. This can be used as the default role to make links 'smart'. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index 775490471..99d5d5796 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -14,7 +14,7 @@ generate: sphinx-autogen -o source/generated source/*.rst - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/ext/coverage.py b/sphinx/ext/coverage.py index 02843ac83..476a0ed46 100644 --- a/sphinx/ext/coverage.py +++ b/sphinx/ext/coverage.py @@ -6,7 +6,7 @@ Check Python modules and C API for coverage. Mostly written by Josip Dzolonga for the Google Highly Open Participation contest. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py index 4110d9c90..e0ce050f7 100644 --- a/sphinx/ext/doctest.py +++ b/sphinx/ext/doctest.py @@ -6,7 +6,7 @@ Mimic doctest by automatically executing code snippets and checking their results. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import absolute_import diff --git a/sphinx/ext/extlinks.py b/sphinx/ext/extlinks.py index 00180b35c..c247e6722 100644 --- a/sphinx/ext/extlinks.py +++ b/sphinx/ext/extlinks.py @@ -20,7 +20,7 @@ You can also give an explicit caption, e.g. :exmpl:`Foo `. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/githubpages.py b/sphinx/ext/githubpages.py index 028b65622..7d673a72d 100644 --- a/sphinx/ext/githubpages.py +++ b/sphinx/ext/githubpages.py @@ -5,7 +5,7 @@ To publish HTML docs at GitHub Pages, create .nojekyll file. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py index 2a83474ce..546594843 100644 --- a/sphinx/ext/graphviz.py +++ b/sphinx/ext/graphviz.py @@ -6,7 +6,7 @@ Allow graphviz-formatted graphs to be included in Sphinx-generated documents inline. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/ifconfig.py b/sphinx/ext/ifconfig.py index c700649dd..16042ac3f 100644 --- a/sphinx/ext/ifconfig.py +++ b/sphinx/ext/ifconfig.py @@ -16,7 +16,7 @@ namespace of the project configuration (that is, all variables from ``conf.py`` are available.) - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/imgconverter.py b/sphinx/ext/imgconverter.py index d2894b2a3..95f579e36 100644 --- a/sphinx/ext/imgconverter.py +++ b/sphinx/ext/imgconverter.py @@ -5,7 +5,7 @@ Image converter extension for Sphinx - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import subprocess diff --git a/sphinx/ext/imgmath.py b/sphinx/ext/imgmath.py index 8bf4fcad5..f4a144403 100644 --- a/sphinx/ext/imgmath.py +++ b/sphinx/ext/imgmath.py @@ -5,7 +5,7 @@ Render math in HTML via dvipng or dvisvgm. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py index f5b0228a5..34fe7bea6 100644 --- a/sphinx/ext/inheritance_diagram.py +++ b/sphinx/ext/inheritance_diagram.py @@ -32,7 +32,7 @@ r""" The graph is inserted as a PNG+image map into HTML and a PDF in LaTeX. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py index ad50542a3..ccd2c9321 100644 --- a/sphinx/ext/intersphinx.py +++ b/sphinx/ext/intersphinx.py @@ -20,7 +20,7 @@ also be specified individually, e.g. if the docs should be buildable without Internet access. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/jsmath.py b/sphinx/ext/jsmath.py index dc57c13c6..21ec3cd23 100644 --- a/sphinx/ext/jsmath.py +++ b/sphinx/ext/jsmath.py @@ -6,7 +6,7 @@ Set up everything for use of JSMath to display math in HTML via JavaScript. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/linkcode.py b/sphinx/ext/linkcode.py index e74ee8529..a42dab528 100644 --- a/sphinx/ext/linkcode.py +++ b/sphinx/ext/linkcode.py @@ -5,7 +5,7 @@ Add external links to module code in Python object descriptions. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py index baa4df176..549ca30cd 100644 --- a/sphinx/ext/mathbase.py +++ b/sphinx/ext/mathbase.py @@ -5,7 +5,7 @@ Set up math support in source files and LaTeX/text output. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py index f25f91e74..7fb3b17ad 100644 --- a/sphinx/ext/mathjax.py +++ b/sphinx/ext/mathjax.py @@ -7,7 +7,7 @@ Sphinx's HTML writer -- requires the MathJax JavaScript library on your webserver/computer. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/napoleon/__init__.py b/sphinx/ext/napoleon/__init__.py index 7aca9b629..b65f7f2a1 100644 --- a/sphinx/ext/napoleon/__init__.py +++ b/sphinx/ext/napoleon/__init__.py @@ -5,7 +5,7 @@ Support for NumPy and Google style docstrings. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py index d3a64049b..b349c761f 100644 --- a/sphinx/ext/napoleon/docstring.py +++ b/sphinx/ext/napoleon/docstring.py @@ -7,7 +7,7 @@ Classes for docstring parsing and formatting. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/napoleon/iterators.py b/sphinx/ext/napoleon/iterators.py index b03bcf047..b4bba8863 100644 --- a/sphinx/ext/napoleon/iterators.py +++ b/sphinx/ext/napoleon/iterators.py @@ -7,7 +7,7 @@ A collection of helpful iterators. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/pngmath.py b/sphinx/ext/pngmath.py index 85010b799..eb1c82e8f 100644 --- a/sphinx/ext/pngmath.py +++ b/sphinx/ext/pngmath.py @@ -6,7 +6,7 @@ Render math in HTML via dvipng. This extension has been deprecated; please use sphinx.ext.imgmath instead. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/todo.py b/sphinx/ext/todo.py index badfbc35f..e60620b5b 100644 --- a/sphinx/ext/todo.py +++ b/sphinx/ext/todo.py @@ -8,7 +8,7 @@ all todos of your project and lists them along with a backlink to the original location. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py index 25e5fe82a..2fd4479f8 100644 --- a/sphinx/ext/viewcode.py +++ b/sphinx/ext/viewcode.py @@ -5,7 +5,7 @@ Add links to module code in Python object descriptions. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/extension.py b/sphinx/extension.py index 0520bf564..8a2f945ae 100644 --- a/sphinx/extension.py +++ b/sphinx/extension.py @@ -5,7 +5,7 @@ Utilities for Sphinx extensions. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py index eb309d82a..eef24ee95 100644 --- a/sphinx/highlighting.py +++ b/sphinx/highlighting.py @@ -5,7 +5,7 @@ Highlight code blocks using Pygments. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/io.py b/sphinx/io.py index 8f048c7fc..8365e22e0 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -5,7 +5,7 @@ Input/Output files - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from docutils.io import FileInput diff --git a/sphinx/jinja2glue.py b/sphinx/jinja2glue.py index 41d48ad34..8839e48fa 100644 --- a/sphinx/jinja2glue.py +++ b/sphinx/jinja2glue.py @@ -5,7 +5,7 @@ Glue code for the jinja2 templating engine. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/make_mode.py b/sphinx/make_mode.py index e7962db2e..f22a63b09 100644 --- a/sphinx/make_mode.py +++ b/sphinx/make_mode.py @@ -11,7 +11,7 @@ This is in its own module so that importing it is fast. It should not import the main Sphinx modules (like sphinx.applications, sphinx.builders). - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/parsers.py b/sphinx/parsers.py index 33556e487..b58eefa23 100644 --- a/sphinx/parsers.py +++ b/sphinx/parsers.py @@ -5,7 +5,7 @@ A Base class for additional parsers. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/pycode/__init__.py b/sphinx/pycode/__init__.py index eabcc8188..92d96cecf 100644 --- a/sphinx/pycode/__init__.py +++ b/sphinx/pycode/__init__.py @@ -5,7 +5,7 @@ Utilities parsing and analyzing Python code. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/pycode/nodes.py b/sphinx/pycode/nodes.py index ea3b3e9ad..52bba1a35 100644 --- a/sphinx/pycode/nodes.py +++ b/sphinx/pycode/nodes.py @@ -5,7 +5,7 @@ Parse tree node implementations. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/pygments_styles.py b/sphinx/pygments_styles.py index a70005d7c..d29d825d5 100644 --- a/sphinx/pygments_styles.py +++ b/sphinx/pygments_styles.py @@ -5,7 +5,7 @@ Sphinx theme specific highlighting styles. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index 5d8738996..a36c57528 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -5,7 +5,7 @@ Quickly setup documentation source to work with Sphinx. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/roles.py b/sphinx/roles.py index 4007b9f88..223c6c21f 100644 --- a/sphinx/roles.py +++ b/sphinx/roles.py @@ -5,7 +5,7 @@ Handlers for additional ReST roles. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/search/__init__.py b/sphinx/search/__init__.py index 17560213d..d56b9e626 100644 --- a/sphinx/search/__init__.py +++ b/sphinx/search/__init__.py @@ -5,7 +5,7 @@ Create a full-text search index for offline search. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import re diff --git a/sphinx/search/en.py b/sphinx/search/en.py index f7ce43350..fe9b7d8da 100644 --- a/sphinx/search/en.py +++ b/sphinx/search/en.py @@ -5,7 +5,7 @@ English search language: includes the JS porter stemmer. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/search/ja.py b/sphinx/search/ja.py index d1d922dd4..0cdc14a11 100644 --- a/sphinx/search/ja.py +++ b/sphinx/search/ja.py @@ -5,7 +5,7 @@ Japanese search language: includes routine to split words. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/search/jssplitter.py b/sphinx/search/jssplitter.py index 56b91c1d0..7166565f1 100644 --- a/sphinx/search/jssplitter.py +++ b/sphinx/search/jssplitter.py @@ -7,7 +7,7 @@ DO NOT EDIT. This is generated by utils/jssplitter_generator.py - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/search/zh.py b/sphinx/search/zh.py index bf01812e0..c9ae890ed 100644 --- a/sphinx/search/zh.py +++ b/sphinx/search/zh.py @@ -5,7 +5,7 @@ Chinese search language: includes routine to split words. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/setup_command.py b/sphinx/setup_command.py index 8c00a2ff8..cd89fe7f7 100644 --- a/sphinx/setup_command.py +++ b/sphinx/setup_command.py @@ -8,7 +8,7 @@ :author: Sebastian Wiesner :contact: basti.wiesner@gmx.net - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/testing/__init__.py b/sphinx/testing/__init__.py index e246be8c0..c551da36f 100644 --- a/sphinx/testing/__init__.py +++ b/sphinx/testing/__init__.py @@ -10,6 +10,6 @@ pytest_plugins = 'sphinx.testing.fixtures' - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/testing/fixtures.py b/sphinx/testing/fixtures.py index 624adc03a..be0037b70 100644 --- a/sphinx/testing/fixtures.py +++ b/sphinx/testing/fixtures.py @@ -5,7 +5,7 @@ Sphinx test fixtures for pytest - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/testing/path.py b/sphinx/testing/path.py index 634d61332..30c4b49f3 100644 --- a/sphinx/testing/path.py +++ b/sphinx/testing/path.py @@ -3,7 +3,7 @@ sphinx.testing.path ~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import os diff --git a/sphinx/testing/util.py b/sphinx/testing/util.py index c1b2ae2b2..d8d06d3d4 100644 --- a/sphinx/testing/util.py +++ b/sphinx/testing/util.py @@ -5,7 +5,7 @@ Sphinx test suite utilities - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import os diff --git a/sphinx/themes/agogo/layout.html b/sphinx/themes/agogo/layout.html index dcf5b0ed7..8bd476cad 100644 --- a/sphinx/themes/agogo/layout.html +++ b/sphinx/themes/agogo/layout.html @@ -5,7 +5,7 @@ Sphinx layout template for the agogo theme, originally written by Andi Albrecht. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- extends "basic/layout.html" %} diff --git a/sphinx/themes/agogo/static/agogo.css_t b/sphinx/themes/agogo/static/agogo.css_t index f9e0d1637..0b5bbe16b 100644 --- a/sphinx/themes/agogo/static/agogo.css_t +++ b/sphinx/themes/agogo/static/agogo.css_t @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- agogo theme. * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/basic/defindex.html b/sphinx/themes/basic/defindex.html index 303f9668b..5c92348b9 100644 --- a/sphinx/themes/basic/defindex.html +++ b/sphinx/themes/basic/defindex.html @@ -4,7 +4,7 @@ Default template for the "index" page. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #}{{ warn('Now base template defindex.html is deprecated.') }} {%- extends "layout.html" %} diff --git a/sphinx/themes/basic/domainindex.html b/sphinx/themes/basic/domainindex.html index dafbf72dc..58f0fc990 100644 --- a/sphinx/themes/basic/domainindex.html +++ b/sphinx/themes/basic/domainindex.html @@ -4,7 +4,7 @@ Template for domain indices (module index, ...). - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- extends "layout.html" %} diff --git a/sphinx/themes/basic/genindex-single.html b/sphinx/themes/basic/genindex-single.html index bbdbfd0d0..1f61fa0f5 100644 --- a/sphinx/themes/basic/genindex-single.html +++ b/sphinx/themes/basic/genindex-single.html @@ -4,7 +4,7 @@ Template for a "single" page of a split index. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {% macro indexentries(firstname, links) %} diff --git a/sphinx/themes/basic/genindex-split.html b/sphinx/themes/basic/genindex-split.html index 12887c10e..42a7a4be3 100644 --- a/sphinx/themes/basic/genindex-split.html +++ b/sphinx/themes/basic/genindex-split.html @@ -4,7 +4,7 @@ Template for a "split" index overview page. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- extends "layout.html" %} diff --git a/sphinx/themes/basic/genindex.html b/sphinx/themes/basic/genindex.html index fd96ba642..c852f25e8 100644 --- a/sphinx/themes/basic/genindex.html +++ b/sphinx/themes/basic/genindex.html @@ -4,7 +4,7 @@ Template for an "all-in-one" index. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {% macro indexentries(firstname, links) %} diff --git a/sphinx/themes/basic/globaltoc.html b/sphinx/themes/basic/globaltoc.html index 3b3a9201a..dc6fea373 100644 --- a/sphinx/themes/basic/globaltoc.html +++ b/sphinx/themes/basic/globaltoc.html @@ -4,7 +4,7 @@ Sphinx sidebar template: global table of contents. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #}

{{ _('Table Of Contents') }}

diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html index bae7db7b5..cb89921fd 100644 --- a/sphinx/themes/basic/layout.html +++ b/sphinx/themes/basic/layout.html @@ -4,7 +4,7 @@ Master layout template for Sphinx themes. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- block doctype -%}{%- if html5_doctype %} diff --git a/sphinx/themes/basic/localtoc.html b/sphinx/themes/basic/localtoc.html index ca1a73ac0..5d3c7f4fd 100644 --- a/sphinx/themes/basic/localtoc.html +++ b/sphinx/themes/basic/localtoc.html @@ -4,7 +4,7 @@ Sphinx sidebar template: local table of contents. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- if display_toc %} diff --git a/sphinx/themes/basic/page.html b/sphinx/themes/basic/page.html index e96f667ba..d2f0bd3f3 100644 --- a/sphinx/themes/basic/page.html +++ b/sphinx/themes/basic/page.html @@ -4,7 +4,7 @@ Master template for simple pages. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- extends "layout.html" %} diff --git a/sphinx/themes/basic/relations.html b/sphinx/themes/basic/relations.html index d7fb6f0a4..7c0f4e711 100644 --- a/sphinx/themes/basic/relations.html +++ b/sphinx/themes/basic/relations.html @@ -4,7 +4,7 @@ Sphinx sidebar template: relation links. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- if prev %} diff --git a/sphinx/themes/basic/search.html b/sphinx/themes/basic/search.html index ce8fa8924..32432a1e3 100644 --- a/sphinx/themes/basic/search.html +++ b/sphinx/themes/basic/search.html @@ -4,7 +4,7 @@ Template for the search page. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- extends "layout.html" %} diff --git a/sphinx/themes/basic/searchbox.html b/sphinx/themes/basic/searchbox.html index 17d84a02b..a8ea03cc8 100644 --- a/sphinx/themes/basic/searchbox.html +++ b/sphinx/themes/basic/searchbox.html @@ -4,7 +4,7 @@ Sphinx sidebar template: quick search box. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- if pagename != "search" and builder != "singlehtml" %} diff --git a/sphinx/themes/basic/searchresults.html b/sphinx/themes/basic/searchresults.html index e04ec15d6..1371bf93c 100644 --- a/sphinx/themes/basic/searchresults.html +++ b/sphinx/themes/basic/searchresults.html @@ -4,7 +4,7 @@ Template for the body of the search results page. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #}

{{ _('Search') }}

diff --git a/sphinx/themes/basic/sourcelink.html b/sphinx/themes/basic/sourcelink.html index 3d4f76ddb..ecde6d3c5 100644 --- a/sphinx/themes/basic/sourcelink.html +++ b/sphinx/themes/basic/sourcelink.html @@ -4,7 +4,7 @@ Sphinx sidebar template: "show source" link. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- if show_source and has_source and sourcename %} diff --git a/sphinx/themes/basic/static/basic.css_t b/sphinx/themes/basic/static/basic.css_t index d16c760cb..745864e28 100644 --- a/sphinx/themes/basic/static/basic.css_t +++ b/sphinx/themes/basic/static/basic.css_t @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- basic theme. * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/basic/static/doctools.js_t b/sphinx/themes/basic/static/doctools.js_t index 326856cfc..b261a44f3 100644 --- a/sphinx/themes/basic/static/doctools.js_t +++ b/sphinx/themes/basic/static/doctools.js_t @@ -4,7 +4,7 @@ * * Sphinx JavaScript utilities for all documentation. * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/basic/static/searchtools.js_t b/sphinx/themes/basic/static/searchtools.js_t index 306fdf55f..e707bb1ea 100644 --- a/sphinx/themes/basic/static/searchtools.js_t +++ b/sphinx/themes/basic/static/searchtools.js_t @@ -4,7 +4,7 @@ * * Sphinx JavaScript utilities for the full-text search. * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/basic/static/websupport.js b/sphinx/themes/basic/static/websupport.js index 53f6a4525..79b18e389 100644 --- a/sphinx/themes/basic/static/websupport.js +++ b/sphinx/themes/basic/static/websupport.js @@ -4,7 +4,7 @@ * * sphinx.websupport utilities for all documentation. * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/classic/layout.html b/sphinx/themes/classic/layout.html index 50b6dc9e0..19f3d0279 100644 --- a/sphinx/themes/classic/layout.html +++ b/sphinx/themes/classic/layout.html @@ -4,7 +4,7 @@ Sphinx layout template for the classic theme. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- extends "basic/layout.html" %} diff --git a/sphinx/themes/classic/static/classic.css_t b/sphinx/themes/classic/static/classic.css_t index 25e1c0261..a84ef8696 100644 --- a/sphinx/themes/classic/static/classic.css_t +++ b/sphinx/themes/classic/static/classic.css_t @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- classic theme. * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/classic/static/sidebar.js_t b/sphinx/themes/classic/static/sidebar.js_t index 494df24f9..ce8361d9b 100644 --- a/sphinx/themes/classic/static/sidebar.js_t +++ b/sphinx/themes/classic/static/sidebar.js_t @@ -16,7 +16,7 @@ * Once the browser is closed the cookie is deleted and the position * reset to the default (expanded). * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/epub/epub-cover.html b/sphinx/themes/epub/epub-cover.html index 763be11ff..436c36aa0 100644 --- a/sphinx/themes/epub/epub-cover.html +++ b/sphinx/themes/epub/epub-cover.html @@ -4,7 +4,7 @@ Sample template for the html cover page. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- extends "layout.html" %} diff --git a/sphinx/themes/epub/layout.html b/sphinx/themes/epub/layout.html index f27e4daa1..84d4bf31c 100644 --- a/sphinx/themes/epub/layout.html +++ b/sphinx/themes/epub/layout.html @@ -4,7 +4,7 @@ Sphinx layout template for the epub theme. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- extends "basic/layout.html" %} diff --git a/sphinx/themes/epub/static/epub.css_t b/sphinx/themes/epub/static/epub.css_t index f8ef61e7c..0e8808f4a 100644 --- a/sphinx/themes/epub/static/epub.css_t +++ b/sphinx/themes/epub/static/epub.css_t @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- epub theme. * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/haiku/layout.html b/sphinx/themes/haiku/layout.html index a6e42d2d2..c93c52dbd 100644 --- a/sphinx/themes/haiku/layout.html +++ b/sphinx/themes/haiku/layout.html @@ -4,7 +4,7 @@ Sphinx layout template for the haiku theme. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- extends "basic/layout.html" %} diff --git a/sphinx/themes/haiku/static/haiku.css_t b/sphinx/themes/haiku/static/haiku.css_t index cb4a2fb62..16d49fea4 100644 --- a/sphinx/themes/haiku/static/haiku.css_t +++ b/sphinx/themes/haiku/static/haiku.css_t @@ -16,7 +16,7 @@ * Braden Ewing * Humdinger * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/nature/static/nature.css_t b/sphinx/themes/nature/static/nature.css_t index bb0c83bac..5751bf940 100644 --- a/sphinx/themes/nature/static/nature.css_t +++ b/sphinx/themes/nature/static/nature.css_t @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- nature theme. * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/nonav/layout.html b/sphinx/themes/nonav/layout.html index 4d79446c4..5e79b2a7a 100644 --- a/sphinx/themes/nonav/layout.html +++ b/sphinx/themes/nonav/layout.html @@ -4,7 +4,7 @@ Sphinx layout template for the any help system theme. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- extends "basic/layout.html" %} diff --git a/sphinx/themes/nonav/static/nonav.css b/sphinx/themes/nonav/static/nonav.css index 554b4b912..b41bd2044 100644 --- a/sphinx/themes/nonav/static/nonav.css +++ b/sphinx/themes/nonav/static/nonav.css @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- nonav theme. * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/pyramid/static/epub.css b/sphinx/themes/pyramid/static/epub.css index a0cffc066..0df0eaeeb 100644 --- a/sphinx/themes/pyramid/static/epub.css +++ b/sphinx/themes/pyramid/static/epub.css @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- default theme. * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/pyramid/static/pyramid.css_t b/sphinx/themes/pyramid/static/pyramid.css_t index ca36ef6ac..93799111e 100644 --- a/sphinx/themes/pyramid/static/pyramid.css_t +++ b/sphinx/themes/pyramid/static/pyramid.css_t @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- pylons theme. * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/scrolls/layout.html b/sphinx/themes/scrolls/layout.html index 893ae17d3..9ebe3b35d 100644 --- a/sphinx/themes/scrolls/layout.html +++ b/sphinx/themes/scrolls/layout.html @@ -5,7 +5,7 @@ Sphinx layout template for the scrolls theme, originally written by Armin Ronacher. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- extends "basic/layout.html" %} diff --git a/sphinx/themes/scrolls/static/scrolls.css_t b/sphinx/themes/scrolls/static/scrolls.css_t index 996a6d22a..3edd869af 100644 --- a/sphinx/themes/scrolls/static/scrolls.css_t +++ b/sphinx/themes/scrolls/static/scrolls.css_t @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- scrolls theme. * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/sphinxdoc/layout.html b/sphinx/themes/sphinxdoc/layout.html index b37567bf8..91349c970 100644 --- a/sphinx/themes/sphinxdoc/layout.html +++ b/sphinx/themes/sphinxdoc/layout.html @@ -4,7 +4,7 @@ Sphinx layout template for the sphinxdoc theme. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. #} {%- extends "basic/layout.html" %} diff --git a/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t b/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t index 3b88e888e..2f4275a6c 100644 --- a/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t +++ b/sphinx/themes/sphinxdoc/static/sphinxdoc.css_t @@ -5,7 +5,7 @@ * Sphinx stylesheet -- sphinxdoc theme. Originally created by * Armin Ronacher for Werkzeug. * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/themes/traditional/static/traditional.css_t b/sphinx/themes/traditional/static/traditional.css_t index fb0ab54c9..e5fda3bab 100644 --- a/sphinx/themes/traditional/static/traditional.css_t +++ b/sphinx/themes/traditional/static/traditional.css_t @@ -4,7 +4,7 @@ * * Sphinx stylesheet -- traditional docs.python.org theme. * - * :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + * :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ diff --git a/sphinx/theming.py b/sphinx/theming.py index f787e8120..64cd67126 100644 --- a/sphinx/theming.py +++ b/sphinx/theming.py @@ -5,7 +5,7 @@ Theming support for HTML builders. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/transforms/__init__.py b/sphinx/transforms/__init__.py index c5fe7864e..acfff6a4d 100644 --- a/sphinx/transforms/__init__.py +++ b/sphinx/transforms/__init__.py @@ -5,7 +5,7 @@ Docutils transforms used by Sphinx when reading documents. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/transforms/compact_bullet_list.py b/sphinx/transforms/compact_bullet_list.py index 8c930c8bc..0121dd12f 100644 --- a/sphinx/transforms/compact_bullet_list.py +++ b/sphinx/transforms/compact_bullet_list.py @@ -5,7 +5,7 @@ Docutils transforms used by Sphinx when reading documents. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/transforms/i18n.py b/sphinx/transforms/i18n.py index 4c1fbc2a7..12f143302 100644 --- a/sphinx/transforms/i18n.py +++ b/sphinx/transforms/i18n.py @@ -5,7 +5,7 @@ Docutils transforms used by Sphinx when reading documents. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/transforms/post_transforms/__init__.py b/sphinx/transforms/post_transforms/__init__.py index 4c4e094d1..42e7307be 100644 --- a/sphinx/transforms/post_transforms/__init__.py +++ b/sphinx/transforms/post_transforms/__init__.py @@ -5,7 +5,7 @@ Docutils transforms used by Sphinx. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/transforms/post_transforms/images.py b/sphinx/transforms/post_transforms/images.py index df207f8ad..bffba8516 100644 --- a/sphinx/transforms/post_transforms/images.py +++ b/sphinx/transforms/post_transforms/images.py @@ -5,7 +5,7 @@ Docutils transforms used by Sphinx. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/__init__.py b/sphinx/util/__init__.py index 55fb9fcc1..4201c9462 100644 --- a/sphinx/util/__init__.py +++ b/sphinx/util/__init__.py @@ -5,7 +5,7 @@ Utility functions for Sphinx. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import absolute_import diff --git a/sphinx/util/compat.py b/sphinx/util/compat.py index 988d41744..402e4bf9f 100644 --- a/sphinx/util/compat.py +++ b/sphinx/util/compat.py @@ -5,7 +5,7 @@ Stuff for docutils compatibility. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import absolute_import diff --git a/sphinx/util/console.py b/sphinx/util/console.py index 63a619f55..8069dd9c9 100644 --- a/sphinx/util/console.py +++ b/sphinx/util/console.py @@ -5,7 +5,7 @@ Format colored console output. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/docfields.py b/sphinx/util/docfields.py index 4bce071c0..2f952d7cc 100644 --- a/sphinx/util/docfields.py +++ b/sphinx/util/docfields.py @@ -6,7 +6,7 @@ "Doc fields" are reST field lists in object descriptions that will be domain-specifically transformed to a more appealing presentation. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import absolute_import diff --git a/sphinx/util/docstrings.py b/sphinx/util/docstrings.py index c2ef91a66..bc4b96a56 100644 --- a/sphinx/util/docstrings.py +++ b/sphinx/util/docstrings.py @@ -5,7 +5,7 @@ Utilities for docstring processing. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index 92e6c8c22..bbf32da1d 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -5,7 +5,7 @@ Utility functions for docutils. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import absolute_import diff --git a/sphinx/util/fileutil.py b/sphinx/util/fileutil.py index fe98117d2..3fd570273 100644 --- a/sphinx/util/fileutil.py +++ b/sphinx/util/fileutil.py @@ -5,7 +5,7 @@ File utility functions for Sphinx. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import absolute_import diff --git a/sphinx/util/i18n.py b/sphinx/util/i18n.py index 09b53b4a0..75a8506fa 100644 --- a/sphinx/util/i18n.py +++ b/sphinx/util/i18n.py @@ -5,7 +5,7 @@ Builder superclass for all builders. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import gettext diff --git a/sphinx/util/images.py b/sphinx/util/images.py index 1c2b4033a..46187775d 100644 --- a/sphinx/util/images.py +++ b/sphinx/util/images.py @@ -5,7 +5,7 @@ Image utility functions for Sphinx. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import absolute_import diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index f29cd9a78..704225359 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -5,7 +5,7 @@ Helpers for inspecting Python modules. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/inventory.py b/sphinx/util/inventory.py index 40c0dc648..837188b5a 100644 --- a/sphinx/util/inventory.py +++ b/sphinx/util/inventory.py @@ -5,7 +5,7 @@ Inventory utility functions for Sphinx. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import re diff --git a/sphinx/util/jsdump.py b/sphinx/util/jsdump.py index 73aa2ce03..6776691cf 100644 --- a/sphinx/util/jsdump.py +++ b/sphinx/util/jsdump.py @@ -6,7 +6,7 @@ This module implements a simple JavaScript serializer. Uses the basestring encode function from simplejson by Bob Ippolito. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/jsonimpl.py b/sphinx/util/jsonimpl.py index 09c04dc6a..fbaa72978 100644 --- a/sphinx/util/jsonimpl.py +++ b/sphinx/util/jsonimpl.py @@ -5,7 +5,7 @@ JSON serializer implementation wrapper. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/logging.py b/sphinx/util/logging.py index 00c12ec4f..ec81f02d7 100644 --- a/sphinx/util/logging.py +++ b/sphinx/util/logging.py @@ -5,7 +5,7 @@ Logging utility functions for Sphinx. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import absolute_import diff --git a/sphinx/util/matching.py b/sphinx/util/matching.py index 401f5f002..bddf84f5c 100644 --- a/sphinx/util/matching.py +++ b/sphinx/util/matching.py @@ -5,7 +5,7 @@ Pattern-matching utility functions for Sphinx. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/nodes.py b/sphinx/util/nodes.py index 5d9ac78c6..97e5b7f30 100644 --- a/sphinx/util/nodes.py +++ b/sphinx/util/nodes.py @@ -5,7 +5,7 @@ Docutils node-related utility functions for Sphinx. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import absolute_import diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py index a8bff11c4..b38e58e5d 100644 --- a/sphinx/util/osutil.py +++ b/sphinx/util/osutil.py @@ -5,7 +5,7 @@ Operating system-related utility functions for Sphinx. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/util/parallel.py b/sphinx/util/parallel.py index 9bc3c36e1..6340e4dfc 100644 --- a/sphinx/util/parallel.py +++ b/sphinx/util/parallel.py @@ -5,7 +5,7 @@ Parallel building utilities. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/png.py b/sphinx/util/png.py index cc4447e4e..d22839fbf 100644 --- a/sphinx/util/png.py +++ b/sphinx/util/png.py @@ -5,7 +5,7 @@ PNG image manipulation helpers. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/pycompat.py b/sphinx/util/pycompat.py index 7f7ee4e9b..e1a2bad9a 100644 --- a/sphinx/util/pycompat.py +++ b/sphinx/util/pycompat.py @@ -5,7 +5,7 @@ Stuff for Python version compatibility. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/requests.py b/sphinx/util/requests.py index 3dc1a30b2..9dee6e694 100644 --- a/sphinx/util/requests.py +++ b/sphinx/util/requests.py @@ -5,7 +5,7 @@ Simple requests package loader - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/rst.py b/sphinx/util/rst.py index 8186130cf..efc1ca76d 100644 --- a/sphinx/util/rst.py +++ b/sphinx/util/rst.py @@ -5,7 +5,7 @@ reST helper functions. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/stemmer/__init__.py b/sphinx/util/stemmer/__init__.py index 6f17d6cdf..8cefee6d2 100644 --- a/sphinx/util/stemmer/__init__.py +++ b/sphinx/util/stemmer/__init__.py @@ -5,7 +5,7 @@ Word stemming utilities for Sphinx. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/tags.py b/sphinx/util/tags.py index 24f64bece..2c4855e91 100644 --- a/sphinx/util/tags.py +++ b/sphinx/util/tags.py @@ -3,7 +3,7 @@ sphinx.util.tags ~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/template.py b/sphinx/util/template.py index 87e81d823..a78871349 100644 --- a/sphinx/util/template.py +++ b/sphinx/util/template.py @@ -5,7 +5,7 @@ Templates utility functions for Sphinx. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/texescape.py b/sphinx/util/texescape.py index 07f5390c4..8d37e0f60 100644 --- a/sphinx/util/texescape.py +++ b/sphinx/util/texescape.py @@ -5,7 +5,7 @@ TeX escaping helper. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py index d30cc230a..793504b77 100644 --- a/sphinx/util/typing.py +++ b/sphinx/util/typing.py @@ -5,7 +5,7 @@ The composit types for Sphinx. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/util/websupport.py b/sphinx/util/websupport.py index 4d91cb77c..59133b9e1 100644 --- a/sphinx/util/websupport.py +++ b/sphinx/util/websupport.py @@ -3,7 +3,7 @@ sphinx.util.websupport ~~~~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/versioning.py b/sphinx/versioning.py index 97a013135..d911085c3 100644 --- a/sphinx/versioning.py +++ b/sphinx/versioning.py @@ -6,7 +6,7 @@ Implements the low-level algorithms Sphinx uses for the versioning of doctrees. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from uuid import uuid4 diff --git a/sphinx/websupport/__init__.py b/sphinx/websupport/__init__.py index 528343f8c..51d906fa6 100644 --- a/sphinx/websupport/__init__.py +++ b/sphinx/websupport/__init__.py @@ -5,7 +5,7 @@ Base Module for web support functions. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/websupport/errors.py b/sphinx/websupport/errors.py index 587d7e7e7..7456659ec 100644 --- a/sphinx/websupport/errors.py +++ b/sphinx/websupport/errors.py @@ -5,7 +5,7 @@ Contains Error classes for the web support package. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/websupport/search/__init__.py b/sphinx/websupport/search/__init__.py index 0f90e009b..e1e871ba0 100644 --- a/sphinx/websupport/search/__init__.py +++ b/sphinx/websupport/search/__init__.py @@ -5,7 +5,7 @@ Server side search support for the web support package. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/websupport/search/nullsearch.py b/sphinx/websupport/search/nullsearch.py index afae1ca57..422b398c9 100644 --- a/sphinx/websupport/search/nullsearch.py +++ b/sphinx/websupport/search/nullsearch.py @@ -5,7 +5,7 @@ The default search adapter, does nothing. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/websupport/search/whooshsearch.py b/sphinx/websupport/search/whooshsearch.py index f007c3cdc..94cce8ed7 100644 --- a/sphinx/websupport/search/whooshsearch.py +++ b/sphinx/websupport/search/whooshsearch.py @@ -5,7 +5,7 @@ Whoosh search adapter. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/websupport/search/xapiansearch.py b/sphinx/websupport/search/xapiansearch.py index 23be038e5..4df4769e2 100644 --- a/sphinx/websupport/search/xapiansearch.py +++ b/sphinx/websupport/search/xapiansearch.py @@ -5,7 +5,7 @@ Xapian search adapter. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/websupport/storage/__init__.py b/sphinx/websupport/storage/__init__.py index adfdec4a5..727e86da4 100644 --- a/sphinx/websupport/storage/__init__.py +++ b/sphinx/websupport/storage/__init__.py @@ -5,7 +5,7 @@ Storage for the websupport package. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/websupport/storage/differ.py b/sphinx/websupport/storage/differ.py index 449d038da..1358d8645 100644 --- a/sphinx/websupport/storage/differ.py +++ b/sphinx/websupport/storage/differ.py @@ -5,7 +5,7 @@ A differ for creating an HTML representations of proposal diffs - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/websupport/storage/sqlalchemy_db.py b/sphinx/websupport/storage/sqlalchemy_db.py index a2dfc35b9..e1c86dd9d 100644 --- a/sphinx/websupport/storage/sqlalchemy_db.py +++ b/sphinx/websupport/storage/sqlalchemy_db.py @@ -6,7 +6,7 @@ SQLAlchemy table and mapper definitions used by the :class:`sphinx.websupport.storage.sqlalchemystorage.SQLAlchemyStorage`. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/websupport/storage/sqlalchemystorage.py b/sphinx/websupport/storage/sqlalchemystorage.py index dc5e9400b..b018ea0a3 100644 --- a/sphinx/websupport/storage/sqlalchemystorage.py +++ b/sphinx/websupport/storage/sqlalchemystorage.py @@ -5,7 +5,7 @@ An SQLAlchemy storage backend. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/writers/__init__.py b/sphinx/writers/__init__.py index 6b157a83a..79eacbbfb 100644 --- a/sphinx/writers/__init__.py +++ b/sphinx/writers/__init__.py @@ -5,6 +5,6 @@ Custom docutils writers. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py index 8d02793e3..30631f560 100644 --- a/sphinx/writers/html.py +++ b/sphinx/writers/html.py @@ -5,7 +5,7 @@ docutils writers handling Sphinx' custom nodes. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py index 51c4e8ecb..533235f62 100644 --- a/sphinx/writers/html5.py +++ b/sphinx/writers/html5.py @@ -5,7 +5,7 @@ Experimental docutils writers for HTML5 handling Sphinx' custom nodes. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 39c7bc81e..98fec811c 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -8,7 +8,7 @@ Much of this code is adapted from Dave Kuhlman's "docpy" writer from his docutils sandbox. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/writers/manpage.py b/sphinx/writers/manpage.py index 71c2aac0b..1d645ce5f 100644 --- a/sphinx/writers/manpage.py +++ b/sphinx/writers/manpage.py @@ -5,7 +5,7 @@ Manual page writer, extended for Sphinx custom nodes. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/writers/texinfo.py b/sphinx/writers/texinfo.py index d7e08510e..b73557f86 100644 --- a/sphinx/writers/texinfo.py +++ b/sphinx/writers/texinfo.py @@ -5,7 +5,7 @@ Custom docutils writer for Texinfo. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/writers/text.py b/sphinx/writers/text.py index d2b2f9045..b6e3f4cec 100644 --- a/sphinx/writers/text.py +++ b/sphinx/writers/text.py @@ -5,7 +5,7 @@ Custom docutils writer for plain text. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import os diff --git a/sphinx/writers/websupport.py b/sphinx/writers/websupport.py index 1e7f4babd..a962faf4d 100644 --- a/sphinx/writers/websupport.py +++ b/sphinx/writers/websupport.py @@ -5,7 +5,7 @@ sphinx.websupport writer that adds comment-related annotations. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/writers/xml.py b/sphinx/writers/xml.py index 9cb64216a..f94fe847c 100644 --- a/sphinx/writers/xml.py +++ b/sphinx/writers/xml.py @@ -5,7 +5,7 @@ Docutils-native XML and pseudo-XML writers. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/conftest.py b/tests/conftest.py index 28dbd6ed4..4de67c7d6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -3,7 +3,7 @@ pytest config for sphinx/tests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/py35/test_autodoc_py35.py b/tests/py35/test_autodoc_py35.py index 481374948..ecb0a96af 100644 --- a/tests/py35/test_autodoc_py35.py +++ b/tests/py35/test_autodoc_py35.py @@ -6,7 +6,7 @@ Test the autodoc extension. This tests mainly the Documenters; the auto directives are tested in a test source file translated by test_build. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/run.py b/tests/run.py index a8439ba02..f84926fb6 100755 --- a/tests/run.py +++ b/tests/run.py @@ -6,7 +6,7 @@ This script runs the Sphinx unit test suite. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/tests/test_api_translator.py b/tests/test_api_translator.py index 35b24732b..4e4230ba3 100644 --- a/tests/test_api_translator.py +++ b/tests/test_api_translator.py @@ -5,7 +5,7 @@ Test the Sphinx API for translator. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_apidoc.py b/tests/test_apidoc.py index 20582e9fc..fd0049c8f 100644 --- a/tests/test_apidoc.py +++ b/tests/test_apidoc.py @@ -5,7 +5,7 @@ Test the sphinx.apidoc module. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_application.py b/tests/test_application.py index 785a78878..8535cc9dc 100644 --- a/tests/test_application.py +++ b/tests/test_application.py @@ -5,7 +5,7 @@ Test the Sphinx class. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from docutils import nodes diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index 6eb087567..462f65698 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -6,7 +6,7 @@ Test the autodoc extension. This tests mainly the Documenters; the auto directives are tested in a test source file translated by test_build. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_build.py b/tests/test_build.py index c61fbb5c2..6533a1763 100644 --- a/tests/test_build.py +++ b/tests/test_build.py @@ -5,7 +5,7 @@ Test all builders. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_build_applehelp.py b/tests/test_build_applehelp.py index 4418cb265..31d4ca4df 100644 --- a/tests/test_build_applehelp.py +++ b/tests/test_build_applehelp.py @@ -7,7 +7,7 @@ test the HTML itself; that's already handled by :file:`test_build_html.py`. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_build_gettext.py b/tests/test_build_gettext.py index f256140fe..c14013f9a 100644 --- a/tests/test_build_gettext.py +++ b/tests/test_build_gettext.py @@ -5,7 +5,7 @@ Test the build process with gettext builder with the test root. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 0ccd4da01..6fc024d35 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -5,7 +5,7 @@ Test the HTML builder and check output against XPath. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_build_html5.py b/tests/test_build_html5.py index 4ad282973..217050ec7 100644 --- a/tests/test_build_html5.py +++ b/tests/test_build_html5.py @@ -10,7 +10,7 @@ https://github.com/sphinx-doc/sphinx/pull/2805/files - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index faa2f46a7..0c95a0cdb 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -5,7 +5,7 @@ Test the build process with LaTeX builder with the test root. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/tests/test_build_linkcheck.py b/tests/test_build_linkcheck.py index cc3d6e24f..839a15628 100644 --- a/tests/test_build_linkcheck.py +++ b/tests/test_build_linkcheck.py @@ -5,7 +5,7 @@ Test the build process with manpage builder with the test root. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/tests/test_build_manpage.py b/tests/test_build_manpage.py index 953332c73..3448d6eeb 100644 --- a/tests/test_build_manpage.py +++ b/tests/test_build_manpage.py @@ -5,7 +5,7 @@ Test the build process with manpage builder with the test root. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/tests/test_build_texinfo.py b/tests/test_build_texinfo.py index 14c6028bc..50f42542d 100644 --- a/tests/test_build_texinfo.py +++ b/tests/test_build_texinfo.py @@ -5,7 +5,7 @@ Test the build process with Texinfo builder with the test root. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/tests/test_build_text.py b/tests/test_build_text.py index 1732b3187..382e62b34 100644 --- a/tests/test_build_text.py +++ b/tests/test_build_text.py @@ -5,7 +5,7 @@ Test the build process with Text builder with the test root. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_catalogs.py b/tests/test_catalogs.py index b3e17a0a1..4bfbb18a3 100644 --- a/tests/test_catalogs.py +++ b/tests/test_catalogs.py @@ -5,7 +5,7 @@ Test the base build process. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import shutil diff --git a/tests/test_config.py b/tests/test_config.py index f9300c30e..965f46c3e 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -6,7 +6,7 @@ Test the sphinx.config.Config class and its handling in the Application class. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from six import PY3, iteritems diff --git a/tests/test_correct_year.py b/tests/test_correct_year.py index a8058f08c..e7501bb6a 100644 --- a/tests/test_correct_year.py +++ b/tests/test_correct_year.py @@ -5,7 +5,7 @@ Test copyright year adjustment - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import pytest diff --git a/tests/test_directive_code.py b/tests/test_directive_code.py index e3069061b..f62f44f13 100644 --- a/tests/test_directive_code.py +++ b/tests/test_directive_code.py @@ -5,7 +5,7 @@ Test the code-block directive. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_directive_only.py b/tests/test_directive_only.py index d70585774..79544975b 100644 --- a/tests/test_directive_only.py +++ b/tests/test_directive_only.py @@ -5,7 +5,7 @@ Test the only directive with the test root. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_docutilsconf.py b/tests/test_docutilsconf.py index 572660d69..d2b56d30d 100644 --- a/tests/test_docutilsconf.py +++ b/tests/test_docutilsconf.py @@ -5,7 +5,7 @@ Test docutils.conf support for several writers. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_domain_cpp.py b/tests/test_domain_cpp.py index 2932f356f..7437b4c05 100644 --- a/tests/test_domain_cpp.py +++ b/tests/test_domain_cpp.py @@ -5,7 +5,7 @@ Tests the C++ Domain - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_domain_js.py b/tests/test_domain_js.py index 22faf4458..a609dcefe 100644 --- a/tests/test_domain_js.py +++ b/tests/test_domain_js.py @@ -5,7 +5,7 @@ Tests the JavaScript Domain - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_domain_py.py b/tests/test_domain_py.py index 5596950df..b917540d8 100644 --- a/tests/test_domain_py.py +++ b/tests/test_domain_py.py @@ -5,7 +5,7 @@ Tests the Python Domain - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_domain_rst.py b/tests/test_domain_rst.py index 1e55e92a1..8cfe7e284 100644 --- a/tests/test_domain_rst.py +++ b/tests/test_domain_rst.py @@ -5,7 +5,7 @@ Tests the reStructuredText domain. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_domain_std.py b/tests/test_domain_std.py index edd5a0ebf..06573fa38 100644 --- a/tests/test_domain_std.py +++ b/tests/test_domain_std.py @@ -5,7 +5,7 @@ Tests the std domain - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_environment.py b/tests/test_environment.py index 611d34577..adc1e306b 100644 --- a/tests/test_environment.py +++ b/tests/test_environment.py @@ -5,7 +5,7 @@ Test the BuildEnvironment class. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import pytest diff --git a/tests/test_environment_indexentries.py b/tests/test_environment_indexentries.py index b9de151cc..03e4d9662 100644 --- a/tests/test_environment_indexentries.py +++ b/tests/test_environment_indexentries.py @@ -5,7 +5,7 @@ Test the sphinx.environment.managers.indexentries. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_environment_toctree.py b/tests/test_environment_toctree.py index f7a24d1fc..26334858b 100644 --- a/tests/test_environment_toctree.py +++ b/tests/test_environment_toctree.py @@ -5,7 +5,7 @@ Test the sphinx.environment.managers.toctree. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py index 1c1ebf7a0..e7057df0f 100644 --- a/tests/test_ext_autodoc.py +++ b/tests/test_ext_autodoc.py @@ -5,7 +5,7 @@ Test the autodoc extension. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_autosectionlabel.py b/tests/test_ext_autosectionlabel.py index 4726a2378..1266edbc3 100644 --- a/tests/test_ext_autosectionlabel.py +++ b/tests/test_ext_autosectionlabel.py @@ -5,7 +5,7 @@ Test sphinx.ext.autosectionlabel extension. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_autosummary.py b/tests/test_ext_autosummary.py index 81fd35762..a4cd9e03b 100644 --- a/tests/test_ext_autosummary.py +++ b/tests/test_ext_autosummary.py @@ -5,7 +5,7 @@ Test the autosummary extension. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_coverage.py b/tests/test_ext_coverage.py index ff3fb4c02..d1b4b55c4 100644 --- a/tests/test_ext_coverage.py +++ b/tests/test_ext_coverage.py @@ -5,7 +5,7 @@ Test the coverage builder. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_doctest.py b/tests/test_ext_doctest.py index fa3ad6bc4..020357879 100644 --- a/tests/test_ext_doctest.py +++ b/tests/test_ext_doctest.py @@ -5,7 +5,7 @@ Test the doctest extension. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import pytest diff --git a/tests/test_ext_githubpages.py b/tests/test_ext_githubpages.py index 56ce7b775..18ee51480 100644 --- a/tests/test_ext_githubpages.py +++ b/tests/test_ext_githubpages.py @@ -5,7 +5,7 @@ Test sphinx.ext.githubpages extension. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_graphviz.py b/tests/test_ext_graphviz.py index 1d2a3ab2f..e59b697be 100644 --- a/tests/test_ext_graphviz.py +++ b/tests/test_ext_graphviz.py @@ -5,7 +5,7 @@ Test sphinx.ext.graphviz extension. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_ifconfig.py b/tests/test_ext_ifconfig.py index 5c59caaaf..b4c941512 100644 --- a/tests/test_ext_ifconfig.py +++ b/tests/test_ext_ifconfig.py @@ -5,7 +5,7 @@ Test sphinx.ext.ifconfig extension. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_imgconverter.py b/tests/test_ext_imgconverter.py index cc84001df..8f610377c 100644 --- a/tests/test_ext_imgconverter.py +++ b/tests/test_ext_imgconverter.py @@ -5,7 +5,7 @@ Test sphinx.ext.imgconverter extension. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_inheritance_diagram.py b/tests/test_ext_inheritance_diagram.py index 6a2652514..1b168e622 100644 --- a/tests/test_ext_inheritance_diagram.py +++ b/tests/test_ext_inheritance_diagram.py @@ -5,7 +5,7 @@ Test sphinx.ext.inheritance_diagram extension. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_intersphinx.py b/tests/test_ext_intersphinx.py index 96210dc6c..371f296ea 100644 --- a/tests/test_ext_intersphinx.py +++ b/tests/test_ext_intersphinx.py @@ -5,7 +5,7 @@ Test the intersphinx extension. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_math.py b/tests/test_ext_math.py index 552be96f3..2b8a68f9c 100644 --- a/tests/test_ext_math.py +++ b/tests/test_ext_math.py @@ -5,7 +5,7 @@ Test math extensions. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_napoleon.py b/tests/test_ext_napoleon.py index b2ca7fe7a..d8d6adc65 100644 --- a/tests/test_ext_napoleon.py +++ b/tests/test_ext_napoleon.py @@ -6,7 +6,7 @@ Tests for :mod:`sphinx.ext.napoleon.__init__` module. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_napoleon_docstring.py b/tests/test_ext_napoleon_docstring.py index e71d517fe..1865b004c 100644 --- a/tests/test_ext_napoleon_docstring.py +++ b/tests/test_ext_napoleon_docstring.py @@ -6,7 +6,7 @@ Tests for :mod:`sphinx.ext.napoleon.docstring` module. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_napoleon_iterators.py b/tests/test_ext_napoleon_iterators.py index 5258d9b79..bf144275d 100644 --- a/tests/test_ext_napoleon_iterators.py +++ b/tests/test_ext_napoleon_iterators.py @@ -6,7 +6,7 @@ Tests for :mod:`sphinx.ext.napoleon.iterators` module. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_todo.py b/tests/test_ext_todo.py index cee59fe9d..99eb7b801 100644 --- a/tests/test_ext_todo.py +++ b/tests/test_ext_todo.py @@ -5,7 +5,7 @@ Test sphinx.ext.todo extension. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_ext_viewcode.py b/tests/test_ext_viewcode.py index 4dceaa488..3f6612c76 100644 --- a/tests/test_ext_viewcode.py +++ b/tests/test_ext_viewcode.py @@ -5,7 +5,7 @@ Test sphinx.ext.viewcode extension. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_highlighting.py b/tests/test_highlighting.py index 938181fe1..5660869bd 100644 --- a/tests/test_highlighting.py +++ b/tests/test_highlighting.py @@ -5,7 +5,7 @@ Test the Pygments highlighting bridge. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_intl.py b/tests/test_intl.py index 6b72438bd..920def588 100644 --- a/tests/test_intl.py +++ b/tests/test_intl.py @@ -6,7 +6,7 @@ Test message patching for internationalization purposes. Runs the text builder in the test root. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/tests/test_markup.py b/tests/test_markup.py index 9c41845fc..34ab1405d 100644 --- a/tests/test_markup.py +++ b/tests/test_markup.py @@ -5,7 +5,7 @@ Test various Sphinx-specific markup extensions. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 58f573b0a..a00d76f87 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -5,7 +5,7 @@ Test our handling of metadata in files with bibliographic metadata. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py index b95356aaa..a4f12a551 100644 --- a/tests/test_quickstart.py +++ b/tests/test_quickstart.py @@ -5,7 +5,7 @@ Test the sphinx.quickstart module. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_search.py b/tests/test_search.py index f1825dfa4..fc5fb7e04 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -5,7 +5,7 @@ Test the search index builder. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_setup_command.py b/tests/test_setup_command.py index 562b0a715..e1f976b8a 100644 --- a/tests/test_setup_command.py +++ b/tests/test_setup_command.py @@ -5,7 +5,7 @@ Test setup_command for distutils. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_templating.py b/tests/test_templating.py index b0070f06a..341b33f51 100644 --- a/tests/test_templating.py +++ b/tests/test_templating.py @@ -5,7 +5,7 @@ Test templating. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_theming.py b/tests/test_theming.py index 176c9eebc..48a4e1865 100644 --- a/tests/test_theming.py +++ b/tests/test_theming.py @@ -5,7 +5,7 @@ Test the Theme class. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_toctree.py b/tests/test_toctree.py index 18910197f..42ec0ce89 100644 --- a/tests/test_toctree.py +++ b/tests/test_toctree.py @@ -5,7 +5,7 @@ Test the HTML builder and check output against XPath. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import pytest diff --git a/tests/test_util.py b/tests/test_util.py index 84ce44007..d55de7f5c 100644 --- a/tests/test_util.py +++ b/tests/test_util.py @@ -5,7 +5,7 @@ Tests util functions. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_util_fileutil.py b/tests/test_util_fileutil.py index 849ccce22..69f51f52c 100644 --- a/tests/test_util_fileutil.py +++ b/tests/test_util_fileutil.py @@ -5,7 +5,7 @@ Tests sphinx.util.fileutil functions. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from sphinx.util.fileutil import copy_asset, copy_asset_file diff --git a/tests/test_util_i18n.py b/tests/test_util_i18n.py index 53e0e4cf1..bec4e91e9 100644 --- a/tests/test_util_i18n.py +++ b/tests/test_util_i18n.py @@ -5,7 +5,7 @@ Test i18n util. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/tests/test_util_images.py b/tests/test_util_images.py index 6f67dcc82..a9c023b09 100644 --- a/tests/test_util_images.py +++ b/tests/test_util_images.py @@ -5,7 +5,7 @@ Test images util. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/tests/test_util_inspect.py b/tests/test_util_inspect.py index 87b4d5186..a463f4f6a 100644 --- a/tests/test_util_inspect.py +++ b/tests/test_util_inspect.py @@ -5,7 +5,7 @@ Tests util.inspect functions. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from unittest import TestCase diff --git a/tests/test_util_logging.py b/tests/test_util_logging.py index 7ae086872..e909c2dcf 100644 --- a/tests/test_util_logging.py +++ b/tests/test_util_logging.py @@ -5,7 +5,7 @@ Test logging util. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/tests/test_util_matching.py b/tests/test_util_matching.py index 3b84f4735..fc38470d3 100644 --- a/tests/test_util_matching.py +++ b/tests/test_util_matching.py @@ -5,7 +5,7 @@ Tests sphinx.util.matching functions. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from sphinx.util.matching import compile_matchers, Matcher diff --git a/tests/test_util_nodes.py b/tests/test_util_nodes.py index c392c2bc7..c58ecc205 100644 --- a/tests/test_util_nodes.py +++ b/tests/test_util_nodes.py @@ -5,7 +5,7 @@ Tests uti.nodes functions. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from textwrap import dedent diff --git a/tests/test_util_rst.py b/tests/test_util_rst.py index 5fce6e3eb..406ea710e 100644 --- a/tests/test_util_rst.py +++ b/tests/test_util_rst.py @@ -5,7 +5,7 @@ Tests sphinx.util.rst functions. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from sphinx.util.rst import escape diff --git a/tests/test_versioning.py b/tests/test_versioning.py index b73c00fa6..7956b6710 100644 --- a/tests/test_versioning.py +++ b/tests/test_versioning.py @@ -5,7 +5,7 @@ Test the versioning implementation. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_websupport.py b/tests/test_websupport.py index 51cb2b287..10942798c 100644 --- a/tests/test_websupport.py +++ b/tests/test_websupport.py @@ -5,7 +5,7 @@ Test the Web Support Package - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_writer_latex.py b/tests/test_writer_latex.py index b026f8d17..5c73469ec 100644 --- a/tests/test_writer_latex.py +++ b/tests/test_writer_latex.py @@ -5,7 +5,7 @@ Test the LaTeX writer - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/utils/check_sources.py b/utils/check_sources.py index 3895ee1d6..30f1fb93c 100755 --- a/utils/check_sources.py +++ b/utils/check_sources.py @@ -7,7 +7,7 @@ Make sure each Python file has a correct file header including copyright and license information. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/utils/jssplitter_generator.py b/utils/jssplitter_generator.py index 75f0353af..073b7c7ae 100644 --- a/utils/jssplitter_generator.py +++ b/utils/jssplitter_generator.py @@ -122,7 +122,7 @@ python_src = '''# -*- coding: utf-8 -*- DO NOT EDIT. This is generated by utils/jssplitter_generator.py - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ From 5562e76585611928ad8628cb9a40a0eb2b3d87fe Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 1 Jan 2018 01:10:10 +0900 Subject: [PATCH 205/275] A happy new year! --- sphinx/cmd/__init__.py | 2 +- sphinx/cmd/build.py | 2 +- sphinx/cmd/quickstart.py | 2 +- sphinx/ext/apidoc.py | 2 +- sphinx/ext/autodoc/importer.py | 2 +- sphinx/ext/autodoc/inspector.py | 2 +- sphinx/pycode/parser.py | 2 +- tests/test_build_qthelp.py | 2 +- tests/test_io.py | 2 +- utils/checks.py | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sphinx/cmd/__init__.py b/sphinx/cmd/__init__.py index 9ffb9e612..a559306d6 100644 --- a/sphinx/cmd/__init__.py +++ b/sphinx/cmd/__init__.py @@ -5,6 +5,6 @@ Modules for command line executables. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/cmd/build.py b/sphinx/cmd/build.py index 6c9d6e3e9..c0c31ae67 100644 --- a/sphinx/cmd/build.py +++ b/sphinx/cmd/build.py @@ -5,7 +5,7 @@ Build documentation from a provided source. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/cmd/quickstart.py b/sphinx/cmd/quickstart.py index 3051520cb..fd9b15649 100644 --- a/sphinx/cmd/quickstart.py +++ b/sphinx/cmd/quickstart.py @@ -5,7 +5,7 @@ Quickly setup documentation source to work with Sphinx. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ from __future__ import print_function diff --git a/sphinx/ext/apidoc.py b/sphinx/ext/apidoc.py index d99f852f1..f44bc0b85 100644 --- a/sphinx/ext/apidoc.py +++ b/sphinx/ext/apidoc.py @@ -11,7 +11,7 @@ Copyright 2008 Société des arts technologiques (SAT), http://www.sat.qc.ca/ - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py index 5c28f490d..75e045c21 100644 --- a/sphinx/ext/autodoc/importer.py +++ b/sphinx/ext/autodoc/importer.py @@ -5,7 +5,7 @@ Importer utilities for autodoc - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/ext/autodoc/inspector.py b/sphinx/ext/autodoc/inspector.py index 50c5a9082..6e07c9547 100644 --- a/sphinx/ext/autodoc/inspector.py +++ b/sphinx/ext/autodoc/inspector.py @@ -5,7 +5,7 @@ Inspect utilities for autodoc - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/sphinx/pycode/parser.py b/sphinx/pycode/parser.py index 7460dcfce..9aed7f7f4 100644 --- a/sphinx/pycode/parser.py +++ b/sphinx/pycode/parser.py @@ -5,7 +5,7 @@ Utilities parsing and analyzing Python code. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import re diff --git a/tests/test_build_qthelp.py b/tests/test_build_qthelp.py index 3e4815fbe..de676e6e0 100644 --- a/tests/test_build_qthelp.py +++ b/tests/test_build_qthelp.py @@ -7,7 +7,7 @@ test the HTML itself; that's already handled by :file:`test_build_html.py`. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/tests/test_io.py b/tests/test_io.py index ecd4a1009..1c8fee86b 100644 --- a/tests/test_io.py +++ b/tests/test_io.py @@ -5,7 +5,7 @@ Tests io modules. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/utils/checks.py b/utils/checks.py index 03104d78a..90d89439e 100644 --- a/utils/checks.py +++ b/utils/checks.py @@ -5,7 +5,7 @@ Custom, Sphinx-only flake8 plugins. - :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS. + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ From 1d64ade74911c9a9d3178d4f215fe4d75c2eddda Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 18 Jun 2017 00:39:23 +0900 Subject: [PATCH 206/275] Refactor: Add import_object() --- sphinx/ext/autodoc/__init__.py | 58 +++++----------------------------- sphinx/ext/autodoc/importer.py | 52 +++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 51 deletions(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 5c1a71ea9..f9f7c5edc 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -14,9 +14,8 @@ import re import sys import inspect -import traceback -from six import PY2, iterkeys, iteritems, itervalues, text_type, class_types, string_types +from six import iterkeys, iteritems, itervalues, text_type, class_types, string_types from docutils import nodes from docutils.utils import assemble_option_dict @@ -24,7 +23,7 @@ from docutils.parsers.rst import Directive from docutils.statemachine import ViewList import sphinx -from sphinx.ext.autodoc.importer import mock, import_module +from sphinx.ext.autodoc.importer import mock, import_object from sphinx.ext.autodoc.importer import _MockImporter # to keep compatibility # NOQA from sphinx.ext.autodoc.inspector import format_annotation, formatargspec # to keep compatibility # NOQA from sphinx.util import rpartition, force_decode @@ -384,56 +383,15 @@ class Documenter(object): Returns True if successful, False if an error occurred. """ - if self.objpath: - logger.debug('[autodoc] from %s import %s', - self.modname, '.'.join(self.objpath)) - # always enable mock import hook - # it will do nothing if autodoc_mock_imports is empty with mock(self.env.config.autodoc_mock_imports): try: - logger.debug('[autodoc] import %s', self.modname) - obj = import_module(self.modname, self.env.config.autodoc_warningiserror) - parent = None - self.module = obj - logger.debug('[autodoc] => %r', obj) - for part in self.objpath: - parent = obj - logger.debug('[autodoc] getattr(_, %r)', part) - obj = self.get_attr(obj, part) - logger.debug('[autodoc] => %r', obj) - self.object_name = part - self.parent = parent - self.object = obj + ret = import_object(self.modname, self.objpath, self.objtype, + attrgetter=self.get_attr, + warningiserror=self.env.config.autodoc_warningiserror) + self.module, self.parent, self.object_name, self.object = ret return True - except (AttributeError, ImportError) as exc: - if self.objpath: - errmsg = 'autodoc: failed to import %s %r from module %r' % \ - (self.objtype, '.'.join(self.objpath), self.modname) - else: - errmsg = 'autodoc: failed to import %s %r' % \ - (self.objtype, self.fullname) - - if isinstance(exc, ImportError): - # import_module() raises ImportError having real exception obj and - # traceback - real_exc, traceback_msg = exc.args - if isinstance(real_exc, SystemExit): - errmsg += ('; the module executes module level statement ' + - 'and it might call sys.exit().') - elif isinstance(real_exc, ImportError): - errmsg += ('; the following exception was raised:\n%s' % - real_exc.args[0]) - else: - errmsg += ('; the following exception was raised:\n%s' % - traceback_msg) - else: - errmsg += ('; the following exception was raised:\n%s' % - traceback.format_exc()) - - if PY2: - errmsg = errmsg.decode('utf-8') # type: ignore - logger.debug(errmsg) - self.directive.warn(errmsg) + except ImportError as exc: + self.directive.warn(exc.args[0]) self.env.note_reread() return False diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py index 75e045c21..95ca58d0b 100644 --- a/sphinx/ext/autodoc/importer.py +++ b/sphinx/ext/autodoc/importer.py @@ -15,11 +15,14 @@ import traceback import contextlib from types import FunctionType, MethodType, ModuleType +from six import PY2 + from sphinx.util import logging +from sphinx.util.inspect import safe_getattr if False: # For type annotation - from typing import Any, Generator, List, Set # NOQA + from typing import Any, Callable, Generator, List, Set # NOQA logger = logging.getLogger(__name__) @@ -144,3 +147,50 @@ def import_module(modname, warningiserror=False): # Importing modules may cause any side effects, including # SystemExit, so we need to catch all errors. raise ImportError(exc, traceback.format_exc()) + + +def import_object(modname, objpath, objtype='', attrgetter=safe_getattr, warningiserror=False): + # type: (str, List[unicode], str, Callable[[Any, unicode], Any]) -> Any + if objpath: + logger.debug('[autodoc] from %s import %s', modname, '.'.join(objpath)) + else: + logger.debug('[autodoc] import %s', modname) + + try: + module = import_module(modname, warningiserror=warningiserror) + logger.debug('[autodoc] => %r', module) + obj = module + parent = None + object_name = None + for attrname in objpath: + parent = obj + logger.debug('[autodoc] getattr(_, %r)', attrname) + obj = attrgetter(obj, attrname) + logger.debug('[autodoc] => %r', obj) + object_name = attrname + return [module, parent, object_name, obj] + except (AttributeError, ImportError) as exc: + if objpath: + errmsg = ('autodoc: failed to import %s %r from module %r' % + (objtype, '.'.join(objpath), modname)) + else: + errmsg = 'autodoc: failed to import %s %r' % (objtype, modname) + + if isinstance(exc, ImportError): + # import_module() raises ImportError having real exception obj and + # traceback + real_exc, traceback_msg = exc.args + if isinstance(real_exc, SystemExit): + errmsg += ('; the module executes module level statement ' + 'and it might call sys.exit().') + elif isinstance(real_exc, ImportError): + errmsg += '; the following exception was raised:\n%s' % real_exc.args[0] + else: + errmsg += '; the following exception was raised:\n%s' % traceback_msg + else: + errmsg += '; the following exception was raised:\n%s' % traceback.format_exc() + + if PY2: + errmsg = errmsg.decode('utf-8') # type: ignore + logger.debug(errmsg) + raise ImportError(errmsg) From 5d6413b7120cfc6d3d0cc9367cfe8b6f7ee87523 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 18 Jun 2017 10:25:34 +0900 Subject: [PATCH 207/275] Deprecate sphinx.ext.autodoc.add_documenter() and AutoDirective._register --- CHANGES | 2 ++ sphinx/application.py | 6 ++-- sphinx/ext/autodoc/__init__.py | 55 ++++++++++++++++++++++++++---- sphinx/ext/autosummary/__init__.py | 18 +++++----- sphinx/ext/autosummary/generate.py | 38 ++++++++++++--------- sphinx/registry.py | 6 ++++ tests/py35/test_autodoc_py35.py | 8 ++--- tests/test_autodoc.py | 22 ++++++------ tests/test_ext_autosummary.py | 10 ++++-- tests/test_templating.py | 11 ++++-- 10 files changed, 121 insertions(+), 55 deletions(-) diff --git a/CHANGES b/CHANGES index bd6a92728..c0934c396 100644 --- a/CHANGES +++ b/CHANGES @@ -21,6 +21,8 @@ Deprecated values will be accepted at 2.0. * ``format_annotation()`` and ``formatargspec()`` is deprecated. Please use ``sphinx.util.inspect.Signature`` instead. +* ``sphinx.ext.autodoc.add_documenter()`` and ``AutoDirective._register`` is now + deprecated. Please use ``app.add_autodocumenter()`` Features added -------------- diff --git a/sphinx/application.py b/sphinx/application.py index 9195f11af..3bfea910f 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -642,9 +642,9 @@ class Sphinx(object): def add_autodocumenter(self, cls): # type: (Any) -> None logger.debug('[app] adding autodocumenter: %r', cls) - from sphinx.ext import autodoc - autodoc.add_documenter(cls) - self.add_directive('auto' + cls.objtype, autodoc.AutoDirective) + from sphinx.ext.autodoc import AutoDirective + self.add_directive('auto' + cls.objtype, AutoDirective) + self.registry.add_documenter(cls.objtype, cls) def add_autodoc_attrgetter(self, type, getter): # type: (Any, Callable) -> None diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index f9f7c5edc..a6afe4f4c 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -14,6 +14,7 @@ import re import sys import inspect +import warnings from six import iterkeys, iteritems, itervalues, text_type, class_types, string_types @@ -23,6 +24,7 @@ from docutils.parsers.rst import Directive from docutils.statemachine import ViewList import sphinx +from sphinx.deprecation import RemovedInSphinx20Warning from sphinx.ext.autodoc.importer import mock, import_object from sphinx.ext.autodoc.importer import _MockImporter # to keep compatibility # NOQA from sphinx.ext.autodoc.inspector import format_annotation, formatargspec # to keep compatibility # NOQA @@ -323,6 +325,14 @@ class Documenter(object): # the module analyzer to get at attribute docs, or None self.analyzer = None # type: Any + @property + def documenters(self): + # type: () -> Dict[unicode, Type[Documenter]] + """Returns registered Documenter classes""" + classes = dict(AutoDirective._registry) # registered directly + classes.update(self.env.app.registry.documenters) # registered by API + return classes + def add_line(self, line, source, *lineno): # type: (unicode, unicode, int) -> None """Append one line of generated reST to the output.""" @@ -727,7 +737,7 @@ class Documenter(object): # document non-skipped members memberdocumenters = [] # type: List[Tuple[Documenter, bool]] for (mname, member, isattr) in self.filter_members(members, want_all): - classes = [cls for cls in itervalues(AutoDirective._registry) + classes = [cls for cls in itervalues(self.documenters) if cls.can_document_member(member, mname, isattr, self)] if not classes: # don't know how to document this member @@ -1463,11 +1473,28 @@ class InstanceAttributeDocumenter(AttributeDocumenter): AttributeDocumenter.add_content(self, more_content, no_docstring=True) +class DeprecatedDict(dict): + def __init__(self, message): + self.message = message + super(DeprecatedDict, self).__init__() + + def __setitem__(self, key, value): + warnings.warn(self.message, RemovedInSphinx20Warning) + super(DeprecatedDict, self).__setitem__(key, value) + + def setdefault(self, key, default=None): + warnings.warn(self.message, RemovedInSphinx20Warning) + super(DeprecatedDict, self).setdefault(key, default) + + def update(self, other=None): + warnings.warn(self.message, RemovedInSphinx20Warning) + super(DeprecatedDict, self).update(other) + + class AutoDirective(Directive): """ The AutoDirective class is used for all autodoc directives. It dispatches - most of the work to one of the Documenters, which it selects through its - *_registry* dictionary. + most of the work to one of the Documenters. The *_special_attrgetters* attribute is used to customize ``getattr()`` calls that the Documenters make; its entries are of the form ``type: @@ -1478,8 +1505,11 @@ class AutoDirective(Directive): dictionary should include all necessary functions for accessing attributes of the parents. """ - # a registry of objtype -> documenter class - _registry = {} # type: Dict[unicode, Type[Documenter]] + # a registry of objtype -> documenter class (Deprecated) + _registry = DeprecatedDict( + 'AutoDirective._registry has been deprecated. ' + 'Please use app.add_autodocumenter() instead.' + ) # type: Dict[unicode, Type[Documenter]] # a registry of type -> getattr function _special_attrgetters = {} # type: Dict[Type, Callable] @@ -1521,7 +1551,7 @@ class AutoDirective(Directive): # find out what documenter to call objtype = self.name[4:] - doc_class = self._registry[objtype] + doc_class = get_documenters(self.env.app)[objtype] # add default flags for flag in self._default_flags: if flag not in doc_class.option_spec: @@ -1575,6 +1605,10 @@ class AutoDirective(Directive): def add_documenter(cls): # type: (Type[Documenter]) -> None """Register a new Documenter.""" + warnings.warn('sphinx.ext.autodoc.add_documenter() has been deprecated. ' + 'Please use app.add_autodocumenter() instead.', + RemovedInSphinx20Warning) + if not issubclass(cls, Documenter): raise ExtensionError('autodoc documenter %r must be a subclass ' 'of Documenter' % cls) @@ -1585,6 +1619,15 @@ def add_documenter(cls): AutoDirective._registry[cls.objtype] = cls +def get_documenters(app): + # type: (Sphinx) -> Dict[unicode, Type[Documenter]] + """Returns registered Documenter classes""" + classes = dict(AutoDirective._registry) # registered directly + if app: + classes.update(app.registry.documenters) # registered by API + return classes + + def setup(app): # type: (Sphinx) -> Dict[unicode, Any] app.add_autodocumenter(ModuleDocumenter) diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 3dded11ff..af7da3b1e 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -72,8 +72,8 @@ from sphinx import addnodes from sphinx.environment.adapters.toctree import TocTree from sphinx.util import import_object, rst, logging from sphinx.pycode import ModuleAnalyzer, PycodeError -from sphinx.ext.autodoc import Options from sphinx.ext.autodoc.importer import import_module +from sphinx.ext.autodoc import Options, get_documenters if False: # For type annotation @@ -158,8 +158,8 @@ class FakeDirective(object): genopt = Options() -def get_documenter(obj, parent): - # type: (Any, Any) -> Type[Documenter] +def get_documenter(app, obj, parent): + # type: (Sphinx, Any, Any) -> Type[Documenter] """Get an autodoc.Documenter class suitable for documenting the given object. @@ -167,8 +167,7 @@ def get_documenter(obj, parent): another Python object (e.g. a module or a class) to which *obj* belongs to. """ - from sphinx.ext.autodoc import AutoDirective, DataDocumenter, \ - ModuleDocumenter + from sphinx.ext.autodoc import DataDocumenter, ModuleDocumenter if inspect.ismodule(obj): # ModuleDocumenter.can_document_member always returns False @@ -176,7 +175,7 @@ def get_documenter(obj, parent): # Construct a fake documenter for *parent* if parent is not None: - parent_doc_cls = get_documenter(parent, None) + parent_doc_cls = get_documenter(app, parent, None) else: parent_doc_cls = ModuleDocumenter @@ -186,7 +185,7 @@ def get_documenter(obj, parent): parent_doc = parent_doc_cls(FakeDirective(), "") # Get the corrent documenter class for *obj* - classes = [cls for cls in AutoDirective._registry.values() + classes = [cls for cls in get_documenters(app).values() if cls.can_document_member(obj, '', False, parent_doc)] if classes: classes.sort(key=lambda cls: cls.priority) @@ -289,7 +288,7 @@ class Autosummary(Directive): full_name = modname + '::' + full_name[len(modname) + 1:] # NB. using full_name here is important, since Documenters # handle module prefixes slightly differently - documenter = get_documenter(obj, parent)(self, full_name) + documenter = get_documenter(self.env.app, obj, parent)(self, full_name) if not documenter.parse_name(): self.warn('failed to parse name %s' % real_name) items.append((display_name, '', '', real_name)) @@ -615,7 +614,8 @@ def process_generate_options(app): generate_autosummary_docs(genfiles, builder=app.builder, warn=logger.warning, info=logger.info, - suffix=suffix, base_path=app.srcdir) + suffix=suffix, base_path=app.srcdir, + app=app) def setup(app): diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index 4db1a93e9..2873b6082 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -31,26 +31,13 @@ from jinja2.sandbox import SandboxedEnvironment from sphinx import __display_version__ from sphinx import package_dir +from sphinx.ext.autodoc import add_documenter from sphinx.ext.autosummary import import_by_name, get_documenter from sphinx.jinja2glue import BuiltinTemplateLoader from sphinx.util.osutil import ensuredir from sphinx.util.inspect import safe_getattr from sphinx.util.rst import escape as rst_escape -# Add documenters to AutoDirective registry -from sphinx.ext.autodoc import add_documenter, \ - ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter, \ - FunctionDocumenter, MethodDocumenter, AttributeDocumenter, \ - InstanceAttributeDocumenter -add_documenter(ModuleDocumenter) -add_documenter(ClassDocumenter) -add_documenter(ExceptionDocumenter) -add_documenter(DataDocumenter) -add_documenter(FunctionDocumenter) -add_documenter(MethodDocumenter) -add_documenter(AttributeDocumenter) -add_documenter(InstanceAttributeDocumenter) - if False: # For type annotation from typing import Any, Callable, Dict, Tuple, List # NOQA @@ -60,6 +47,22 @@ if False: from sphinx.environment import BuildEnvironment # NOQA +def setup_documenters(): + from sphinx.ext.autodoc import ( + ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter, + FunctionDocumenter, MethodDocumenter, AttributeDocumenter, + InstanceAttributeDocumenter + ) + add_documenter(ModuleDocumenter) + add_documenter(ClassDocumenter) + add_documenter(ExceptionDocumenter) + add_documenter(DataDocumenter) + add_documenter(FunctionDocumenter) + add_documenter(MethodDocumenter) + add_documenter(AttributeDocumenter) + add_documenter(InstanceAttributeDocumenter) + + def _simple_info(msg): # type: (unicode) -> None print(msg) @@ -81,7 +84,7 @@ def _underline(title, line='='): def generate_autosummary_docs(sources, output_dir=None, suffix='.rst', warn=_simple_warn, info=_simple_info, base_path=None, builder=None, template_dir=None, - imported_members=False): + imported_members=False, app=None): # type: (List[unicode], unicode, unicode, Callable, Callable, unicode, Builder, unicode, bool) -> None # NOQA showed_sources = list(sorted(sources)) @@ -148,7 +151,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst', new_files.append(fn) with open(fn, 'w') as f: - doc = get_documenter(obj, parent) + doc = get_documenter(app, obj, parent) if template_name is not None: template = template_env.get_template(template_name) @@ -167,7 +170,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst', value = safe_getattr(obj, name) except AttributeError: continue - documenter = get_documenter(value, obj) + documenter = get_documenter(app, value, obj) if documenter.objtype == typ: if typ == 'method': items.append(name) @@ -392,6 +395,7 @@ The format of the autosummary directive is documented in the def main(argv=sys.argv[1:]): # type: (List[str]) -> None + setup_documenters() args = get_parser().parse_args(argv) generate_autosummary_docs(args.source_file, args.output_dir, '.' + args.suffix, diff --git a/sphinx/registry.py b/sphinx/registry.py index 6ec966a6a..38fe9caf3 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -38,6 +38,7 @@ if False: from sphinx.builders import Builder # NOQA from sphinx.domains import Domain, Index # NOQA from sphinx.environment import BuildEnvironment # NOQA + from sphinx.ext.autodoc import Documenter # NOQA from sphinx.util.typing import RoleFunction # NOQA logger = logging.getLogger(__name__) @@ -52,6 +53,7 @@ EXTENSION_BLACKLIST = { class SphinxComponentRegistry(object): def __init__(self): self.builders = {} # type: Dict[unicode, Type[Builder]] + self.documenters = {} # type: Dict[unicode, Type[Documenter]] self.domains = {} # type: Dict[unicode, Type[Domain]] self.domain_directives = {} # type: Dict[unicode, Dict[unicode, Any]] self.domain_indices = {} # type: Dict[unicode, List[Type[Index]]] @@ -284,6 +286,10 @@ class SphinxComponentRegistry(object): # type: () -> List[Type[Transform]] return self.post_transforms + def add_documenter(self, objtype, documenter): + # type: (unicode, Type[Documenter]) -> None + self.documenters[objtype] = documenter + def load_extension(self, app, extname): # type: (Sphinx, unicode) -> None """Load a Sphinx extension.""" diff --git a/tests/py35/test_autodoc_py35.py b/tests/py35/test_autodoc_py35.py index ecb0a96af..d13e50d9c 100644 --- a/tests/py35/test_autodoc_py35.py +++ b/tests/py35/test_autodoc_py35.py @@ -112,7 +112,7 @@ def skip_member(app, what, name, obj, skip, options): @pytest.mark.usefixtures('setup_test') def test_generate(): def assert_warns(warn_str, objtype, name, **kw): - inst = AutoDirective._registry[objtype](directive, name) + inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) assert len(directive.result) == 0, directive.result assert len(_warnings) == 1, _warnings @@ -120,7 +120,7 @@ def test_generate(): del _warnings[:] def assert_works(objtype, name, **kw): - inst = AutoDirective._registry[objtype](directive, name) + inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) assert directive.result # print '\n'.join(directive.result) @@ -134,7 +134,7 @@ def test_generate(): assert set(processed_docstrings) | set(processed_signatures) == set(items) def assert_result_contains(item, objtype, name, **kw): - inst = AutoDirective._registry[objtype](directive, name) + inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) # print '\n'.join(directive.result) assert len(_warnings) == 0, _warnings @@ -142,7 +142,7 @@ def test_generate(): del directive.result[:] def assert_order(items, objtype, name, member_order, **kw): - inst = AutoDirective._registry[objtype](directive, name) + inst = app.registry.documenters[objtype](directive, name) inst.options.member_order = member_order inst.generate(**kw) assert len(_warnings) == 0, _warnings diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index 61152ba02..1abd01b5f 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -121,7 +121,7 @@ def skip_member(app, what, name, obj, skip, options): @pytest.mark.usefixtures('setup_test') def test_parse_name(): def verify(objtype, name, result): - inst = AutoDirective._registry[objtype](directive, name) + inst = app.registry.documenters[objtype](directive, name) assert inst.parse_name() assert (inst.modname, inst.objpath, inst.args, inst.retann) == result @@ -164,7 +164,7 @@ def test_parse_name(): @pytest.mark.usefixtures('setup_test') def test_format_signature(): def formatsig(objtype, name, obj, args, retann): - inst = AutoDirective._registry[objtype](directive, name) + inst = app.registry.documenters[objtype](directive, name) inst.fullname = name inst.doc_as_attr = False # for class objtype inst.object = obj @@ -270,7 +270,7 @@ def test_format_signature(): @pytest.mark.usefixtures('setup_test') def test_get_doc(): def getdocl(objtype, obj, encoding=None): - inst = AutoDirective._registry[objtype](directive, 'tmp') + inst = app.registry.documenters[objtype](directive, 'tmp') inst.object = obj inst.objpath = [obj.__name__] inst.doc_as_attr = False @@ -449,7 +449,7 @@ def test_get_doc(): @pytest.mark.usefixtures('setup_test') def test_docstring_processing(): def process(objtype, name, obj): - inst = AutoDirective._registry[objtype](directive, name) + inst = app.registry.documenters[objtype](directive, name) inst.object = obj inst.fullname = name return list(inst.process_doc(inst.get_doc())) @@ -506,7 +506,7 @@ def test_docstring_property_processing(): def genarate_docstring(objtype, name, **kw): del processed_docstrings[:] del processed_signatures[:] - inst = AutoDirective._registry[objtype](directive, name) + inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) results = list(directive.result) docstrings = inst.get_doc()[0] @@ -555,7 +555,7 @@ def test_new_documenter(): add_documenter(MyDocumenter) def assert_result_contains(item, objtype, name, **kw): - inst = AutoDirective._registry[objtype](directive, name) + inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) # print '\n'.join(directive.result) assert len(_warnings) == 0, _warnings @@ -581,7 +581,7 @@ def test_attrgetter_using(): AutoDirective._special_attrgetters[type] = special_getattr del getattr_spy[:] - inst = AutoDirective._registry[objtype](directive, name) + inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) hooked_members = [s[1] for s in getattr_spy] @@ -603,7 +603,7 @@ def test_attrgetter_using(): @pytest.mark.usefixtures('setup_test') def test_generate(): def assert_warns(warn_str, objtype, name, **kw): - inst = AutoDirective._registry[objtype](directive, name) + inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) assert len(directive.result) == 0, directive.result assert len(_warnings) == 1, _warnings @@ -611,7 +611,7 @@ def test_generate(): del _warnings[:] def assert_works(objtype, name, **kw): - inst = AutoDirective._registry[objtype](directive, name) + inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) assert directive.result # print '\n'.join(directive.result) @@ -625,7 +625,7 @@ def test_generate(): assert set(processed_docstrings) | set(processed_signatures) == set(items) def assert_result_contains(item, objtype, name, **kw): - inst = AutoDirective._registry[objtype](directive, name) + inst = app.registry.documenters[objtype](directive, name) inst.generate(**kw) # print '\n'.join(directive.result) assert len(_warnings) == 0, _warnings @@ -633,7 +633,7 @@ def test_generate(): del directive.result[:] def assert_order(items, objtype, name, member_order, **kw): - inst = AutoDirective._registry[objtype](directive, name) + inst = app.registry.documenters[objtype](directive, name) inst.options.member_order = member_order inst.generate(**kw) assert len(_warnings) == 0, _warnings diff --git a/tests/test_ext_autosummary.py b/tests/test_ext_autosummary.py index 0aea99df6..1035d3b3b 100644 --- a/tests/test_ext_autosummary.py +++ b/tests/test_ext_autosummary.py @@ -57,10 +57,14 @@ def test_mangle_signature(): @pytest.mark.sphinx('dummy', **default_kw) -def test_get_items_summary(app, status, warning): +def test_get_items_summary(make_app, app_params): + import sphinx.ext.autosummary + import sphinx.ext.autosummary.generate + sphinx.ext.autosummary.generate.setup_documenters() + args, kwargs = app_params + app = make_app(*args, **kwargs) # monkey-patch Autosummary.get_items so we can easily get access to it's # results.. - import sphinx.ext.autosummary orig_get_items = sphinx.ext.autosummary.Autosummary.get_items autosummary_items = {} @@ -81,7 +85,7 @@ def test_get_items_summary(app, status, warning): finally: sphinx.ext.autosummary.Autosummary.get_items = orig_get_items - html_warnings = warning.getvalue() + html_warnings = app._warning.getvalue() assert html_warnings == '' expected_values = { diff --git a/tests/test_templating.py b/tests/test_templating.py index 341b33f51..88a196e77 100644 --- a/tests/test_templating.py +++ b/tests/test_templating.py @@ -10,10 +10,14 @@ """ import pytest +from sphinx.ext.autosummary.generate import setup_documenters @pytest.mark.sphinx('html', testroot='templating') -def test_layout_overloading(app, status, warning): +def test_layout_overloading(make_app, app_params): + setup_documenters() + args, kwargs = app_params + app = make_app(*args, **kwargs) app.builder.build_update() result = (app.outdir / 'contents.html').text(encoding='utf-8') @@ -22,7 +26,10 @@ def test_layout_overloading(app, status, warning): @pytest.mark.sphinx('html', testroot='templating') -def test_autosummary_class_template_overloading(app, status, warning): +def test_autosummary_class_template_overloading(make_app, app_params): + setup_documenters() + args, kwargs = app_params + app = make_app(*args, **kwargs) app.builder.build_update() result = (app.outdir / 'generated' / 'sphinx.application.TemplateBridge.html').text( From 4b51ed4aa9170265d682d120bb900e9fd94a21bc Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 18 Jun 2017 19:21:46 +0900 Subject: [PATCH 208/275] Deprecate AutoDirective._special_attrgetters --- CHANGES | 4 +++- sphinx/application.py | 9 ++++----- sphinx/ext/autodoc/__init__.py | 31 ++++++++++++++++++++----------- sphinx/registry.py | 5 +++++ 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/CHANGES b/CHANGES index c0934c396..ca0f3220a 100644 --- a/CHANGES +++ b/CHANGES @@ -22,7 +22,9 @@ Deprecated * ``format_annotation()`` and ``formatargspec()`` is deprecated. Please use ``sphinx.util.inspect.Signature`` instead. * ``sphinx.ext.autodoc.add_documenter()`` and ``AutoDirective._register`` is now - deprecated. Please use ``app.add_autodocumenter()`` + deprecated. Please use ``app.add_autodocumenter()`` instead. +* ``AutoDirective._special_attrgetters`` is now deprecated. Please use + ``app.add_autodoc_attrgetter()`` instead. Features added -------------- diff --git a/sphinx/application.py b/sphinx/application.py index 3bfea910f..07b8539a9 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -646,11 +646,10 @@ class Sphinx(object): self.add_directive('auto' + cls.objtype, AutoDirective) self.registry.add_documenter(cls.objtype, cls) - def add_autodoc_attrgetter(self, type, getter): - # type: (Any, Callable) -> None - logger.debug('[app] adding autodoc attrgetter: %r', (type, getter)) - from sphinx.ext import autodoc - autodoc.AutoDirective._special_attrgetters[type] = getter + def add_autodoc_attrgetter(self, typ, getter): + # type: (Type, Callable[[Any, unicode, Any], Any]) -> None + logger.debug('[app] adding autodoc attrgetter: %r', (typ, getter)) + self.registy.add_autodoc_attrgetter(typ, getter) def add_search_language(self, cls): # type: (Any) -> None diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index a6afe4f4c..14572e283 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -285,14 +285,10 @@ class Documenter(object): option_spec = {'noindex': bool_option} # type: Dict[unicode, Callable] - @staticmethod - def get_attr(obj, name, *defargs): + def get_attr(self, obj, name, *defargs): # type: (Any, unicode, Any) -> Any """getattr() override for types such as Zope interfaces.""" - for typ, func in iteritems(AutoDirective._special_attrgetters): - if isinstance(obj, typ): - return func(obj, name, *defargs) - return safe_getattr(obj, name, *defargs) + return autodoc_attrgetter(self.env.app, obj, name, *defargs) @classmethod def can_document_member(cls, member, membername, isattr, parent): @@ -1496,10 +1492,6 @@ class AutoDirective(Directive): The AutoDirective class is used for all autodoc directives. It dispatches most of the work to one of the Documenters. - The *_special_attrgetters* attribute is used to customize ``getattr()`` - calls that the Documenters make; its entries are of the form ``type: - getattr_function``. - Note: When importing an object, all items along the import chain are accessed using the descendant's *_special_attrgetters*, thus this dictionary should include all necessary functions for accessing @@ -1512,7 +1504,10 @@ class AutoDirective(Directive): ) # type: Dict[unicode, Type[Documenter]] # a registry of type -> getattr function - _special_attrgetters = {} # type: Dict[Type, Callable] + _special_attrgetters = DeprecatedDict( + 'AutoDirective._special_attrgetters has been deprecated. ' + 'Please use app.add_autodoc_attrgetter() instead.' + ) # type: Dict[Type, Callable] # flags that can be given in autodoc_default_flags _default_flags = set([ @@ -1628,6 +1623,20 @@ def get_documenters(app): return classes +def autodoc_attrgetter(app, obj, name, *defargs): + # type: (Sphinx, Any, unicode, Any) -> Any + """Alternative getattr() for types""" + candidates = dict(AutoDirective._special_attrgetters) + if app: + candidates.update(app.registry.autodoc_attrgettrs) + + for typ, func in iteritems(candidates): + if isinstance(obj, typ): + return func(obj, name, *defargs) + + return safe_getattr(obj, name, *defargs) + + def setup(app): # type: (Sphinx) -> Dict[unicode, Any] app.add_autodocumenter(ModuleDocumenter) diff --git a/sphinx/registry.py b/sphinx/registry.py index 38fe9caf3..e48c12f96 100644 --- a/sphinx/registry.py +++ b/sphinx/registry.py @@ -52,6 +52,7 @@ EXTENSION_BLACKLIST = { class SphinxComponentRegistry(object): def __init__(self): + self.autodoc_attrgettrs = {} # type: Dict[Type, Callable[[Any, unicode, Any], Any]] self.builders = {} # type: Dict[unicode, Type[Builder]] self.documenters = {} # type: Dict[unicode, Type[Documenter]] self.domains = {} # type: Dict[unicode, Type[Domain]] @@ -290,6 +291,10 @@ class SphinxComponentRegistry(object): # type: (unicode, Type[Documenter]) -> None self.documenters[objtype] = documenter + def add_autodoc_attrgetter(self, typ, attrgetter): + # type: (Type, Callable[[Any, unicode, Any], Any]) -> None + self.autodoc_attrgettrs[typ] = attrgetter + def load_extension(self, app, extname): # type: (Sphinx, unicode) -> None """Load a Sphinx extension.""" From bf0153d74850cc9d498a0ed152a0d3d6e7e49f96 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 22 Jun 2017 01:20:18 +0900 Subject: [PATCH 209/275] autodoc: Refactor get_object_members() --- sphinx/ext/autodoc/__init__.py | 63 ++++++++-------------------------- sphinx/ext/autodoc/importer.py | 33 +++++++++++++++++- 2 files changed, 47 insertions(+), 49 deletions(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 14572e283..16abb8c71 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -16,7 +16,7 @@ import sys import inspect import warnings -from six import iterkeys, iteritems, itervalues, text_type, class_types, string_types +from six import iteritems, itervalues, text_type, class_types, string_types from docutils import nodes from docutils.utils import assemble_option_dict @@ -25,7 +25,7 @@ from docutils.statemachine import ViewList import sphinx from sphinx.deprecation import RemovedInSphinx20Warning -from sphinx.ext.autodoc.importer import mock, import_object +from sphinx.ext.autodoc.importer import mock, import_object, get_object_members from sphinx.ext.autodoc.importer import _MockImporter # to keep compatibility # NOQA from sphinx.ext.autodoc.inspector import format_annotation, formatargspec # to keep compatibility # NOQA from sphinx.util import rpartition, force_decode @@ -36,7 +36,7 @@ from sphinx.util import logging from sphinx.util.nodes import nested_parse_with_titles from sphinx.util.inspect import Signature, isdescriptor, safe_getmembers, \ safe_getattr, object_description, is_builtin_class_method, \ - isenumclass, isenumattribute, getdoc + isenumattribute, getdoc from sphinx.util.docstrings import prepare_docstring if False: @@ -570,57 +570,24 @@ class Documenter(object): If *want_all* is True, return all members. Else, only return those members given by *self.options.members* (which may also be none). """ - analyzed_member_names = set() - if self.analyzer: - attr_docs = self.analyzer.find_attr_docs() - namespace = '.'.join(self.objpath) - for item in iteritems(attr_docs): - if item[0][0] == namespace: - analyzed_member_names.add(item[0][1]) + members = get_object_members(self.object, self.objpath, self.get_attr, self.analyzer) if not want_all: if not self.options.members: return False, [] # specific members given - members = [] - for mname in self.options.members: - try: - members.append((mname, self.get_attr(self.object, mname))) - except AttributeError: - if mname not in analyzed_member_names: - self.directive.warn('missing attribute %s in object %s' - % (mname, self.fullname)) + selected = [] + for name in self.options.members: + if name in members: + selected.append((name, members[name].value)) + else: + self.directive.warn('missing attribute %s in object %s' % + (name, self.fullname)) + return False, sorted(selected) elif self.options.inherited_members: - # safe_getmembers() uses dir() which pulls in members from all - # base classes - members = safe_getmembers(self.object, attr_getter=self.get_attr) + return False, sorted((m.name, m.value) for m in itervalues(members)) else: - # __dict__ contains only the members directly defined in - # the class (but get them via getattr anyway, to e.g. get - # unbound method objects instead of function objects); - # using list(iterkeys()) because apparently there are objects for which - # __dict__ changes while getting attributes - try: - obj_dict = self.get_attr(self.object, '__dict__') - except AttributeError: - members = [] - else: - members = [(mname, self.get_attr(self.object, mname, None)) - for mname in list(iterkeys(obj_dict))] - - # Py34 doesn't have enum members in __dict__. - if isenumclass(self.object): - members.extend( - item for item in self.object.__members__.items() - if item not in members - ) - - membernames = set(m[0] for m in members) - # add instance attributes from the analyzer - for aname in analyzed_member_names: - if aname not in membernames and \ - (want_all or aname in self.options.members): - members.append((aname, INSTANCEATTR)) - return False, sorted(members) + return False, sorted((m.name, m.value) for m in itervalues(members) + if m.directly_defined) def filter_members(self, members, want_all): # type: (List[Tuple[unicode, Any]], bool) -> List[Tuple[unicode, Any, bool]] diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py index 95ca58d0b..b22af9ff5 100644 --- a/sphinx/ext/autodoc/importer.py +++ b/sphinx/ext/autodoc/importer.py @@ -13,6 +13,7 @@ import sys import warnings import traceback import contextlib +from collections import namedtuple from types import FunctionType, MethodType, ModuleType from six import PY2 @@ -22,7 +23,7 @@ from sphinx.util.inspect import safe_getattr if False: # For type annotation - from typing import Any, Callable, Generator, List, Set # NOQA + from typing import Any, Callable, Dict, Generator, List, Optional, Set # NOQA logger = logging.getLogger(__name__) @@ -194,3 +195,33 @@ def import_object(modname, objpath, objtype='', attrgetter=safe_getattr, warning errmsg = errmsg.decode('utf-8') # type: ignore logger.debug(errmsg) raise ImportError(errmsg) + + +Attribute = namedtuple('Attribute', ['name', 'directly_defined', 'value']) + + +def get_object_members(subject, objpath, attrgetter, analyzer=None): + # type: (Any, List[unicode], Callable, Any) -> Dict[str, Attribute] # NOQA + """Get members and attributes of target object.""" + # the members directly defined in the class + obj_dict = attrgetter(subject, '__dict__', {}) + + members = {} + for name in dir(subject): + try: + value = attrgetter(subject, name) + directly_defined = name in obj_dict + members[name] = Attribute(name, directly_defined, value) + except AttributeError: + continue + + if analyzer: + # append instance attributes (cf. self.attr1) if analyzer knows + from sphinx.ext.autodoc import INSTANCEATTR + + namespace = '.'.join(objpath) + for (ns, name) in analyzer.find_attr_docs(): + if namespace == ns and name not in members: + members[name] = Attribute(name, True, INSTANCEATTR) + + return members From 69f39e44d91c0eb10596448f38fb1aafcbf2054a Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Sun, 24 Dec 2017 20:05:13 +0000 Subject: [PATCH 210/275] tox: Enable 'skipsdist' Given that we install Sphinx as part of the dependencies, there's no reason to do it twice. Skip that step. Signed-off-by: Stephen Finucane --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index 530e5b941..9c0f2d2f3 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,6 @@ [tox] envlist=flake8,py27,py34,py35,py36,pypy,du13,du12,du11 +skipsdist = True [testenv] deps= From f21fe6f24f879fcb640e9d9711eeb777a57b10a9 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 1 Jan 2018 23:03:15 +0900 Subject: [PATCH 211/275] Revert "tox: Enable 'skipsdist'" This reverts commit 69f39e44d91c0eb10596448f38fb1aafcbf2054a. --- tox.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/tox.ini b/tox.ini index 9c0f2d2f3..530e5b941 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,5 @@ [tox] envlist=flake8,py27,py34,py35,py36,pypy,du13,du12,du11 -skipsdist = True [testenv] deps= From 850e9a9c5cbd18163eaa8861c7fecbdfb9921a2b Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 1 Jan 2018 23:29:10 +0900 Subject: [PATCH 212/275] Fix links to external option docs with intersphinx (refs: #3769) --- CHANGES | 1 + sphinx/domains/std.py | 16 +++++++++++----- sphinx/ext/intersphinx.py | 1 + tests/test_ext_intersphinx.py | 8 +++++++- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index bb11d643d..39288bea7 100644 --- a/CHANGES +++ b/CHANGES @@ -38,6 +38,7 @@ Bugs fixed * #4315: For PDF 'howto' documents, ``latex_toplevel_sectioning='part'`` generates ``\chapter`` commands * #4214: Two todolist directives break sphinx-1.6.5 +* Fix links to external option docs with intersphinx (refs: #3769) Testing -------- diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py index 27bb88c96..68baa04aa 100644 --- a/sphinx/domains/std.py +++ b/sphinx/domains/std.py @@ -959,12 +959,18 @@ class StandardDomain(Domain): def get_full_qualified_name(self, node): # type: (nodes.Node) -> unicode - progname = node.get('std:program') - target = node.get('reftarget') - if progname is None or target is None: - return None + if node.get('reftype') == 'option': + progname = node.get('std:program') + command = ws_re.split(node.get('reftarget')) + if progname: + command.insert(0, progname) + option = command.pop() + if command: + return '.'.join(['-'.join(command), option]) + else: + return None else: - return '.'.join([progname, target]) + return None def setup(app): diff --git a/sphinx/ext/intersphinx.py b/sphinx/ext/intersphinx.py index ccd2c9321..9336c4b53 100644 --- a/sphinx/ext/intersphinx.py +++ b/sphinx/ext/intersphinx.py @@ -304,6 +304,7 @@ def missing_reference(app, env, node, contnode): in_set = setname to_try.append((inventories.named_inventory[setname], newtarget)) if domain: + node['reftarget'] = newtarget full_qualified_name = env.get_domain(domain).get_full_qualified_name(node) if full_qualified_name: to_try.append((inventories.named_inventory[setname], full_qualified_name)) diff --git a/tests/test_ext_intersphinx.py b/tests/test_ext_intersphinx.py index 371f296ea..a978928d4 100644 --- a/tests/test_ext_intersphinx.py +++ b/tests/test_ext_intersphinx.py @@ -194,7 +194,7 @@ def test_missing_reference_stddomain(tempdir, app, status, warning): inv_file = tempdir / 'inventory' inv_file.write_bytes(inventory_v2) app.config.intersphinx_mapping = { - 'https://docs.python.org/': inv_file, + 'cmd': ('https://docs.python.org/', inv_file), } app.config.intersphinx_cache_limit = 0 @@ -213,6 +213,12 @@ def test_missing_reference_stddomain(tempdir, app, status, warning): rn = missing_reference(app, app.env, node, contnode) assert rn.astext() == 'ls -l' + # refers inventory by name + kwargs = {} + node, contnode = fake_node('std', 'option', 'cmd:ls -l', '-l', **kwargs) + rn = missing_reference(app, app.env, node, contnode) + assert rn.astext() == '-l' + @pytest.mark.sphinx('html', testroot='ext-intersphinx-cppdomain') def test_missing_reference_cppdomain(tempdir, app, status, warning): From cb860f0d306b3dc5a8688e3c88035b060fc0882f Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 2 Jan 2018 01:57:41 +0900 Subject: [PATCH 213/275] Fix #4091: Private members not documented without :undoc-members: --- CHANGES | 1 + sphinx/ext/autodoc.py | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 39288bea7..1e1379178 100644 --- a/CHANGES +++ b/CHANGES @@ -39,6 +39,7 @@ Bugs fixed ``\chapter`` commands * #4214: Two todolist directives break sphinx-1.6.5 * Fix links to external option docs with intersphinx (refs: #3769) +* #4091: Private members not documented without :undoc-members: Testing -------- diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index e04b4a09d..bd686644c 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -965,8 +965,7 @@ class Documenter(object): elif (namespace, membername) in attr_docs: if want_all and membername.startswith('_'): # ignore members whose name starts with _ by default - keep = self.options.private_members and \ - (has_doc or self.options.undoc_members) + keep = self.options.private_members else: # keep documented attributes keep = True From 309f38a91fcbb8405a7f3d8c13fe4bce65b0b230 Mon Sep 17 00:00:00 2001 From: jfbu Date: Tue, 2 Jan 2018 23:11:19 +0100 Subject: [PATCH 214/275] Split out fancy LaTeX macros from ``\sphinxcode`` into ``\sphinxupquote`` Since #2627 (1.4.4), `\code`, and then again at #3116 (1.5) `\sphinxcode` which is the new name has become more complicated than the original `\texttt{#1}`. This was to obtain straight quotes in PDF output, and to allow long inline literals to break across lines. This means though that users who want to customize `\sphinxcode`, for example to not only do `\texttt` but to use some colour, have to copy about 10 lines of complicated LaTeX macros which should be not modified in any way. This commit moves all the code out of `\sphinxcode` into a separate macro `\sphinxupquote`. The LaTeX writer will output `\sphinxcode{\sphinxupquote{foo}}` in place of former `\sphinxcode{foo}`. Moving the `\texttt` from innermost to outermost level is with no consequence. --- sphinx/texinputs/sphinx.sty | 15 ++++++++------- sphinx/writers/latex.py | 26 +++++++++++++------------- tests/test_markup.py | 12 ++++++------ 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 890ef60f7..8de263a52 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -1459,8 +1459,8 @@ % \newenvironment{productionlist}{% % \def\sphinxoptional##1{{\Large[}##1{\Large]}} - \def\production##1##2{\\\sphinxcode{##1}&::=&\sphinxcode{##2}}% - \def\productioncont##1{\\& &\sphinxcode{##1}}% + \def\production##1##2{\\\sphinxcode{\sphinxupquote{##1}}&::=&\sphinxcode{\sphinxupquote{##2}}}% + \def\productioncont##1{\\& &\sphinxcode{\sphinxupquote{##1}}}% \parindent=2em \indent \setlength{\LTpre}{0pt}% @@ -1541,15 +1541,13 @@ %% TEXT STYLING % -% Some custom font markup commands. -\protected\def\sphinxstrong#1{{\textbf{#1}}} % to obtain straight quotes we execute \@noligs as patched by upquote, and % \scantokens is needed in cases where it would be too late for the macro to % first set catcodes and then fetch its argument. We also make the contents % breakable at non-escaped . , ; ? ! / using \sphinxbreaksviaactive. % the macro must be protected if it ends up used in moving arguments, % in 'alltt' \@noligs is done already, and the \scantokens must be avoided. -\protected\def\sphinxcode#1{{\def\@tempa{alltt}% +\protected\def\sphinxupquote#1{{\def\@tempa{alltt}% \ifx\@tempa\@currenvir\else \ifspx@opt@inlineliteralwraps \sphinxbreaksviaactive\let\sphinxafterbreak\empty @@ -1560,12 +1558,15 @@ \let\do@noligs\sphinx@do@noligs \@noligs\endlinechar\m@ne\everyeof{}% (<- in case inside \sphinxhref) \expandafter\scantokens - \fi {\texttt{#1}}}} + \fi {#1}}} \def\sphinx@do@noligs #1{\catcode`#1\active\begingroup\lccode`\~`#1\relax \lowercase{\endgroup\def~{\leavevmode\kern\z@\char`#1 }}} \def\sphinx@literal@nolig@list {\do\`\do\<\do\>\do\'\do\-}% -\protected\def\sphinxbfcode#1{\sphinxcode{\bfseries{}#1}} +% Some custom font markup commands. +\protected\def\sphinxstrong#1{\textbf{#1}} +\protected\def\sphinxcode#1{\texttt{#1}} +\protected\def\sphinxbfcode#1{\textbf{\sphinxcode{#1}}} \protected\def\sphinxemail#1{\textsf{#1}} \protected\def\sphinxtablecontinued#1{\textsf{#1}} \protected\def\sphinxtitleref#1{\emph{#1}} diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 9a3c0e5cd..de472b36c 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -1216,12 +1216,12 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_desc_addname(self, node): # type: (nodes.Node) -> None - self.body.append(r'\sphinxcode{') + self.body.append(r'\sphinxcode{\sphinxupquote{') self.literal_whitespace += 1 def depart_desc_addname(self, node): # type: (nodes.Node) -> None - self.body.append('}') + self.body.append('}}') self.literal_whitespace -= 1 def visit_desc_type(self, node): @@ -1242,13 +1242,13 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_desc_name(self, node): # type: (nodes.Node) -> None - self.body.append(r'\sphinxbfcode{') + self.body.append(r'\sphinxbfcode{\sphinxupquote{') self.no_contractions += 1 self.literal_whitespace += 1 def depart_desc_name(self, node): # type: (nodes.Node) -> None - self.body.append('}') + self.body.append('}}') self.literal_whitespace -= 1 self.no_contractions -= 1 @@ -1287,11 +1287,11 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_desc_annotation(self, node): # type: (nodes.Node) -> None - self.body.append(r'\sphinxbfcode{') + self.body.append(r'\sphinxbfcode{\sphinxupquote{') def depart_desc_annotation(self, node): # type: (nodes.Node) -> None - self.body.append('}') + self.body.append('}}') def visit_desc_content(self, node): # type: (nodes.Node) -> None @@ -2177,12 +2177,12 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_literal_emphasis(self, node): # type: (nodes.Node) -> None - self.body.append(r'\sphinxstyleliteralemphasis{') + self.body.append(r'\sphinxstyleliteralemphasis{\sphinxupquote{') self.no_contractions += 1 def depart_literal_emphasis(self, node): # type: (nodes.Node) -> None - self.body.append('}') + self.body.append('}}') self.no_contractions -= 1 def visit_strong(self, node): @@ -2195,12 +2195,12 @@ class LaTeXTranslator(nodes.NodeVisitor): def visit_literal_strong(self, node): # type: (nodes.Node) -> None - self.body.append(r'\sphinxstyleliteralstrong{') + self.body.append(r'\sphinxstyleliteralstrong{\sphinxupquote{') self.no_contractions += 1 def depart_literal_strong(self, node): # type: (nodes.Node) -> None - self.body.append('}') + self.body.append('}}') self.no_contractions -= 1 def visit_abbreviation(self, node): @@ -2259,14 +2259,14 @@ class LaTeXTranslator(nodes.NodeVisitor): # type: (nodes.Node) -> None self.no_contractions += 1 if self.in_title: - self.body.append(r'\sphinxstyleliteralintitle{') + self.body.append(r'\sphinxstyleliteralintitle{\sphinxupquote{') else: - self.body.append(r'\sphinxcode{') + self.body.append(r'\sphinxcode{\sphinxupquote{') def depart_literal(self, node): # type: (nodes.Node) -> None self.no_contractions -= 1 - self.body.append('}') + self.body.append('}}') def visit_footnote_reference(self, node): # type: (nodes.Node) -> None diff --git a/tests/test_markup.py b/tests/test_markup.py index 34ab1405d..c48096e34 100644 --- a/tests/test_markup.py +++ b/tests/test_markup.py @@ -135,7 +135,7 @@ def get_verifier(verify, verify_re): '``code sample``', ('

' 'code   sample

'), - r'\\sphinxcode{code sample}', + r'\\sphinxcode{\\sphinxupquote{code sample}}', ), ( # correct interpretation of code with whitespace @@ -143,7 +143,7 @@ def get_verifier(verify, verify_re): ':samp:`code sample`', ('

' 'code   sample

'), - r'\\sphinxcode{code sample}', + r'\\sphinxcode{\\sphinxupquote{code sample}}', ), ( # interpolation of braces in samp and file roles (HTML only) @@ -152,7 +152,7 @@ def get_verifier(verify, verify_re): ('

a' 'b' 'c

'), - '\\sphinxcode{a\\sphinxstyleemphasis{b}c}', + '\\sphinxcode{\\sphinxupquote{a\\sphinxstyleemphasis{b}c}}', ), ( # interpolation of arrows in menuselection @@ -175,7 +175,7 @@ def get_verifier(verify, verify_re): ':option:`--with-option`', ('

' '--with-option

$'), - r'\\sphinxcode{-{-}with-option}$', + r'\\sphinxcode{\\sphinxupquote{-{-}with-option}}$', ), ( # verify smarty-pants quotes @@ -190,14 +190,14 @@ def get_verifier(verify, verify_re): '``"John"``', ('

' '"John"

'), - '\\sphinxcode{"John"}', + '\\sphinxcode{\\sphinxupquote{"John"}}', ), ( # verify classes for inline roles 'verify', ':manpage:`mp(1)`', '

mp(1)

', - '\\sphinxstyleliteralemphasis{mp(1)}', + '\\sphinxstyleliteralemphasis{\\sphinxupquote{mp(1)}}', ), ( # correct escaping in normal mode From 680d6766bb556bb31bedac7847120b7ecc7465dd Mon Sep 17 00:00:00 2001 From: jfbu Date: Tue, 2 Jan 2018 23:28:46 +0100 Subject: [PATCH 215/275] Make LaTeX macro definitions more readable This make clearer to average LaTeX user the format which is expected for these macros, in case of redefinitions. --- sphinx/texinputs/sphinx.sty | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 8de263a52..61192d628 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -1580,21 +1580,21 @@ % additional customizable styling % FIXME: convert this to package options ? -\protected\def\sphinxstyleindexentry {\texttt} -\protected\def\sphinxstyleindexextra #1{ \emph{(#1)}} -\protected\def\sphinxstyleindexpageref {, \pageref} -\protected\def\sphinxstyletopictitle #1{\textbf{#1}\par\medskip} +\protected\def\sphinxstyleindexentry #1{\texttt{#1}} +\protected\def\sphinxstyleindexextra #1{ \emph{(#1)}} +\protected\def\sphinxstyleindexpageref #1{, \pageref{#1}} +\protected\def\sphinxstyletopictitle #1{\textbf{#1}\par\medskip} \let\sphinxstylesidebartitle\sphinxstyletopictitle -\protected\def\sphinxstyleothertitle {\textbf} +\protected\def\sphinxstyleothertitle #1{\textbf{#1}} \protected\def\sphinxstylesidebarsubtitle #1{~\\\textbf{#1} \smallskip} % \text.. commands do not allow multiple paragraphs \protected\def\sphinxstyletheadfamily {\sffamily} -\protected\def\sphinxstyleemphasis {\emph} +\protected\def\sphinxstyleemphasis #1{\emph{#1}} \protected\def\sphinxstyleliteralemphasis#1{\emph{\sphinxcode{#1}}} -\protected\def\sphinxstylestrong {\textbf} -\protected\def\sphinxstyleliteralstrong {\sphinxbfcode} -\protected\def\sphinxstyleabbreviation {\textsc} -\protected\def\sphinxstyleliteralintitle {\sphinxcode} +\protected\def\sphinxstylestrong #1{\textbf{#1}} +\protected\def\sphinxstyleliteralstrong#1{\sphinxbfcode{#1}} +\protected\def\sphinxstyleabbreviation #1{\textsc{#1}} +\protected\def\sphinxstyleliteralintitle#1{\sphinxcode{#1}} \newcommand*\sphinxstylecodecontinued[1]{\footnotesize(#1)}% \newcommand*\sphinxstylecodecontinues[1]{\footnotesize(#1)}% % figure legend comes after caption and may contain arbitrary body elements From c892fe98f7a311dc51340f8d98e63d9790b7f820 Mon Sep 17 00:00:00 2001 From: jfbu Date: Wed, 3 Jan 2018 10:50:18 +0100 Subject: [PATCH 216/275] Fix space gobbling issue from PR #4370 This is subtle LaTeX thing. Prior to merge of #4370 there was a `\texttt` which was hiding the potential problem. The fix is to leave a brace pair in place. --- sphinx/texinputs/sphinx.sty | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 61192d628..2b41673db 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -1558,7 +1558,7 @@ \let\do@noligs\sphinx@do@noligs \@noligs\endlinechar\m@ne\everyeof{}% (<- in case inside \sphinxhref) \expandafter\scantokens - \fi {#1}}} + \fi {{#1}}}}% extra brace pair to fix end-space gobbling issue... \def\sphinx@do@noligs #1{\catcode`#1\active\begingroup\lccode`\~`#1\relax \lowercase{\endgroup\def~{\leavevmode\kern\z@\char`#1 }}} \def\sphinx@literal@nolig@list {\do\`\do\<\do\>\do\'\do\-}% From 6fa344c951a8c9c67c4fd7492a758f8e70ee3c4f Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 3 Jan 2018 20:15:20 +0900 Subject: [PATCH 217/275] Show traceback if conf.py raises an exception (refs: #4369) --- CHANGES | 1 + sphinx/config.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGES b/CHANGES index 39288bea7..a6caf7031 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,7 @@ Features added * ``VerbatimHighlightColor`` is a new :ref:`LaTeX 'sphinxsetup' ` key (refs: #4285) * Easier customizability of LaTeX macros involved in rendering of code-blocks +* Show traceback if conf.py raises an exception (refs: #4369) Bugs fixed ---------- diff --git a/sphinx/config.py b/sphinx/config.py index d3468b0a5..50f7c018c 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -10,6 +10,7 @@ """ import re +import traceback from os import path, getenv from six import PY2, PY3, iteritems, string_types, binary_type, text_type, integer_types @@ -35,6 +36,7 @@ copyright_year_re = re.compile(r'^((\d{4}-)?)(\d{4})(?=[ ,])') CONFIG_SYNTAX_ERROR = "There is a syntax error in your configuration file: %s" if PY3: CONFIG_SYNTAX_ERROR += "\nDid you change the syntax from 2.x to 3.x?" +CONFIG_ERROR = "There is a programable error in your configuration file:\n\n%s" CONFIG_EXIT_ERROR = "The configuration file (or one of the modules it imports) " \ "called sys.exit()" CONFIG_ENUM_WARNING = "The config value `{name}` has to be a one of {candidates}, " \ @@ -152,6 +154,8 @@ class Config(object): raise ConfigError(CONFIG_SYNTAX_ERROR % err) except SystemExit: raise ConfigError(CONFIG_EXIT_ERROR) + except Exception: + raise ConfigError(CONFIG_ERROR % traceback.format_exc()) self._raw_config = config # these two must be preinitialized because extensions can add their From b04151bca8d43aceb8a0bf018fb736cb215d0729 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Fri, 5 Jan 2018 01:41:01 +0100 Subject: [PATCH 218/275] improved sidebar search field style --- sphinx/themes/basic/searchbox.html | 6 ++++-- sphinx/themes/basic/static/basic.css_t | 14 +++++++++++++- sphinx/themes/nature/static/nature.css_t | 7 ++----- sphinx/themes/pyramid/static/pyramid.css_t | 7 ++----- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/sphinx/themes/basic/searchbox.html b/sphinx/themes/basic/searchbox.html index a8ea03cc8..506877410 100644 --- a/sphinx/themes/basic/searchbox.html +++ b/sphinx/themes/basic/searchbox.html @@ -10,12 +10,14 @@ {%- if pagename != "search" and builder != "singlehtml" %} {%- endif %} diff --git a/sphinx/themes/basic/static/basic.css_t b/sphinx/themes/basic/static/basic.css_t index 745864e28..efb997d8f 100644 --- a/sphinx/themes/basic/static/basic.css_t +++ b/sphinx/themes/basic/static/basic.css_t @@ -82,9 +82,21 @@ div.sphinxsidebar input { } div.sphinxsidebar #searchbox input[type="text"] { - width: 170px; + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; } +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + img { border: 0; max-width: 100%; diff --git a/sphinx/themes/nature/static/nature.css_t b/sphinx/themes/nature/static/nature.css_t index 5751bf940..ff2b1d5ff 100644 --- a/sphinx/themes/nature/static/nature.css_t +++ b/sphinx/themes/nature/static/nature.css_t @@ -125,14 +125,11 @@ div.sphinxsidebar input { font-size: 1em; } -div.sphinxsidebar input[type=text]{ +div.sphinxsidebar .searchformwrapper { margin-left: 20px; + margin-right: 20px; } -div.sphinxsidebar input[type=submit]{ - margin-left: 20px; -} - /* -- body styles ----------------------------------------------------------- */ a { diff --git a/sphinx/themes/pyramid/static/pyramid.css_t b/sphinx/themes/pyramid/static/pyramid.css_t index 93799111e..792f45452 100644 --- a/sphinx/themes/pyramid/static/pyramid.css_t +++ b/sphinx/themes/pyramid/static/pyramid.css_t @@ -148,12 +148,9 @@ div.sphinxsidebar input { font-size: 1em; } -div.sphinxsidebar input[type=text]{ - margin-left: 20px; -} - -div.sphinxsidebar input[type=submit]{ +div.sphinxsidebar .searchformwrapper { margin-left: 20px; + margin-right: 20px; } /* -- sidebars -------------------------------------------------------------- */ From e3efe5884b08e4e4994d58eaf9c645b8f9567547 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Fri, 5 Jan 2018 22:25:34 +0900 Subject: [PATCH 219/275] Fix #4378: tox: use usedevelop option instead skipsdist --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index ae6b2a4b3..2862fd755 100644 --- a/tox.ini +++ b/tox.ini @@ -1,9 +1,9 @@ [tox] minversion = 2.0 envlist = docs,flake8,mypy,coverage,py{27,34,35,36,py},du{11,12,13,14} -skipsdist = True [testenv] +usedevelop = True passenv = https_proxy http_proxy no_proxy PERL PERL5LIB description = From bd139453c96864646c0b7b1bf2f30b12587cb235 Mon Sep 17 00:00:00 2001 From: jfbu Date: Fri, 5 Jan 2018 15:06:10 +0100 Subject: [PATCH 220/275] Move SphinxSmartQuotes transform to SphinxStandaloneReader closes #4142 closes #4357 closes #4359 refs: #3967 Adds ``smartquotes``, ``smartquotes_action``, ``smartquotes_excludes`` configuration variables. - if ``smartquotes`` is set to False, then Smart Quotes transform is not applied even if a Docutils configuration file activates it, - the current default of ``smartquotes_excludes`` deactivates Smart Quotes for Japanese language, and also for the ``man`` and ``text`` builders. However, currently ``make text html`` deactivates Smart Quotes for ``html`` too, and ``make html text`` activates them for ``text`` too, because the picked environment is shared and already transformed. - now Smart Quotes get applied also when source documents are in Markdown or other formats. --- doc/config.rst | 65 ++++++++++++++++++++++++++++++---- sphinx/config.py | 5 +++ sphinx/environment/__init__.py | 48 ++++++++++++++++++++----- sphinx/io.py | 12 ++++++- sphinx/parsers.py | 7 ++-- 5 files changed, 117 insertions(+), 20 deletions(-) diff --git a/doc/config.rst b/doc/config.rst index 1f222451d..6b7690c76 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -353,6 +353,63 @@ General configuration .. versionadded:: 1.3 +.. confval:: smartquotes + + If true, the `Docutils Smart Quotes transform`__, originally based on + `SmartyPants`__ (limited to English) and currently applying to many + languages, will be used to convert quotes and dashes to typographically + correct entities. Default: ``True``. + + __ http://docutils.sourceforge.net/docs/user/smartquotes.html + __ https://daringfireball.net/projects/smartypants/ + + .. versionadded:: 1.6.6 + It replaces deprecated :confval:`html_use_smartypants`. + It applies by default to all builders except ``man`` and ``text`` + (see :confval:`smartquotes_excludes`.) + + A `docutils.conf`__ file located in the configuration directory (or a + global :file:`~/.docutils` file) is obeyed unconditionally if it + *deactivates* smart quotes via the corresponding `Docutils option`__. But + if it *activates* them, then :confval:`smartquotes` does prevail. + + __ http://docutils.sourceforge.net/docs/user/config.html + __ http://docutils.sourceforge.net/docs/user/config.html#smart-quotes + +.. confval:: smartquotes_action + + This string, for use with Docutils ``0.14`` or later, customizes the Smart + Quotes transform. See the file :file:`smartquotes.py` at the `Docutils + repository`__ for details. The default ``'qDe'`` educates normal **q**\ + uote characters ``"``, ``'``, em- and en-**D**\ ashes ``---``, ``--``, and + **e**\ llipses ``...``. + + .. versionadded:: 1.6.6 + + __ https://sourceforge.net/p/docutils/code/HEAD/tree/trunk/docutils/ + +.. confval:: smartquotes_excludes + + This is a ``dict`` whose default is:: + + {'languages': ['ja'], 'builders': ['man', 'text']} + + Each entry gives a sufficient condition to ignore the + :confval:`smartquotes` setting and deactivate the Smart Quotes transform. + Accepted keys are as above ``'builders'`` or ``'languages'``. + The values are lists. + + .. note:: Currently, in case of invocation of :program:`make` with multiple + targets, the first target name is the only one which is tested against + the ``'builders'`` entry and it decides for all. Also, a ``make text`` + following ``make html`` needs to be issued in the form ``make text + O="-E"`` to force re-parsing of source files, as the cached ones are + already transformed. On the other hand the issue does not arise with + direct usage of :program:`sphinx-build` as it caches + (in its default usage) the parsed source files in per builder locations. + + .. versionadded:: 1.6.6 + .. confval:: tls_verify If true, Sphinx verifies server certifications. Default is ``True``. @@ -784,15 +841,11 @@ that use Sphinx's HTMLWriter class. .. confval:: html_use_smartypants - If true, `SmartyPants `_ - will be used to convert quotes and dashes to typographically correct + If true, quotes and dashes are converted to typographically correct entities. Default: ``True``. .. deprecated:: 1.6 - To disable or customize smart quotes, use the Docutils configuration file - (``docutils.conf``) instead to set there its `smart_quotes option`_. - - .. _`smart_quotes option`: http://docutils.sourceforge.net/docs/user/config.html#smart-quotes + To disable smart quotes, use rather :confval:`smartquotes`. .. confval:: html_add_permalinks diff --git a/sphinx/config.py b/sphinx/config.py index 50f7c018c..a6632807c 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -134,6 +134,11 @@ class Config(object): tls_verify = (True, 'env'), tls_cacerts = (None, 'env'), + smartquotes = (True, 'env'), + smartquotes_action = ('qDe', 'env'), + smartquotes_excludes = ({'languages': ['ja'], + 'builders': ['man', 'text']}, + 'env'), ) # type: Dict[unicode, Tuple] def __init__(self, dirname, filename, overrides, tags): diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index 65a73b019..781382a30 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -20,8 +20,9 @@ import warnings from os import path from copy import copy from collections import defaultdict +from contextlib import contextmanager -from six import BytesIO, itervalues, class_types, next +from six import BytesIO, itervalues, class_types, next, iteritems from six.moves import cPickle as pickle from docutils.io import NullOutput @@ -46,7 +47,7 @@ from sphinx.util.parallel import ParallelTasks, parallel_available, make_chunks from sphinx.util.websupport import is_commentable from sphinx.errors import SphinxError, ExtensionError from sphinx.locale import __ -from sphinx.transforms import SphinxTransformer +from sphinx.transforms import SphinxTransformer, SphinxSmartQuotes from sphinx.versioning import add_uids, merge_doctrees from sphinx.deprecation import RemovedInSphinx17Warning, RemovedInSphinx20Warning from sphinx.environment.adapters.indexentries import IndexEntries @@ -54,7 +55,7 @@ from sphinx.environment.adapters.toctree import TocTree if False: # For type annotation - from typing import Any, Callable, Dict, IO, Iterator, List, Pattern, Set, Tuple, Type, Union # NOQA + from typing import Any, Callable, Dict, IO, Iterator, List, Pattern, Set, Tuple, Type, Union, Generator # NOQA from docutils import nodes # NOQA from sphinx.application import Sphinx # NOQA from sphinx.builders import Builder # NOQA @@ -91,6 +92,22 @@ versioning_conditions = { } # type: Dict[unicode, Union[bool, Callable]] +@contextmanager +def sphinx_smartquotes_action(env): + # type: (BuildEnvironment) -> Generator + if not hasattr(SphinxSmartQuotes, 'smartquotes_action'): + # less than docutils-0.14 + yield + else: + # docutils-0.14 or above + try: + original = SphinxSmartQuotes.smartquotes_action + SphinxSmartQuotes.smartquotes_action = env.config.smartquotes_action + yield + finally: + SphinxSmartQuotes.smartquotes_action = original + + class NoUri(Exception): """Raised by get_relative_uri if there is no URI available.""" pass @@ -600,7 +617,8 @@ class BuildEnvironment(object): # remove all inventory entries for that file app.emit('env-purge-doc', self, docname) self.clear_doc(docname) - self.read_doc(docname, app) + with sphinx_smartquotes_action(self): + self.read_doc(docname, app) def _read_parallel(self, docnames, app, nproc): # type: (List[unicode], Sphinx, int) -> None @@ -612,8 +630,9 @@ class BuildEnvironment(object): def read_process(docs): # type: (List[unicode]) -> unicode self.app = app - for docname in docs: - self.read_doc(docname, app) + with sphinx_smartquotes_action(self): + for docname in docs: + self.read_doc(docname, app) # allow pickling self to send it back return BuildEnvironment.dumps(self) @@ -677,15 +696,26 @@ class BuildEnvironment(object): language = self.config.language or 'en' self.settings['language_code'] = language if 'smart_quotes' not in self.settings: - self.settings['smart_quotes'] = True + self.settings['smart_quotes'] = self.config.smartquotes if self.config.html_use_smartypants is not None: warnings.warn("html_use_smartypants option is deprecated. Smart " "quotes are on by default; if you want to disable " - "or customize them, use the smart_quotes option in " - "docutils.conf.", + "them, use the smartquotes option.", RemovedInSphinx17Warning) self.settings['smart_quotes'] = self.config.html_use_smartypants + # some conditions exclude smart quotes, overriding smart_quotes + for valname, vallist in iteritems(self.config.smartquotes_excludes): + if valname == 'builders': + # this will work only for checking first build target + if self.app.builder.name in vallist: + self.settings['smart_quotes'] = False + break + elif valname == 'languages': + if self.config.language in vallist: + self.settings['smart_quotes'] = False + break + # confirm selected language supports smart_quotes or not for tag in normalize_language_tag(language): if tag in smartchars.quotes: diff --git a/sphinx/io.py b/sphinx/io.py index 8365e22e0..6fcec2cd3 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -18,7 +18,7 @@ from sphinx.transforms import ( ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences, DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, SortIds, AutoNumbering, AutoIndexUpgrader, FilterSystemMessages, - UnreferencedFootnotesDetector + UnreferencedFootnotesDetector, SphinxSmartQuotes ) from sphinx.transforms.compact_bullet_list import RefOnlyBulletListTransform from sphinx.transforms.i18n import ( @@ -98,6 +98,16 @@ class SphinxStandaloneReader(SphinxBaseReader): RemoveTranslatableInline, PreserveTranslatableMessages, FilterSystemMessages, RefOnlyBulletListTransform, UnreferencedFootnotesDetector] + def __init__(self, app, parsers={}, *args, **kwargs): + SphinxBaseReader.__init__(self, app, parsers, *args, **kwargs) + self.smart_quotes = app.env.settings['smart_quotes'] + + def get_transforms(self): + transforms = SphinxBaseReader.get_transforms(self) + if self.smart_quotes: + transforms.append(SphinxSmartQuotes) + return transforms + class SphinxI18nReader(SphinxBaseReader): """ diff --git a/sphinx/parsers.py b/sphinx/parsers.py index b58eefa23..1aa16a45e 100644 --- a/sphinx/parsers.py +++ b/sphinx/parsers.py @@ -13,8 +13,6 @@ import docutils.parsers import docutils.parsers.rst from docutils.transforms.universal import SmartQuotes -from sphinx.transforms import SphinxSmartQuotes - if False: # For type annotation from typing import Any, Dict, List, Type # NOQA @@ -60,10 +58,11 @@ class RSTParser(docutils.parsers.rst.Parser): def get_transforms(self): # type: () -> List[Type[Transform]] - """Sphinx's reST parser replaces a transform class for smart-quotes by own's""" + """Sphinx's reST parser replaces a transform class for smart-quotes by own's + + refs: sphinx.io.SphinxStandaloneReader""" transforms = docutils.parsers.rst.Parser.get_transforms(self) transforms.remove(SmartQuotes) - transforms.append(SphinxSmartQuotes) return transforms From 0d824dfd41302bcea5d8de831bc5f1025c465c1d Mon Sep 17 00:00:00 2001 From: jfbu Date: Fri, 5 Jan 2018 15:06:38 +0100 Subject: [PATCH 221/275] Update CHANGES for PR #4360 --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index 181271868..80f8c4faa 100644 --- a/CHANGES +++ b/CHANGES @@ -18,6 +18,10 @@ Features added :ref:`LaTeX 'sphinxsetup' ` key (refs: #4285) * Easier customizability of LaTeX macros involved in rendering of code-blocks * Show traceback if conf.py raises an exception (refs: #4369) +* Add :confval:`smartquotes` to disable smart quotes through ``conf.py`` + (refs: #3967) +* Add :confval:`smartquotes_action` and :confval:`smartquotes_excludes` + (refs: #4142, #4357) Bugs fixed ---------- From 3736768a59dd1d13b205b894385eadd9791b1ac4 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 6 Jan 2018 13:22:47 +0900 Subject: [PATCH 222/275] test: Reduce DeprecationWarning on testing (from docutils) --- setup.cfg | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/setup.cfg b/setup.cfg index 0ce6282dc..c19d0d518 100644 --- a/setup.cfg +++ b/setup.cfg @@ -44,6 +44,10 @@ incremental = True check_untyped_defs = True warn_unused_ignores = True +[tool:pytest] +filterwarnings = + ignore::DeprecationWarning:docutils.io + [coverage:run] branch = True source = sphinx From fdf0a33eab4d73a36582acbf3c91530f78bf35ef Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 6 Jan 2018 16:09:53 +0900 Subject: [PATCH 223/275] test: Remove PYTHONWARNINGS from travis.yml PYTHONWARNINGS is now controled at tox.ini. So this envvar is no longer referred. --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2bd437436..e51523c19 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,6 @@ cache: pip env: global: - PYTHONFAULTHANDLER=x - - PYTHONWARNINGS=all - SKIP_LATEX_BUILD=1 matrix: From 23533e48b22c4187d172ae1d8bf42a21f5c81f2a Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 6 Jan 2018 16:34:51 +0900 Subject: [PATCH 224/275] Update PYTHONWARNINGS on tox.ini to reduce meaningless warnings --- tests/conftest.py | 9 --------- tox.ini | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 6cb239d9f..9fb06edab 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -35,14 +35,6 @@ def pytest_report_header(config): sys.version.split()[0]) -def _filter_warnings(): - def ignore(**kwargs): warnings.filterwarnings('ignore', **kwargs) - - ignore(category=DeprecationWarning, module='site') # virtualenv - ignore(category=PendingDeprecationWarning, module=r'_pytest\..*') - ignore(category=ImportWarning, module='pkgutil') - - def _initialize_test_directory(session): testroot = os.path.join(str(session.config.rootdir), 'tests') tempdir = os.path.abspath(os.getenv('SPHINX_TEST_TEMPDIR', @@ -58,5 +50,4 @@ def _initialize_test_directory(session): def pytest_sessionstart(session): - _filter_warnings() _initialize_test_directory(session) diff --git a/tox.ini b/tox.ini index 2862fd755..810b76f0c 100644 --- a/tox.ini +++ b/tox.ini @@ -21,7 +21,7 @@ deps = du13: docutils==0.13.1 du14: docutils==0.14 setenv = - PYTHONWARNINGS = all,ignore::ImportWarning:pkgutil + PYTHONWARNINGS = all,ignore::ImportWarning:pkgutil,ignore::ImportWarning:importlib._bootstrap,ignore::ImportWarning:importlib._bootstrap_external,ignore::ImportWarning:pytest_cov.plugin,ignore::DeprecationWarning:site,ignore::DeprecationWarning:_pytest.assertion.rewrite,ignore::DeprecationWarning:_pytest.fixtures SPHINX_TEST_TEMPDIR = {envdir}/testbuild commands= pytest -Wall --durations 25 {posargs} From c1b3efe203752407f37770910da4d082b2b32d52 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 6 Jan 2018 21:01:04 +0900 Subject: [PATCH 225/275] Fix mypy violation --- sphinx/ext/autodoc/importer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py index b22af9ff5..cc68436cd 100644 --- a/sphinx/ext/autodoc/importer.py +++ b/sphinx/ext/autodoc/importer.py @@ -151,7 +151,7 @@ def import_module(modname, warningiserror=False): def import_object(modname, objpath, objtype='', attrgetter=safe_getattr, warningiserror=False): - # type: (str, List[unicode], str, Callable[[Any, unicode], Any]) -> Any + # type: (str, List[unicode], str, Callable[[Any, unicode], Any], bool) -> Any if objpath: logger.debug('[autodoc] from %s import %s', modname, '.'.join(objpath)) else: From c2a7984e05943f33e0ce367baad1fc7855baf5f3 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 6 Jan 2018 22:10:15 +0900 Subject: [PATCH 226/275] Fix enum34 members are treated as inherited member --- sphinx/ext/autodoc/importer.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py index cc68436cd..101cb930f 100644 --- a/sphinx/ext/autodoc/importer.py +++ b/sphinx/ext/autodoc/importer.py @@ -19,7 +19,7 @@ from types import FunctionType, MethodType, ModuleType from six import PY2 from sphinx.util import logging -from sphinx.util.inspect import safe_getattr +from sphinx.util.inspect import isenumclass, safe_getattr if False: # For type annotation @@ -206,6 +206,12 @@ def get_object_members(subject, objpath, attrgetter, analyzer=None): # the members directly defined in the class obj_dict = attrgetter(subject, '__dict__', {}) + # Py34 doesn't have enum members in __dict__. + if sys.version_info[:2] == (3, 4) and isenumclass(subject): + obj_dict = dict(obj_dict) + for name, value in subject.__members__.items(): + obj_dict[name] = value + members = {} for name in dir(subject): try: From e1d8615ce4bd2e3c68f2361447e4e45bbff65d18 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 7 Jan 2018 00:05:48 +0900 Subject: [PATCH 227/275] Don't use add_documenter() in sphinx-autogen --- sphinx/ext/autosummary/generate.py | 32 +++++++++++++++++++----------- tests/test_ext_autosummary.py | 2 +- tests/test_templating.py | 4 ++-- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index 2873b6082..cfaa4a4ca 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -31,9 +31,9 @@ from jinja2.sandbox import SandboxedEnvironment from sphinx import __display_version__ from sphinx import package_dir -from sphinx.ext.autodoc import add_documenter from sphinx.ext.autosummary import import_by_name, get_documenter from sphinx.jinja2glue import BuiltinTemplateLoader +from sphinx.registry import SphinxComponentRegistry from sphinx.util.osutil import ensuredir from sphinx.util.inspect import safe_getattr from sphinx.util.rst import escape as rst_escape @@ -47,20 +47,26 @@ if False: from sphinx.environment import BuildEnvironment # NOQA -def setup_documenters(): +class DummyApplication(object): + """Dummy Application class for sphinx-autogen command.""" + + def __init__(self): + self.registry = SphinxComponentRegistry() + + +def setup_documenters(app): from sphinx.ext.autodoc import ( ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter, FunctionDocumenter, MethodDocumenter, AttributeDocumenter, InstanceAttributeDocumenter ) - add_documenter(ModuleDocumenter) - add_documenter(ClassDocumenter) - add_documenter(ExceptionDocumenter) - add_documenter(DataDocumenter) - add_documenter(FunctionDocumenter) - add_documenter(MethodDocumenter) - add_documenter(AttributeDocumenter) - add_documenter(InstanceAttributeDocumenter) + documenters = [ + ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter, + FunctionDocumenter, MethodDocumenter, AttributeDocumenter, + InstanceAttributeDocumenter + ] + for documenter in documenters: + app.registry.add_documenter(documenter.objtype, documenter) def _simple_info(msg): @@ -395,12 +401,14 @@ The format of the autosummary directive is documented in the def main(argv=sys.argv[1:]): # type: (List[str]) -> None - setup_documenters() + app = DummyApplication() + setup_documenters(app) args = get_parser().parse_args(argv) generate_autosummary_docs(args.source_file, args.output_dir, '.' + args.suffix, template_dir=args.templates, - imported_members=args.imported_members) + imported_members=args.imported_members, + app=app) if __name__ == '__main__': diff --git a/tests/test_ext_autosummary.py b/tests/test_ext_autosummary.py index 1035d3b3b..000ee3af4 100644 --- a/tests/test_ext_autosummary.py +++ b/tests/test_ext_autosummary.py @@ -60,9 +60,9 @@ def test_mangle_signature(): def test_get_items_summary(make_app, app_params): import sphinx.ext.autosummary import sphinx.ext.autosummary.generate - sphinx.ext.autosummary.generate.setup_documenters() args, kwargs = app_params app = make_app(*args, **kwargs) + sphinx.ext.autosummary.generate.setup_documenters(app) # monkey-patch Autosummary.get_items so we can easily get access to it's # results.. orig_get_items = sphinx.ext.autosummary.Autosummary.get_items diff --git a/tests/test_templating.py b/tests/test_templating.py index 88a196e77..550b3bc7d 100644 --- a/tests/test_templating.py +++ b/tests/test_templating.py @@ -15,9 +15,9 @@ from sphinx.ext.autosummary.generate import setup_documenters @pytest.mark.sphinx('html', testroot='templating') def test_layout_overloading(make_app, app_params): - setup_documenters() args, kwargs = app_params app = make_app(*args, **kwargs) + setup_documenters(app) app.builder.build_update() result = (app.outdir / 'contents.html').text(encoding='utf-8') @@ -27,9 +27,9 @@ def test_layout_overloading(make_app, app_params): @pytest.mark.sphinx('html', testroot='templating') def test_autosummary_class_template_overloading(make_app, app_params): - setup_documenters() args, kwargs = app_params app = make_app(*args, **kwargs) + setup_documenters(app) app.builder.build_update() result = (app.outdir / 'generated' / 'sphinx.application.TemplateBridge.html').text( From 356765ee769fb26c07f98b887cff16ededf7ca0b Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 7 Jan 2018 00:39:41 +0900 Subject: [PATCH 228/275] Fix mypy violation --- sphinx/ext/autosummary/generate.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index cfaa4a4ca..aeffcb564 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -51,10 +51,12 @@ class DummyApplication(object): """Dummy Application class for sphinx-autogen command.""" def __init__(self): + # type: () -> None self.registry = SphinxComponentRegistry() def setup_documenters(app): + # type: (Any) -> None from sphinx.ext.autodoc import ( ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter, FunctionDocumenter, MethodDocumenter, AttributeDocumenter, @@ -91,7 +93,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst', warn=_simple_warn, info=_simple_info, base_path=None, builder=None, template_dir=None, imported_members=False, app=None): - # type: (List[unicode], unicode, unicode, Callable, Callable, unicode, Builder, unicode, bool) -> None # NOQA + # type: (List[unicode], unicode, unicode, Callable, Callable, unicode, Builder, unicode, bool, Any) -> None # NOQA showed_sources = list(sorted(sources)) if len(showed_sources) > 20: From 7162fcdff9d76b6923b01c953e32d3949a767548 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 7 Jan 2018 00:51:45 +0900 Subject: [PATCH 229/275] Fix typo --- sphinx/application.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/application.py b/sphinx/application.py index 07b8539a9..1c97fec15 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -649,7 +649,7 @@ class Sphinx(object): def add_autodoc_attrgetter(self, typ, getter): # type: (Type, Callable[[Any, unicode, Any], Any]) -> None logger.debug('[app] adding autodoc attrgetter: %r', (typ, getter)) - self.registy.add_autodoc_attrgetter(typ, getter) + self.registry.add_autodoc_attrgetter(typ, getter) def add_search_language(self, cls): # type: (Any) -> None From bbfcb2443d511bf790d4fe62ed01079b074fef4b Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sat, 6 Jan 2018 17:49:27 +0100 Subject: [PATCH 230/275] cleanup formatting of some sidebar items --- doc/_templates/indexsidebar.html | 10 ++++---- doc/_themes/sphinx13/static/sphinx13.css | 30 ++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/doc/_templates/indexsidebar.html b/doc/_templates/indexsidebar.html index 6359921a5..b07ef2033 100644 --- a/doc/_templates/indexsidebar.html +++ b/doc/_templates/indexsidebar.html @@ -20,12 +20,14 @@ Index, or install it with:{%endtrans%}

{%trans%}Questions? Suggestions?{%endtrans%}

{%trans%}Join the sphinx-users mailing list on Google Groups:{%endtrans%}

+
- - + class="subscribeform"> + +
+

{%trans%}or come to the #sphinx-doc channel on FreeNode.{%endtrans%}

{%trans%}You can also open an issue at the tracker.{%endtrans%}

diff --git a/doc/_themes/sphinx13/static/sphinx13.css b/doc/_themes/sphinx13/static/sphinx13.css index 6bdc5a96c..24a33fba7 100644 --- a/doc/_themes/sphinx13/static/sphinx13.css +++ b/doc/_themes/sphinx13/static/sphinx13.css @@ -140,11 +140,37 @@ div.sphinxsidebar .logo img { vertical-align: middle; } +div.subscribeformwrapper { + display: block; + overflow: auto; + margin-bottom: 1.2em; +} + div.sphinxsidebar input { border: 1px solid #aaa; font-family: 'Open Sans', 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva', 'Verdana', sans-serif; - font-size: 1em; +} + +div.sphinxsidebar .subscribeform { + margin-top: 0; +} + +div.sphinxsidebar .subscribeform input { + border: 1px solid #aaa; + font-size: 0.9em; + float: left; + padding: 0.25em 0.5em; + box-sizing: border-box; +} + +div.sphinxsidebar .subscribeform input[type="text"] { + width: 60%; +} + +div.sphinxsidebar .subscribeform input[type="submit"] { + width: 40%; + border-left: none; } div.sphinxsidebar h3 { @@ -281,7 +307,7 @@ tt { border: 1px solid #ddd; border-radius: 2px; color: #333; - padding: 1px; + padding: 1px 0.2em; } tt.descname, tt.descclassname, tt.xref { From 1498d1359056a80d474266708e3ff372adb40994 Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sat, 6 Jan 2018 19:29:48 +0100 Subject: [PATCH 231/275] updates to conf.py generated by sphinx-quickstart --- sphinx/templates/quickstart/conf.py_t | 39 ++++++++++++--------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/sphinx/templates/quickstart/conf.py_t b/sphinx/templates/quickstart/conf.py_t index c42861c28..a1c00f8c7 100644 --- a/sphinx/templates/quickstart/conf.py_t +++ b/sphinx/templates/quickstart/conf.py_t @@ -6,14 +6,11 @@ # {{ project }} documentation build configuration file, created by # sphinx-quickstart on {{ now }}. # -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/stable/config + +# -- Path setup ----------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -33,6 +30,18 @@ sys.path.insert(0, u'{{ module_path }}') {% endif -%} {% endif %} +# -- Project information -------------------------------------------------- + +project = u'{{ project_str }}' +copyright = u'{{ copyright_str }}' +author = u'{{ author_str }}' + +# The short X.Y version +version = u'{{ version_str }}' +# The full version, including alpha/beta/rc tags +release = u'{{ release_str }}' + + # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. @@ -60,20 +69,6 @@ source_suffix = '{{ suffix }}' # The master toctree document. master_doc = '{{ master_str }}' -# General information about the project. -project = u'{{ project_str }}' -copyright = u'{{ copyright_str }}' -author = u'{{ author_str }}' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = u'{{ version_str }}' -# The full version, including alpha/beta/rc tags. -release = u'{{ release_str }}' - # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # From 2ae7f26fe531c29cedfa01e2f0c3595a4c680972 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 7 Jan 2018 12:09:41 +0900 Subject: [PATCH 232/275] test: Adjust testcase for #3962 --- tests/test_ext_apidoc.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_ext_apidoc.py b/tests/test_ext_apidoc.py index 83951bf03..2bfc8016e 100644 --- a/tests/test_ext_apidoc.py +++ b/tests/test_ext_apidoc.py @@ -191,7 +191,7 @@ def test_extension_parsed(make_app, apidoc): @pytest.mark.apidoc( - coderoot='test-apidoc-toc', + coderoot='test-apidoc-toc/mypackage', options=["--implicit-namespaces"], ) def test_toc_all_references_should_exist_pep420_enabled(make_app, apidoc): @@ -222,7 +222,7 @@ def test_toc_all_references_should_exist_pep420_enabled(make_app, apidoc): @pytest.mark.apidoc( - coderoot='test-apidoc-toc', + coderoot='test-apidoc-toc/mypackage', ) def test_toc_all_references_should_exist_pep420_disabled(make_app, apidoc): """All references in toc should exist. This test doesn't say if From 2484819e96f6616479d4822374f7d4cdf743e31e Mon Sep 17 00:00:00 2001 From: MURAOKA Yusuke Date: Sun, 7 Jan 2018 20:04:53 +0900 Subject: [PATCH 233/275] Fix creating build directory for unknown build target --- sphinx/application.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index 9195f11af..b4fef818f 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -157,10 +157,6 @@ class Sphinx(object): # status code for command-line application self.statuscode = 0 - if not path.isdir(outdir): - logger.info('making output directory...') - ensuredir(outdir) - # read config self.tags = Tags(tags) self.config = Config(confdir, CONFIG_FILENAME, @@ -197,6 +193,10 @@ class Sphinx(object): # preload builder module (before init config values) self.preload_builder(buildername) + if not path.isdir(outdir): + logger.info('making output directory...') + ensuredir(outdir) + # the config file itself can be an extension if self.config.setup: self._setting_up_extension = ['conf.py'] From cc3abba171ed37dc3377b047788894733944c4d5 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sun, 7 Jan 2018 09:08:29 -0800 Subject: [PATCH 234/275] Prefer https & readthedocs.io instead of readthedocs.org for links Read the Docs moved hosting to readthedocs.io instead of readthedocs.org. Fix all links in the project. For additional details, see: https://blog.readthedocs.com/securing-subdomains/ > Starting today, Read the Docs will start hosting projects from subdomains on > the domain readthedocs.io, instead of on readthedocs.org. This change > addresses some security concerns around site cookies while hosting user > generated data on the same domain as our dashboard. --- EXAMPLES | 4 ++-- doc/_templates/index.html | 6 +++--- doc/develop.rst | 2 +- doc/ext/thirdparty.rst | 2 +- doc/faq.rst | 2 +- doc/intro.rst | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/EXAMPLES b/EXAMPLES index 6bf6d0e31..edbf48903 100644 --- a/EXAMPLES +++ b/EXAMPLES @@ -93,7 +93,7 @@ Documentation using the classic theme * simuPOP: http://simupop.sourceforge.net/manual_release/build/userGuide.html (customized) * Sprox: http://sprox.org/ (customized) * SymPy: http://docs.sympy.org/ -* TurboGears: https://turbogears.readthedocs.org/ (customized) +* TurboGears: https://turbogears.readthedocs.io/ (customized) * tvtk: http://docs.enthought.com/mayavi/tvtk/ * Varnish: https://www.varnish-cache.org/docs/ (customized, alabaster for index) * Waf: https://waf.io/apidocs/ @@ -259,7 +259,7 @@ Documentation using sphinx_bootstrap_theme * Bootstrap Theme: https://ryan-roemer.github.io/sphinx-bootstrap-theme/ * C/C++ Software Development with Eclipse: http://eclipsebook.in/ * Dataverse: http://guides.dataverse.org/ -* e-cidadania: http://e-cidadania.readthedocs.org/ +* e-cidadania: https://e-cidadania.readthedocs.io/ * Hangfire: http://docs.hangfire.io/ * Hedge: https://documen.tician.de/hedge/ * ObsPy: https://docs.obspy.org/ diff --git a/doc/_templates/index.html b/doc/_templates/index.html index b4bdb5985..5a8a2f025 100644 --- a/doc/_templates/index.html +++ b/doc/_templates/index.html @@ -74,9 +74,9 @@

{%trans%} You can also download PDF/EPUB versions of the Sphinx documentation: - a PDF version generated from + a PDF version generated from the LaTeX Sphinx produces, and - a EPUB version. + a EPUB version. {%endtrans%}

@@ -106,7 +106,7 @@

{%trans%}Hosting{%endtrans%}

{%trans%}Need a place to host your Sphinx docs? - readthedocs.org hosts a lot of Sphinx docs + readthedocs.org hosts a lot of Sphinx docs already, and integrates well with projects' source control. It also features a powerful built-in search that exceeds the possibilities of Sphinx' JavaScript-based offline search.{%endtrans%}

diff --git a/doc/develop.rst b/doc/develop.rst index 4fc7792f7..19ca81ef9 100644 --- a/doc/develop.rst +++ b/doc/develop.rst @@ -138,7 +138,7 @@ own extensions. .. _cmakedomain: https://bitbucket.org/klorenz/sphinxcontrib-cmakedomain .. _GNU Make: http://www.gnu.org/software/make/ .. _makedomain: https://bitbucket.org/klorenz/sphinxcontrib-makedomain -.. _inlinesyntaxhighlight: http://sphinxcontrib-inlinesyntaxhighlight.readthedocs.org +.. _inlinesyntaxhighlight: https://sphinxcontrib-inlinesyntaxhighlight.readthedocs.io/ .. _CMake: https://cmake.org .. _domaintools: https://bitbucket.org/klorenz/sphinxcontrib-domaintools .. _restbuilder: https://pypi.python.org/pypi/sphinxcontrib-restbuilder diff --git a/doc/ext/thirdparty.rst b/doc/ext/thirdparty.rst index 6304e4af3..40c24246a 100644 --- a/doc/ext/thirdparty.rst +++ b/doc/ext/thirdparty.rst @@ -6,7 +6,7 @@ repository. It is open for anyone who wants to maintain an extension publicly; just send a short message asking for write permissions. There are also several extensions hosted elsewhere. The `Sphinx extension -survey `__ contains a +survey `__ contains a comprehensive list. If you write an extension that you think others will find useful or you think diff --git a/doc/faq.rst b/doc/faq.rst index 1ae9a7792..fe3173749 100644 --- a/doc/faq.rst +++ b/doc/faq.rst @@ -58,7 +58,7 @@ Read the Docs Sphinx. They will host sphinx documentation, along with supporting a number of other features including version support, PDF generation, and more. The `Getting Started - `_ + `_ guide is a good place to start. Epydoc diff --git a/doc/intro.rst b/doc/intro.rst index d3328a5ea..d3b191700 100644 --- a/doc/intro.rst +++ b/doc/intro.rst @@ -17,7 +17,7 @@ docs have a look at `Epydoc `_, which also understands reST. For a great "introduction" to writing docs in general -- the whys and hows, see -also `Write the docs `_, written by Eric +also `Write the docs `_, written by Eric Holscher. .. _rinohtype: https://github.com/brechtm/rinohtype From e015ce2a0fdc7dc2640961d962ea4e153c5ad00c Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 8 Jan 2018 09:36:35 +0900 Subject: [PATCH 235/275] Update CHANGES for PR #4389 --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 040f95e1c..252804ef3 100644 --- a/CHANGES +++ b/CHANGES @@ -13,6 +13,7 @@ Incompatible changes * #3929: apidoc: Move sphinx.apidoc to sphinx.ext.apidoc * #4226: apidoc: Generate new style makefile (make-mode) * #4274: sphinx-build returns 2 as an exit code on argument error +* #4389: output directory will be created after loading extensions Deprecated ---------- @@ -55,6 +56,7 @@ Features added code-blocks * #947: autodoc now supports ignore-module-all to ignore a module's ``__all__`` * #4332: Let LaTeX obey :confval:`math_numfig` for equation numbering +* #4093: sphinx-build creates empty directories for unknown targets/builders Features removed From db415ba05c974e13ad36d5a385dbc2b552272651 Mon Sep 17 00:00:00 2001 From: Joel Nothman Date: Mon, 8 Jan 2018 13:09:29 +1100 Subject: [PATCH 236/275] Avoid duplicate calls to autodoc-process-docstring (#4198) --- sphinx/ext/autosummary/__init__.py | 2 +- tests/test_ext_autosummary.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 3dded11ff..d4fd80467 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -325,7 +325,7 @@ class Autosummary(Directive): # -- Grab the summary documenter.add_content(None) - doc = list(documenter.process_doc([self.result.data])) + doc = self.result.data while doc and not doc[0].strip(): doc.pop(0) diff --git a/tests/test_ext_autosummary.py b/tests/test_ext_autosummary.py index 0aea99df6..8624153e2 100644 --- a/tests/test_ext_autosummary.py +++ b/tests/test_ext_autosummary.py @@ -73,6 +73,10 @@ def test_get_items_summary(app, status, warning): def handler(app, what, name, obj, options, lines): assert isinstance(lines, list) + + # ensure no docstring is processed twice: + assert 'THIS HAS BEEN HANDLED' not in lines + lines.append('THIS HAS BEEN HANDLED') app.connect('autodoc-process-docstring', handler) sphinx.ext.autosummary.Autosummary.get_items = new_get_items From b5edde474db6440f77b0e24fac0203a863429aee Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Mon, 8 Jan 2018 11:18:36 +0900 Subject: [PATCH 237/275] update CHANGES for #4198 --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index 252804ef3..d841f2371 100644 --- a/CHANGES +++ b/CHANGES @@ -103,6 +103,8 @@ Bugs fixed one of figures and tables * #4330: PDF 'howto' documents have an incoherent default LaTeX tocdepth counter setting +* #4198: autosummary emits multiple 'autodoc-process-docstring' event. Thanks + to Joel Nothman. Testing -------- From 7ba54500fcedce47f7cbe29732d246cc84fd2462 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 8 Jan 2018 11:59:50 +0900 Subject: [PATCH 238/275] Fix #4183: doctest: ``:pyversion:`` option also follows PEP-440 specification --- CHANGES | 7 ++++++- doc/ext/doctest.rst | 18 +++++++++++++++--- setup.py | 1 + sphinx/ext/doctest.py | 39 ++++++++++++++++----------------------- tests/test_ext_doctest.py | 39 +++++++++++++++++++++++++-------------- 5 files changed, 63 insertions(+), 41 deletions(-) diff --git a/CHANGES b/CHANGES index 252804ef3..0133d40de 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,11 @@ Release 1.7 (in development) ============================ +Dependencies +------------ + +* Add ``packaging`` package + Incompatible changes -------------------- @@ -57,7 +62,7 @@ Features added * #947: autodoc now supports ignore-module-all to ignore a module's ``__all__`` * #4332: Let LaTeX obey :confval:`math_numfig` for equation numbering * #4093: sphinx-build creates empty directories for unknown targets/builders - +* #4183: doctest: ``:pyversion:`` option also follows PEP-440 specification Features removed ---------------- diff --git a/doc/ext/doctest.rst b/doc/ext/doctest.rst index d1cb3c31d..62221bf04 100644 --- a/doc/ext/doctest.rst +++ b/doc/ext/doctest.rst @@ -80,12 +80,24 @@ a comma-separated list of group names. .. doctest:: :pyversion: > 3.3 - The supported operands are ``<``, ``<=``, ``==``, ``>=``, ``>``, and - comparison is performed by `distutils.version.LooseVersion - `__. + The following operands are supported: + + * ``~=``: Compatible release clause + * ``==``: Version matching clause + * ``!=``: Version exclusion clause + * ``<=``, ``>=``: Inclusive ordered comparison clause + * ``<``, ``>``: Exclusive ordered comparison clause + * ``===``: Arbitrary equality clause. + + ``pyversion`` option is followed `PEP-440: Version Specifiers + `__. .. versionadded:: 1.6 + .. versionchanged:: 1.7 + + Supported PEP-440 operands and notations + Note that like with standard doctests, you have to use ```` to signal a blank line in the expected output. The ```` is removed when building presentation output (HTML, LaTeX etc.). diff --git a/setup.py b/setup.py index 6b7de9129..f35e5f88d 100644 --- a/setup.py +++ b/setup.py @@ -26,6 +26,7 @@ requires = [ 'imagesize', 'requests>=2.0.0', 'setuptools', + 'packaging', 'sphinxcontrib-websupport', ] diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py index e0ce050f7..948ddfec8 100644 --- a/sphinx/ext/doctest.py +++ b/sphinx/ext/doctest.py @@ -20,7 +20,8 @@ from os import path import doctest from six import itervalues, StringIO, binary_type, text_type, PY2 -from distutils.version import LooseVersion +from packaging.specifiers import SpecifierSet, InvalidSpecifier +from packaging.version import Version from docutils import nodes from docutils.parsers.rst import Directive, directives @@ -57,28 +58,23 @@ else: return text -def compare_version(ver1, ver2, operand): - # type: (unicode, unicode, unicode) -> bool - """Compare `ver1` to `ver2`, relying on `operand`. +def is_allowed_version(spec, version): + # type: (unicode, unicode) -> bool + """Check `spec` satisfies `version` or not. + + This obeys PEP-440 specifiers: + https://www.python.org/dev/peps/pep-0440/#version-specifiers Some examples: - >>> compare_version('3.3', '3.5', '<=') + >>> is_allowed_version('3.3', '<=3.5') True - >>> compare_version('3.3', '3.2', '<=') + >>> is_allowed_version('3.3', '<=3.2') False - >>> compare_version('3.3a0', '3.3', '<=') + >>> is_allowed_version('3.3', '>3.2, <4.0') True """ - if operand not in ('<=', '<', '==', '>=', '>'): - raise ValueError("'%s' is not a valid operand.") - v1 = LooseVersion(ver1) - v2 = LooseVersion(ver2) - return ((operand == '<=' and (v1 <= v2)) or - (operand == '<' and (v1 < v2)) or - (operand == '==' and (v1 == v2)) or - (operand == '>=' and (v1 >= v2)) or - (operand == '>' and (v1 > v2))) + return Version(version) in SpecifierSet(spec) # set up the necessary directives @@ -143,16 +139,13 @@ class TestDirective(Directive): node['options'][flag] = (option[0] == '+') if self.name == 'doctest' and 'pyversion' in self.options: try: - option = self.options['pyversion'] - # :pyversion: >= 3.6 --> operand='>=', option_version='3.6' - operand, option_version = [item.strip() for item in option.split()] - running_version = platform.python_version() - if not compare_version(running_version, option_version, operand): + spec = self.options['pyversion'] + if not is_allowed_version(spec, platform.python_version()): flag = doctest.OPTIONFLAGS_BY_NAME['SKIP'] node['options'][flag] = True # Skip the test - except ValueError: + except InvalidSpecifier: self.state.document.reporter.warning( - _("'%s' is not a valid pyversion option") % option, + _("'%s' is not a valid pyversion option") % spec, line=self.lineno) return [node] diff --git a/tests/test_ext_doctest.py b/tests/test_ext_doctest.py index 020357879..7d907d086 100644 --- a/tests/test_ext_doctest.py +++ b/tests/test_ext_doctest.py @@ -9,7 +9,9 @@ :license: BSD, see LICENSE for details. """ import pytest -from sphinx.ext.doctest import compare_version +from sphinx.ext.doctest import is_allowed_version +from packaging.version import InvalidVersion +from packaging.specifiers import InvalidSpecifier cleanup_called = 0 @@ -26,19 +28,28 @@ def test_build(app, status, warning): assert cleanup_called == 3, 'testcleanup did not get executed enough times' -def test_compare_version(): - assert compare_version('3.3', '3.4', '<') is True - assert compare_version('3.3', '3.2', '<') is False - assert compare_version('3.3', '3.4', '<=') is True - assert compare_version('3.3', '3.2', '<=') is False - assert compare_version('3.3', '3.3', '==') is True - assert compare_version('3.3', '3.4', '==') is False - assert compare_version('3.3', '3.2', '>=') is True - assert compare_version('3.3', '3.4', '>=') is False - assert compare_version('3.3', '3.2', '>') is True - assert compare_version('3.3', '3.4', '>') is False - with pytest.raises(ValueError): - compare_version('3.3', '3.4', '+') +def test_is_allowed_version(): + assert is_allowed_version('<3.4', '3.3') is True + assert is_allowed_version('<3.4', '3.3') is True + assert is_allowed_version('<3.2', '3.3') is False + assert is_allowed_version('<=3.4', '3.3') is True + assert is_allowed_version('<=3.2', '3.3') is False + assert is_allowed_version('==3.3', '3.3') is True + assert is_allowed_version('==3.4', '3.3') is False + assert is_allowed_version('>=3.2', '3.3') is True + assert is_allowed_version('>=3.4', '3.3') is False + assert is_allowed_version('>3.2', '3.3') is True + assert is_allowed_version('>3.4', '3.3') is False + assert is_allowed_version('~=3.4', '3.4.5') is True + assert is_allowed_version('~=3.4', '3.5.0') is True + + # invalid spec + with pytest.raises(InvalidSpecifier): + is_allowed_version('&3.4', '3.5') + + # invalid version + with pytest.raises(InvalidVersion): + is_allowed_version('>3.4', 'Sphinx') def cleanup_call(): From 273f834157a90806e0cd2031e8974c43f9787a6f Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 8 Jan 2018 12:19:08 +0900 Subject: [PATCH 239/275] Fix #4081: Warnings and errors colored the same when building --- CHANGES | 2 +- sphinx/util/logging.py | 2 +- tests/test_util_logging.py | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index d841f2371..6227328c4 100644 --- a/CHANGES +++ b/CHANGES @@ -58,7 +58,6 @@ Features added * #4332: Let LaTeX obey :confval:`math_numfig` for equation numbering * #4093: sphinx-build creates empty directories for unknown targets/builders - Features removed ---------------- @@ -105,6 +104,7 @@ Bugs fixed setting * #4198: autosummary emits multiple 'autodoc-process-docstring' event. Thanks to Joel Nothman. +* #4081: Warnings and errors colored the same when building Testing -------- diff --git a/sphinx/util/logging.py b/sphinx/util/logging.py index ec81f02d7..04bf91830 100644 --- a/sphinx/util/logging.py +++ b/sphinx/util/logging.py @@ -53,7 +53,7 @@ VERBOSITY_MAP.update({ COLOR_MAP = defaultdict(lambda: 'blue') # type: Dict[int, unicode] COLOR_MAP.update({ logging.ERROR: 'darkred', - logging.WARNING: 'darkred', + logging.WARNING: 'red', logging.DEBUG: 'darkgray', }) diff --git a/tests/test_util_logging.py b/tests/test_util_logging.py index e909c2dcf..48eed82b0 100644 --- a/tests/test_util_logging.py +++ b/tests/test_util_logging.py @@ -183,7 +183,7 @@ def test_warning_location(app, status, warning): assert 'index.txt:10: WARNING: message2' in warning.getvalue() logger.warning('message3', location=None) - assert colorize('darkred', 'WARNING: message3') in warning.getvalue() + assert colorize('red', 'WARNING: message3') in warning.getvalue() node = nodes.Node() node.source, node.line = ('index.txt', 10) @@ -200,7 +200,7 @@ def test_warning_location(app, status, warning): node.source, node.line = (None, None) logger.warning('message7', location=node) - assert colorize('darkred', 'WARNING: message7') in warning.getvalue() + assert colorize('red', 'WARNING: message7') in warning.getvalue() def test_pending_warnings(app, status, warning): @@ -236,7 +236,7 @@ def test_colored_logs(app, status, warning): assert colorize('darkgray', 'message1') in status.getvalue() assert 'message2\n' in status.getvalue() # not colored assert 'message3\n' in status.getvalue() # not colored - assert colorize('darkred', 'WARNING: message4') in warning.getvalue() + assert colorize('red', 'WARNING: message4') in warning.getvalue() assert 'WARNING: message5\n' in warning.getvalue() # not colored assert colorize('darkred', 'WARNING: message6') in warning.getvalue() From 9a6ad38e2d23a7285d15d967e9d1eb5dcd2e2cfb Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 8 Jan 2018 14:12:44 +0900 Subject: [PATCH 240/275] Rename AutoDirective (and make alias) --- sphinx/ext/autodoc/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 68f78eeb2..4de899384 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -1477,7 +1477,7 @@ class InstanceAttributeDocumenter(AttributeDocumenter): AttributeDocumenter.add_content(self, more_content, no_docstring=True) -class AutoDirective(object): +class AutodocRegistry(object): """ A registry of Documenters and attrgetters. @@ -1499,6 +1499,9 @@ class AutoDirective(object): _special_attrgetters = {} # type: Dict[Type, Callable] +AutoDirective = AutodocRegistry # for backward compatibility + + def add_documenter(cls): # type: (Type[Documenter]) -> None """Register a new Documenter.""" From f717f2dd64ed427ba68e08728f6757cf34492777 Mon Sep 17 00:00:00 2001 From: Guillaume Gay Date: Mon, 8 Jan 2018 08:49:22 +0100 Subject: [PATCH 241/275] Fixes bug when evaluating entry to bool As reported here: https://github.com/rtfd/readthedocs.org/issues/3411 sphinx sometimes fails with the error: ```python File "/home/docs/checkouts/readthedocs.org/user_builds/drf-yasg/envs/latest/lib/python3.5/site-packages/sphinx/ext/viewcode.py", line 74, in has_tag if entry is None or entry[0] != code: TypeError: 'bool' object is not subscriptable ``` This is not critical as whipping the build or even just running it again fixes it, but the error is confusing... I believe switching the two if statement above should prevent this from happening. --- sphinx/ext/viewcode.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py index 2fd4479f8..3df5b86e2 100644 --- a/sphinx/ext/viewcode.py +++ b/sphinx/ext/viewcode.py @@ -71,12 +71,12 @@ def doctree_read(app, doctree): code = analyzer.code.decode(analyzer.encoding) else: code = analyzer.code - if entry is None or entry[0] != code: + if entry is False: + return + elif entry is None or entry[0] != code: analyzer.find_tags() entry = code, analyzer.tags, {}, refname env._viewcode_modules[modname] = entry # type: ignore - elif entry is False: - return _, tags, used, _ = entry if fullname in tags: used[fullname] = docname From 6448d9b1536ea03f614cb3cb6a83b7f9bda63039 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 8 Jan 2018 18:03:48 +0900 Subject: [PATCH 242/275] Refactor autodoc: Use get_documenters() --- sphinx/ext/autodoc/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 070a7bb2e..386245d20 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -296,9 +296,7 @@ class Documenter(object): def documenters(self): # type: () -> Dict[unicode, Type[Documenter]] """Returns registered Documenter classes""" - classes = dict(AutoDirective._registry) # registered directly - classes.update(self.env.app.registry.documenters) # registered by API - return classes + return get_documenters(self.env.app) def add_line(self, line, source, *lineno): # type: (unicode, unicode, int) -> None From 8ca490f3996a6babc10b69fb4c2af5766c6a1a85 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 8 Jan 2018 19:01:54 +0900 Subject: [PATCH 243/275] Fix flake8 violation --- sphinx/ext/autodoc/directive.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/ext/autodoc/directive.py b/sphinx/ext/autodoc/directive.py index d36888f7e..5d17481eb 100644 --- a/sphinx/ext/autodoc/directive.py +++ b/sphinx/ext/autodoc/directive.py @@ -12,7 +12,7 @@ from docutils.parsers.rst import Directive from docutils.statemachine import ViewList from docutils.utils import assemble_option_dict -from sphinx.ext.autodoc import AutoDirective, get_documenters +from sphinx.ext.autodoc import get_documenters from sphinx.util import logging from sphinx.util.docutils import switch_source_input from sphinx.util.nodes import nested_parse_with_titles From f366816968e29ba0783fa493d58d4f0a0a03888e Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 8 Jan 2018 20:31:57 +0900 Subject: [PATCH 244/275] Fix SphinxStandaloneReader.__init__() method has been duplicated --- sphinx/io.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sphinx/io.py b/sphinx/io.py index 416dfde10..66ba8334e 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -86,11 +86,8 @@ class SphinxStandaloneReader(SphinxBaseReader): def __init__(self, app, *args, **kwargs): # type: (Sphinx, Any, Any) -> None self.transforms = self.transforms + app.registry.get_transforms() - SphinxBaseReader.__init__(self, *args, **kwargs) # type: ignore - - def __init__(self, app, parsers={}, *args, **kwargs): - SphinxBaseReader.__init__(self, app, parsers, *args, **kwargs) self.smart_quotes = app.env.settings['smart_quotes'] + SphinxBaseReader.__init__(self, *args, **kwargs) # type: ignore def get_transforms(self): transforms = SphinxBaseReader.get_transforms(self) From b6b71d99c9df23ce77d247c5295df4bbd7712c43 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 8 Jan 2018 20:32:37 +0900 Subject: [PATCH 245/275] Initialize settings.smartquotes_locales --- sphinx/environment/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index fc5ac691a..c04073163 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -67,6 +67,7 @@ default_settings = { 'sectsubtitle_xform': False, 'halt_level': 5, 'file_insertion_enabled': True, + 'smartquotes_locales': [], } # This is increased every time an environment attribute is added From 739022730295c4968ecc212bbb80b03981eeced3 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 8 Jan 2018 21:38:18 +0900 Subject: [PATCH 246/275] Bump to 1.6.6 final --- CHANGES | 4 ++-- sphinx/__init__.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 80f8c4faa..05c1abdba 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,5 @@ -Release 1.6.6 (in development) -============================== +Release 1.6.6 (released Jan 08, 2018) +===================================== Dependencies ------------ diff --git a/sphinx/__init__.py b/sphinx/__init__.py index b8a62f9e8..332bfe9a2 100644 --- a/sphinx/__init__.py +++ b/sphinx/__init__.py @@ -34,13 +34,13 @@ if 'PYTHONWARNINGS' not in os.environ: warnings.filterwarnings('ignore', "'U' mode is deprecated", DeprecationWarning, module='docutils.io') -__version__ = '1.6.6+' +__version__ = '1.6.6' __released__ = '1.6.6' # used when Sphinx builds its own docs # version info for better programmatic use # possible values for 3rd element: 'alpha', 'beta', 'rc', 'final' # 'final' has 0 as the last element -version_info = (1, 6, 6, 'beta', 0) +version_info = (1, 6, 6, 'final', 0) package_dir = path.abspath(path.dirname(__file__)) From 562683ea32e687c279c019f9837450ba3d6b54df Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 8 Jan 2018 21:42:09 +0900 Subject: [PATCH 247/275] Bump version --- CHANGES | 19 ++++++++++++++----- sphinx/__init__.py | 6 +++--- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index 05c1abdba..00fcb59a7 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,5 @@ -Release 1.6.6 (released Jan 08, 2018) -===================================== +Release 1.6.7 (in development) +============================== Dependencies ------------ @@ -13,6 +13,18 @@ Deprecated Features added -------------- +Bugs fixed +---------- + +Testing +-------- + +Release 1.6.6 (released Jan 08, 2018) +===================================== + +Features added +-------------- + * #4181: autodoc: Sort dictionary keys when possible * ``VerbatimHighlightColor`` is a new :ref:`LaTeX 'sphinxsetup' ` key (refs: #4285) @@ -46,9 +58,6 @@ Bugs fixed * Fix links to external option docs with intersphinx (refs: #3769) * #4091: Private members not documented without :undoc-members: -Testing --------- - Release 1.6.5 (released Oct 23, 2017) ===================================== diff --git a/sphinx/__init__.py b/sphinx/__init__.py index 332bfe9a2..69775059c 100644 --- a/sphinx/__init__.py +++ b/sphinx/__init__.py @@ -34,13 +34,13 @@ if 'PYTHONWARNINGS' not in os.environ: warnings.filterwarnings('ignore', "'U' mode is deprecated", DeprecationWarning, module='docutils.io') -__version__ = '1.6.6' -__released__ = '1.6.6' # used when Sphinx builds its own docs +__version__ = '1.6.7+' +__released__ = '1.6.7' # used when Sphinx builds its own docs # version info for better programmatic use # possible values for 3rd element: 'alpha', 'beta', 'rc', 'final' # 'final' has 0 as the last element -version_info = (1, 6, 6, 'final', 0) +version_info = (1, 6, 7, 'beta', 0) package_dir = path.abspath(path.dirname(__file__)) From 84b4882b31b0af34fd67fd15ceb57582d6951c32 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 9 Jan 2018 23:01:55 +0900 Subject: [PATCH 248/275] Fix smartquotes has been ignored --- sphinx/environment/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index c04073163..251a88589 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -665,7 +665,7 @@ class BuildEnvironment(object): language = self.config.language or 'en' self.settings['language_code'] = language if 'smart_quotes' not in self.settings: - self.settings['smart_quotes'] = True + self.settings['smart_quotes'] = self.config.smartquotes # some conditions exclude smart quotes, overriding smart_quotes for valname, vallist in iteritems(self.config.smartquotes_excludes): From e77267dd943330aea66eaa09f2cd62ea4eb7cc68 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 9 Jan 2018 22:21:49 +0900 Subject: [PATCH 249/275] Add tests for smartquotes --- tests/roots/test-smartquotes/conf.py | 7 ++ tests/roots/test-smartquotes/index.rst | 4 ++ tests/test_smartquotes.py | 92 ++++++++++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 tests/roots/test-smartquotes/conf.py create mode 100644 tests/roots/test-smartquotes/index.rst create mode 100644 tests/test_smartquotes.py diff --git a/tests/roots/test-smartquotes/conf.py b/tests/roots/test-smartquotes/conf.py new file mode 100644 index 000000000..31e7a6ed4 --- /dev/null +++ b/tests/roots/test-smartquotes/conf.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- + +master_doc = 'index' + +latex_documents = [ + (master_doc, 'test.tex', 'The basic Sphinx documentation for testing', 'Sphinx', 'report') +] diff --git a/tests/roots/test-smartquotes/index.rst b/tests/roots/test-smartquotes/index.rst new file mode 100644 index 000000000..be0d9b89c --- /dev/null +++ b/tests/roots/test-smartquotes/index.rst @@ -0,0 +1,4 @@ +test-smartquotes +================ + +-- "Sphinx" is a tool that makes it easy ... diff --git a/tests/test_smartquotes.py b/tests/test_smartquotes.py new file mode 100644 index 000000000..f9ea9d726 --- /dev/null +++ b/tests/test_smartquotes.py @@ -0,0 +1,92 @@ +# -*- coding: utf-8 -*- +""" + test_smartquotes + ~~~~~~~~~~~~~~~~ + + Test smart quotes. + + :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +import pytest +from sphinx.util import docutils + + +@pytest.mark.sphinx(buildername='html', testroot='smartquotes', freshenv=True) +def test_basic(app, status, warning): + app.build() + + content = (app.outdir / 'index.html').text() + assert u'

– “Sphinx” is a tool that makes it easy …

' in content + + +@pytest.mark.sphinx(buildername='text', testroot='smartquotes', freshenv=True) +def test_text_builder(app, status, warning): + app.build() + + content = (app.outdir / 'index.txt').text() + assert u'-- "Sphinx" is a tool that makes it easy ...' in content + + +@pytest.mark.sphinx(buildername='man', testroot='smartquotes', freshenv=True) +def test_man_builder(app, status, warning): + app.build() + + content = (app.outdir / 'python.1').text() + assert u'\\-\\- "Sphinx" is a tool that makes it easy ...' in content + + +@pytest.mark.sphinx(buildername='latex', testroot='smartquotes', freshenv=True) +def test_latex_builder(app, status, warning): + app.build() + + content = (app.outdir / 'test.tex').text() + assert u'\\textendash{} “Sphinx” is a tool that makes it easy …' in content + + +@pytest.mark.sphinx(buildername='html', testroot='smartquotes', freshenv=True, + confoverrides={'language': 'ja'}) +def test_ja_html_builder(app, status, warning): + app.build() + + content = (app.outdir / 'index.html').text() + assert u'

-- "Sphinx" is a tool that makes it easy ...

' in content + + +@pytest.mark.sphinx(buildername='html', testroot='smartquotes', freshenv=True, + confoverrides={'smartquotes': False}) +def test_smartquotes_disabled(app, status, warning): + app.build() + + content = (app.outdir / 'index.html').text() + assert u'

-- "Sphinx" is a tool that makes it easy ...

' in content + + +@pytest.mark.skipif(docutils.__version_info__ < (0, 14), + reason='docutils-0.14 or above is required') +@pytest.mark.sphinx(buildername='html', testroot='smartquotes', freshenv=True, + confoverrides={'smartquotes_action': 'q'}) +def test_smartquotes_action(app, status, warning): + app.build() + + content = (app.outdir / 'index.html').text() + assert u'

-- “Sphinx” is a tool that makes it easy ...

' in content + + +@pytest.mark.sphinx(buildername='html', testroot='smartquotes', freshenv=True, + confoverrides={'language': 'ja', 'smartquotes_excludes': {}}) +def test_smartquotes_excludes_language(app, status, warning): + app.build() + + content = (app.outdir / 'index.html').text() + assert u'

– 「Sphinx」 is a tool that makes it easy …

' in content + + +@pytest.mark.sphinx(buildername='man', testroot='smartquotes', freshenv=True, + confoverrides={'smartquotes_excludes': {}}) +def test_smartquotes_excludes_builders(app, status, warning): + app.build() + + content = (app.outdir / 'python.1').text() + assert u'– “Sphinx” is a tool that makes it easy …' in content From 33fd1f446ab0041ae53d42fa7ed5e7b4aa18d74b Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 10 Jan 2018 21:35:21 +0900 Subject: [PATCH 250/275] latex: Do not display Release label if :confval:`release` is not set --- CHANGES | 1 + sphinx/writers/latex.py | 2 +- tests/test_build_latex.py | 18 ++++++++++++++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index d9350d21a..b3e6283fd 100644 --- a/CHANGES +++ b/CHANGES @@ -113,6 +113,7 @@ Bugs fixed * #4198: autosummary emits multiple 'autodoc-process-docstring' event. Thanks to Joel Nothman. * #4081: Warnings and errors colored the same when building +* latex: Do not display 'Release' label if :confval:`release` is not set Testing -------- diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index de472b36c..6c86e6174 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -549,7 +549,7 @@ class LaTeXTranslator(nodes.NodeVisitor): 'author': document.settings.author, # treat as a raw LaTeX code 'indexname': _('Index'), }) - if not self.elements['releasename']: + if not self.elements['releasename'] and self.elements['release']: self.elements.update({ 'releasename': _('Release'), }) diff --git a/tests/test_build_latex.py b/tests/test_build_latex.py index ab91d7a48..e7b61ad0c 100644 --- a/tests/test_build_latex.py +++ b/tests/test_build_latex.py @@ -165,13 +165,15 @@ def test_latex_warnings(app, status, warning): @pytest.mark.sphinx('latex', testroot='basic') -def test_latex_title(app, status, warning): +def test_latex_basic(app, status, warning): app.builder.build_all() result = (app.outdir / 'test.tex').text(encoding='utf8') print(result) print(status.getvalue()) print(warning.getvalue()) - assert '\\title{The basic Sphinx documentation for testing}' in result + assert r'\title{The basic Sphinx documentation for testing}' in result + assert r'\release{}' in result + assert r'\renewcommand{\releasename}{}' in result @pytest.mark.sphinx('latex', testroot='latex-title') @@ -184,6 +186,18 @@ def test_latex_title_after_admonitions(app, status, warning): assert '\\title{test-latex-title}' in result +@pytest.mark.sphinx('latex', testroot='basic', + confoverrides={'release': '1.0'}) +def test_latex_release(app, status, warning): + app.builder.build_all() + result = (app.outdir / 'test.tex').text(encoding='utf8') + print(result) + print(status.getvalue()) + print(warning.getvalue()) + assert r'\release{1.0}' in result + assert r'\renewcommand{\releasename}{Release}' in result + + @pytest.mark.sphinx('latex', testroot='numfig', confoverrides={'numfig': True}) def test_numref(app, status, warning): From 90f7c7ef3fd18b5ceff5eef1361f5f71f68209ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Beaupr=C3=A9?= Date: Thu, 11 Jan 2018 13:20:26 -0500 Subject: [PATCH 251/275] add link to manpages in HTML builder It is useful to have the HTML documentation builder actually link to real rendered versions of HTML manpages in its output. That way people can click on manpages to get the full documentation. There are a few services offering this online, so we do not explicitly enable one by default, but the Debian manpages repository has a lot of the manpages pre-rendered, so it is used as an example in the documentation. The parsing work is done by a transformer class that parses manpage objects and extract name/section elements. Those then can be used by writers to cross-reference to actual sites. An implementation is done in the two HTML writers, but could also apply to ePUB/PDF writers as well in the future. This is not enabled by default: the `manpages_url` configuration item needs to be enabled to point to the chosen site. The `page`, `section` and `path` parameters are expanded through Python string formatting in the URL on output. Unit tests are fairly limited, but should cover most common use-cases. --- doc/config.rst | 18 ++++++++++++++++++ doc/markup/inline.rst | 3 ++- sphinx/config.py | 1 + sphinx/io.py | 6 +++--- sphinx/transforms/__init__.py | 20 ++++++++++++++++++++ sphinx/writers/html.py | 6 ++++++ sphinx/writers/html5.py | 6 ++++++ tests/roots/test-manpage_url/conf.py | 5 +++++ tests/roots/test-manpage_url/index.rst | 3 +++ tests/test_build_html.py | 13 +++++++++++++ 10 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 tests/roots/test-manpage_url/conf.py create mode 100644 tests/roots/test-manpage_url/index.rst diff --git a/doc/config.rst b/doc/config.rst index 9bdd283a9..587d5785b 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -293,6 +293,24 @@ General configuration .. versionadded:: 1.3 +.. confval:: manpages_url + + A URL to cross-reference :rst:role:`manpage` directives. If this is + defined to ``https://manpages.debian.org/{path}``, the + :literal:`:manpage:`man(1)`` role will like to + . The patterns available are: + + * ``page`` - the manual page (``man``) + * ``section`` - the manual section (``1``) + * ``path`` - the original manual page and section specified (``man(1)``) + + This also supports manpages specified as ``man.1``. + + .. note:: This currently affects only HTML writers but could be + expanded in the future. + + .. versionadded:: 1.7 + .. confval:: nitpicky If true, Sphinx will warn about *all* references where the target cannot be diff --git a/doc/markup/inline.rst b/doc/markup/inline.rst index 4d14a653d..c8dfb6ff7 100644 --- a/doc/markup/inline.rst +++ b/doc/markup/inline.rst @@ -355,7 +355,8 @@ in a different style: .. rst:role:: manpage A reference to a Unix manual page including the section, - e.g. ``:manpage:`ls(1)```. + e.g. ``:manpage:`ls(1)```. Creates a hyperlink to an external site + rendering the manpage if :confval:`manpages_url` is defined. .. rst:role:: menuselection diff --git a/sphinx/config.py b/sphinx/config.py index c6bf1cc3c..1b3f51a6e 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -125,6 +125,7 @@ class Config(object): primary_domain = ('py', 'env', [NoneType]), needs_sphinx = (None, None, string_classes), needs_extensions = ({}, None), + manpages_url = (None, 'env'), nitpicky = (False, None), nitpick_ignore = ([], None), numfig = (False, 'env'), diff --git a/sphinx/io.py b/sphinx/io.py index 66ba8334e..3c32c167c 100644 --- a/sphinx/io.py +++ b/sphinx/io.py @@ -23,7 +23,7 @@ from sphinx.transforms import ( ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences, DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, SortIds, AutoNumbering, AutoIndexUpgrader, FilterSystemMessages, - UnreferencedFootnotesDetector, SphinxSmartQuotes + UnreferencedFootnotesDetector, SphinxSmartQuotes, ManpageLink ) from sphinx.transforms.compact_bullet_list import RefOnlyBulletListTransform from sphinx.transforms.i18n import ( @@ -80,7 +80,7 @@ class SphinxStandaloneReader(SphinxBaseReader): Locale, CitationReferences, DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, AutoNumbering, AutoIndexUpgrader, SortIds, RemoveTranslatableInline, PreserveTranslatableMessages, FilterSystemMessages, - RefOnlyBulletListTransform, UnreferencedFootnotesDetector + RefOnlyBulletListTransform, UnreferencedFootnotesDetector, ManpageLink ] # type: List[Transform] def __init__(self, app, *args, **kwargs): @@ -110,7 +110,7 @@ class SphinxI18nReader(SphinxBaseReader): DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, AutoNumbering, SortIds, RemoveTranslatableInline, FilterSystemMessages, RefOnlyBulletListTransform, - UnreferencedFootnotesDetector] + UnreferencedFootnotesDetector, ManpageLink] def set_lineno_for_reporter(self, lineno): # type: (int) -> None diff --git a/sphinx/transforms/__init__.py b/sphinx/transforms/__init__.py index acfff6a4d..ceb8de364 100644 --- a/sphinx/transforms/__init__.py +++ b/sphinx/transforms/__init__.py @@ -9,6 +9,8 @@ :license: BSD, see LICENSE for details. """ +import re + from docutils import nodes from docutils.transforms import Transform, Transformer from docutils.transforms.parts import ContentsFilter @@ -348,3 +350,21 @@ class SphinxSmartQuotes(SmartQuotes): for txtnode in txtnodes: notsmartquotable = not is_smartquotable(txtnode) yield (texttype[notsmartquotable], txtnode.astext()) + + +class ManpageLink(SphinxTransform): + """Find manpage section numbers and names""" + default_priority = 999 + + def apply(self): + for node in self.document.traverse(addnodes.manpage): + manpage = ' '.join([str(x) for x in node.children + if isinstance(x, nodes.Text)]) + pattern = r'^(?P(?P.+)[\(\.](?P
[1-9]\w*)?\)?)$' # noqa + info = {'path': manpage, + 'page': manpage, + 'section': ''} + r = re.match(pattern, manpage) + if r: + info = r.groupdict() + node.attributes.update(info) diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py index b3d27e31a..84e7bfbc9 100644 --- a/sphinx/writers/html.py +++ b/sphinx/writers/html.py @@ -79,6 +79,7 @@ class HTMLTranslator(BaseTranslator): self.highlightopts = builder.config.highlight_options self.highlightlinenothreshold = sys.maxsize self.docnames = [builder.current_docname] # for singlehtml builder + self.manpages_url = builder.config.manpages_url self.protect_literal_text = 0 self.permalink_text = builder.config.html_add_permalinks # support backwards-compatible setting to a bool @@ -816,9 +817,14 @@ class HTMLTranslator(BaseTranslator): def visit_manpage(self, node): # type: (nodes.Node) -> None self.visit_literal_emphasis(node) + if self.manpages_url: + node['refuri'] = self.manpages_url.format(**node.attributes) + self.visit_reference(node) def depart_manpage(self, node): # type: (nodes.Node) -> None + if self.manpages_url: + self.depart_reference(node) self.depart_literal_emphasis(node) # overwritten to add even/odd classes diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py index a47fee77e..50bf2ea8c 100644 --- a/sphinx/writers/html5.py +++ b/sphinx/writers/html5.py @@ -49,6 +49,7 @@ class HTML5Translator(BaseTranslator): self.highlightopts = builder.config.highlight_options self.highlightlinenothreshold = sys.maxsize self.docnames = [builder.current_docname] # for singlehtml builder + self.manpages_url = builder.config.manpages_url self.protect_literal_text = 0 self.permalink_text = builder.config.html_add_permalinks # support backwards-compatible setting to a bool @@ -758,9 +759,14 @@ class HTML5Translator(BaseTranslator): def visit_manpage(self, node): # type: (nodes.Node) -> None self.visit_literal_emphasis(node) + if self.manpages_url: + node['refuri'] = self.manpages_url.format(**dict(node)) + self.visit_reference(node) def depart_manpage(self, node): # type: (nodes.Node) -> None + if self.manpages_url: + self.depart_reference(node) self.depart_literal_emphasis(node) # overwritten to add even/odd classes diff --git a/tests/roots/test-manpage_url/conf.py b/tests/roots/test-manpage_url/conf.py new file mode 100644 index 000000000..c46e40773 --- /dev/null +++ b/tests/roots/test-manpage_url/conf.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + +master_doc = 'index' +html_theme = 'classic' +exclude_patterns = ['_build'] diff --git a/tests/roots/test-manpage_url/index.rst b/tests/roots/test-manpage_url/index.rst new file mode 100644 index 000000000..50d3b042e --- /dev/null +++ b/tests/roots/test-manpage_url/index.rst @@ -0,0 +1,3 @@ + * :manpage:`man(1)` + * :manpage:`ls.1` + * :manpage:`sphinx` diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 8265c8471..153ff5165 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -1243,3 +1243,16 @@ def test_html_sidebar(app, status, warning): assert '

Related Topics

' not in result assert '

This Page

' not in result assert '

Quick search

' not in result + + +@pytest.mark.parametrize('fname,expect', flat_dict({ + 'index.html': [(".//em/a[@href='https://example.com/man.1']", "", True), + (".//em/a[@href='https://example.com/ls.1']", "", True), + (".//em/a[@href='https://example.com/sphinx.']", "", True)] + })) +@pytest.mark.sphinx('html', testroot='manpage_url', confoverrides={ + 'manpages_url': 'https://example.com/{page}.{section}'}) +@pytest.mark.test_params(shared_result='test_build_html_manpage_url') +def test_html_manpage(app, cached_etree_parse, fname, expect): + app.build() + check_xpath(cached_etree_parse(app.outdir / fname), fname, *expect) From a83e8bab7d03d209f76cc92ffe29a9b89289cf6f Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 28 Dec 2017 20:45:02 +0000 Subject: [PATCH 252/275] builders: Add 'Builder.epilog' option This allows builders to emit a final epilog message containing information such as where resulting files can be found. This is only emitted if the build was successful. This allows us to remove this content from the 'make_mode' tool and the legacy 'Makefile' and 'make.bat' templates. There's room for more dramatic simplification of the former, but this will come later. Signed-off-by: Stephen Finucane --- doc/extdev/builderapi.rst | 1 + sphinx/application.py | 7 +++ sphinx/builders/__init__.py | 5 +++ sphinx/builders/applehelp.py | 4 ++ sphinx/builders/changes.py | 1 + sphinx/builders/devhelp.py | 4 ++ sphinx/builders/dummy.py | 2 + sphinx/builders/epub3.py | 1 + sphinx/builders/gettext.py | 1 + sphinx/builders/html.py | 12 ++++- sphinx/builders/htmlhelp.py | 2 + sphinx/builders/latex.py | 6 +++ sphinx/builders/linkcheck.py | 2 + sphinx/builders/manpage.py | 2 + sphinx/builders/qthelp.py | 5 +++ sphinx/builders/texinfo.py | 7 +++ sphinx/builders/text.py | 2 + sphinx/builders/xml.py | 4 ++ sphinx/ext/coverage.py | 6 ++- sphinx/ext/doctest.py | 2 + sphinx/make_mode.py | 61 -------------------------- sphinx/templates/quickstart/Makefile_t | 61 -------------------------- sphinx/templates/quickstart/make.bat_t | 50 --------------------- 23 files changed, 73 insertions(+), 175 deletions(-) diff --git a/doc/extdev/builderapi.rst b/doc/extdev/builderapi.rst index 668f46698..b8ff0595b 100644 --- a/doc/extdev/builderapi.rst +++ b/doc/extdev/builderapi.rst @@ -15,6 +15,7 @@ Builder API .. autoattribute:: name .. autoattribute:: format + .. autoattribute:: epilog .. autoattribute:: supported_image_types These methods are predefined and will be called from the application: diff --git a/sphinx/application.py b/sphinx/application.py index e76f101a3..8a22a9e6d 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -338,6 +338,13 @@ class Sphinx(object): (status, self._warncount))) else: logger.info(bold(__('build %s.') % status)) + + if self.statuscode == 0 and self.builder.epilog: + logger.info('') + logger.info(self.builder.epilog % { + 'outdir': path.relpath(self.outdir), + 'project': self.config.project + }) except Exception as err: # delete the saved env to force a fresh build next time envfile = path.join(self.doctreedir, ENV_PICKLE_FILENAME) diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py index a1e360d2f..51578a1d6 100644 --- a/sphinx/builders/__init__.py +++ b/sphinx/builders/__init__.py @@ -54,6 +54,11 @@ class Builder(object): name = '' # type: unicode #: The builder's output format, or '' if no document output is produced. format = '' # type: unicode + #: The message emitted upon successful build completion. This can be a + #: printf-style template string with the following keys: ``outdir``, + #: ``project`` + epilog = '' # type: unicode + # default translator class for the builder. This will be overrided by # ``app.set_translator()``. default_translator_class = None # type: nodes.NodeVisitor diff --git a/sphinx/builders/applehelp.py b/sphinx/builders/applehelp.py index 52ba2ce5c..0426be331 100644 --- a/sphinx/builders/applehelp.py +++ b/sphinx/builders/applehelp.py @@ -75,6 +75,10 @@ class AppleHelpBuilder(StandaloneHTMLBuilder): on the ``hiutil`` command line tool. """ name = 'applehelp' + epilog = ('The help book is in %(outdir)s.\n' + 'Note that won\'t be able to view it unless you put it in ' + '~/Library/Documentation/Help or install it in your application ' + 'bundle.') # don't copy the reST source copysource = False diff --git a/sphinx/builders/changes.py b/sphinx/builders/changes.py index 5309649c6..ff80250a3 100644 --- a/sphinx/builders/changes.py +++ b/sphinx/builders/changes.py @@ -38,6 +38,7 @@ class ChangesBuilder(Builder): Write a summary with all versionadded/changed directives. """ name = 'changes' + epilog = 'The overview file is in %(outdir)s.' def init(self): # type: () -> None diff --git a/sphinx/builders/devhelp.py b/sphinx/builders/devhelp.py index 88a9be219..c5e9eb6ea 100644 --- a/sphinx/builders/devhelp.py +++ b/sphinx/builders/devhelp.py @@ -43,6 +43,10 @@ class DevhelpBuilder(StandaloneHTMLBuilder): Builder that also outputs GNOME Devhelp file. """ name = 'devhelp' + epilog = ('To view the help file:\n' + '$ mkdir -p $HOME/.local/share/devhelp/%(project)s\n' + '$ ln -s %(outdir)s $HOME/.local/share/devhelp/%(project)s\n' + '$ devhelp') # don't copy the reST source copysource = False diff --git a/sphinx/builders/dummy.py b/sphinx/builders/dummy.py index 74a3d4187..08d99a584 100644 --- a/sphinx/builders/dummy.py +++ b/sphinx/builders/dummy.py @@ -21,6 +21,8 @@ if False: class DummyBuilder(Builder): name = 'dummy' + epilog = 'The dummy builder generates no files.' + allow_parallel = True def init(self): diff --git a/sphinx/builders/epub3.py b/sphinx/builders/epub3.py index 92c55c880..c98c4b853 100644 --- a/sphinx/builders/epub3.py +++ b/sphinx/builders/epub3.py @@ -63,6 +63,7 @@ class Epub3Builder(_epub_base.EpubBuilder): an epub file. """ name = 'epub' + epilog = 'The ePub file is in %(outdir)s.' supported_remote_images = False template_dir = path.join(package_dir, 'templates', 'epub3') diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py index 464d574cc..f7f0d6811 100644 --- a/sphinx/builders/gettext.py +++ b/sphinx/builders/gettext.py @@ -214,6 +214,7 @@ class MessageCatalogBuilder(I18nBuilder): Builds gettext-style message catalogs (.pot files). """ name = 'gettext' + epilog = 'The message catalogs are in %(outdir)s.' def init(self): # type: () -> None diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index f9c9420c2..dcbc59280 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -153,6 +153,8 @@ class StandaloneHTMLBuilder(Builder): """ name = 'html' format = 'html' + epilog = 'The HTML pages are in %(outdir)s.' + copysource = True allow_parallel = True out_suffix = '.html' @@ -1066,6 +1068,8 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder): HTML page. """ name = 'singlehtml' + epilog = 'The HTML page is in %(outdir)s.' + copysource = False def get_outdated_docs(self): # type: ignore @@ -1328,12 +1332,14 @@ class PickleHTMLBuilder(SerializingHTMLBuilder): """ A Builder that dumps the generated HTML into pickle files. """ + name = 'pickle' + epilog = 'You can now process the pickle files in %(outdir)s.' + implementation = pickle implementation_dumps_unicode = False additional_dump_args = (pickle.HIGHEST_PROTOCOL,) indexer_format = pickle indexer_dumps_unicode = False - name = 'pickle' out_suffix = '.fpickle' globalcontext_filename = 'globalcontext.pickle' searchindex_filename = 'searchindex.pickle' @@ -1347,11 +1353,13 @@ class JSONHTMLBuilder(SerializingHTMLBuilder): """ A builder that dumps the generated HTML into JSON files. """ + name = 'json' + epilog = 'You can now process the JSON files in %(outdir)s.' + implementation = jsonimpl implementation_dumps_unicode = True indexer_format = jsonimpl indexer_dumps_unicode = True - name = 'json' out_suffix = '.fjson' globalcontext_filename = 'globalcontext.json' searchindex_filename = 'searchindex.json' diff --git a/sphinx/builders/htmlhelp.py b/sphinx/builders/htmlhelp.py index 0b45601e3..63fba05f3 100644 --- a/sphinx/builders/htmlhelp.py +++ b/sphinx/builders/htmlhelp.py @@ -174,6 +174,8 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder): index files. Adapted from the original Doc/tools/prechm.py. """ name = 'htmlhelp' + epilog = ('You can now run HTML Help Workshop with the .htp file in ' + '%(outdir)s.') # don't copy the reST source copysource = False diff --git a/sphinx/builders/latex.py b/sphinx/builders/latex.py index 8fdb2fa49..088f5d9ef 100644 --- a/sphinx/builders/latex.py +++ b/sphinx/builders/latex.py @@ -49,6 +49,12 @@ class LaTeXBuilder(Builder): """ name = 'latex' format = 'latex' + epilog = 'The LaTeX files are in %(outdir)s.' + if os.name == 'posix': + epilog += ("\nRun 'make' in that directory to run these through " + "(pdf)latex\n" + "(use `make latexpdf' here to do that automatically).") + supported_image_types = ['application/pdf', 'image/png', 'image/jpeg'] supported_remote_images = False default_translator_class = LaTeXTranslator diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py index ca62b9fe1..c1a47607b 100644 --- a/sphinx/builders/linkcheck.py +++ b/sphinx/builders/linkcheck.py @@ -90,6 +90,8 @@ class CheckExternalLinksBuilder(Builder): Checks for broken external links. """ name = 'linkcheck' + epilog = ('Look for any errors in the above output or in ' + '%(outdir)s/output.txt') def init(self): # type: () -> None diff --git a/sphinx/builders/manpage.py b/sphinx/builders/manpage.py index b57a756ee..8f7800846 100644 --- a/sphinx/builders/manpage.py +++ b/sphinx/builders/manpage.py @@ -40,6 +40,8 @@ class ManualPageBuilder(Builder): """ name = 'man' format = 'man' + epilog = 'The manual pages are in %(outdir)s.' + default_translator_class = ManualPageTranslator supported_image_types = [] # type: List[unicode] diff --git a/sphinx/builders/qthelp.py b/sphinx/builders/qthelp.py index 2f56792a9..9d08df2a3 100644 --- a/sphinx/builders/qthelp.py +++ b/sphinx/builders/qthelp.py @@ -108,6 +108,11 @@ class QtHelpBuilder(StandaloneHTMLBuilder): Builder that also outputs Qt help project, contents and index files. """ name = 'qthelp' + epilog = ('You can now run "qcollectiongenerator" with the .qhcp ' + 'project file in %(outdir)s, like this:\n' + '$ qcollectiongenerator %(outdir)s/%(project)s.qhcp\n' + 'To view the help file:\n' + '$ assistant -collectionFile %(outdir)s/%(project)s.qhc') # don't copy the reST source copysource = False diff --git a/sphinx/builders/texinfo.py b/sphinx/builders/texinfo.py index 82c6f1b9d..39653c117 100644 --- a/sphinx/builders/texinfo.py +++ b/sphinx/builders/texinfo.py @@ -9,6 +9,7 @@ :license: BSD, see LICENSE for details. """ +import os from os import path from docutils import nodes @@ -97,6 +98,12 @@ class TexinfoBuilder(Builder): """ name = 'texinfo' format = 'texinfo' + epilog = 'The Texinfo files are in %(outdir)s.' + if os.name == 'posix': + epilog += ("\nRun 'make' in that directory to run these through " + "makeinfo\n" + "(use 'make info' here to do that automatically).") + supported_image_types = ['image/png', 'image/jpeg', 'image/gif'] default_translator_class = TexinfoTranslator diff --git a/sphinx/builders/text.py b/sphinx/builders/text.py index 7b977b1b9..a7ecd0e68 100644 --- a/sphinx/builders/text.py +++ b/sphinx/builders/text.py @@ -31,6 +31,8 @@ logger = logging.getLogger(__name__) class TextBuilder(Builder): name = 'text' format = 'text' + epilog = 'The text files are in %(outdir)s.' + out_suffix = '.txt' allow_parallel = True default_translator_class = TextTranslator diff --git a/sphinx/builders/xml.py b/sphinx/builders/xml.py index 599530ac1..80d7723aa 100644 --- a/sphinx/builders/xml.py +++ b/sphinx/builders/xml.py @@ -35,6 +35,8 @@ class XMLBuilder(Builder): """ name = 'xml' format = 'xml' + epilog = 'The XML files are in %(outdir)s.' + out_suffix = '.xml' allow_parallel = True @@ -108,6 +110,8 @@ class PseudoXMLBuilder(XMLBuilder): """ name = 'pseudoxml' format = 'pseudoxml' + epilog = 'The pseudo-XML files are in %(outdir)s.' + out_suffix = '.pseudoxml' _writer_class = PseudoXMLWriter diff --git a/sphinx/ext/coverage.py b/sphinx/ext/coverage.py index 476a0ed46..74d004ad1 100644 --- a/sphinx/ext/coverage.py +++ b/sphinx/ext/coverage.py @@ -50,8 +50,12 @@ def compile_regex_list(name, exps): class CoverageBuilder(Builder): - + """ + Evaluates coverage of code in the documentation. + """ name = 'coverage' + epilog = ('Testing of coverage in the sources finished, look at the ' + 'results in %(outdir)s/python.txt.') def init(self): # type: () -> None diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py index e0ce050f7..b104cfc08 100644 --- a/sphinx/ext/doctest.py +++ b/sphinx/ext/doctest.py @@ -278,6 +278,8 @@ class DocTestBuilder(Builder): Runs test snippets in the documentation. """ name = 'doctest' + epilog = ('Testing of doctests in the sources finished, look at the ' + 'results in %(outdir)s/output.txt.') def init(self): # type: () -> None diff --git a/sphinx/make_mode.py b/sphinx/make_mode.py index 0bc1a797d..64268c2ec 100644 --- a/sphinx/make_mode.py +++ b/sphinx/make_mode.py @@ -101,95 +101,60 @@ class Make(object): # type: () -> int if self.run_generic_build('html') > 0: return 1 - print() - print('Build finished. The HTML pages are in %s.' % self.builddir_join('html')) return 0 def build_dirhtml(self): # type: () -> int if self.run_generic_build('dirhtml') > 0: return 1 - print() - print('Build finished. The HTML pages are in %s.' % - self.builddir_join('dirhtml')) return 0 def build_singlehtml(self): # type: () -> int if self.run_generic_build('singlehtml') > 0: return 1 - print() - print('Build finished. The HTML page is in %s.' % - self.builddir_join('singlehtml')) return 0 def build_pickle(self): # type: () -> int if self.run_generic_build('pickle') > 0: return 1 - print() - print('Build finished; now you can process the pickle files.') return 0 def build_json(self): # type: () -> int if self.run_generic_build('json') > 0: return 1 - print() - print('Build finished; now you can process the JSON files.') return 0 def build_htmlhelp(self): # type: () -> int if self.run_generic_build('htmlhelp') > 0: return 1 - print() - print('Build finished; now you can run HTML Help Workshop with the ' - '.hhp project file in %s.' % self.builddir_join('htmlhelp')) return 0 def build_qthelp(self): # type: () -> int if self.run_generic_build('qthelp') > 0: return 1 - print() - print('Build finished; now you can run "qcollectiongenerator" with the ' - '.qhcp project file in %s, like this:' % self.builddir_join('qthelp')) - print('$ qcollectiongenerator %s.qhcp' % self.builddir_join('qthelp', proj_name)) - print('To view the help file:') - print('$ assistant -collectionFile %s.qhc' % - self.builddir_join('qthelp', proj_name)) return 0 def build_devhelp(self): # type: () -> int if self.run_generic_build('devhelp') > 0: return 1 - print() - print("Build finished.") - print("To view the help file:") - print("$ mkdir -p $HOME/.local/share/devhelp/" + proj_name) - print("$ ln -s %s $HOME/.local/share/devhelp/%s" % - (self.builddir_join('devhelp'), proj_name)) - print("$ devhelp") return 0 def build_epub(self): # type: () -> int if self.run_generic_build('epub') > 0: return 1 - print() - print('Build finished. The ePub file is in %s.' % self.builddir_join('epub')) return 0 def build_latex(self): # type: () -> int if self.run_generic_build('latex') > 0: return 1 - print("Build finished; the LaTeX files are in %s." % self.builddir_join('latex')) - if os.name == 'posix': - print("Run `make' in that directory to run these through (pdf)latex") - print("(use `make latexpdf' here to do that automatically).") return 0 def build_latexpdf(self): @@ -210,19 +175,12 @@ class Make(object): # type: () -> int if self.run_generic_build('text') > 0: return 1 - print() - print('Build finished. The text files are in %s.' % self.builddir_join('text')) return 0 def build_texinfo(self): # type: () -> int if self.run_generic_build('texinfo') > 0: return 1 - print("Build finished; the Texinfo files are in %s." % - self.builddir_join('texinfo')) - if os.name == 'posix': - print("Run `make' in that directory to run these through makeinfo") - print("(use `make info' here to do that automatically).") return 0 def build_info(self): @@ -237,33 +195,22 @@ class Make(object): dtdir = self.builddir_join('gettext', '.doctrees') if self.run_generic_build('gettext', doctreedir=dtdir) > 0: return 1 - print() - print('Build finished. The message catalogs are in %s.' % - self.builddir_join('gettext')) return 0 def build_changes(self): # type: () -> int if self.run_generic_build('changes') > 0: return 1 - print() - print('Build finished. The overview file is in %s.' % - self.builddir_join('changes')) return 0 def build_linkcheck(self): # type: () -> int res = self.run_generic_build('linkcheck') - print() - print('Link check complete; look for any errors in the above output ' - 'or in %s.' % self.builddir_join('linkcheck', 'output.txt')) return res def build_doctest(self): # type: () -> int res = self.run_generic_build('doctest') - print("Testing of doctests in the sources finished, look at the " - "results in %s." % self.builddir_join('doctest', 'output.txt')) return res def build_coverage(self): @@ -271,26 +218,18 @@ class Make(object): if self.run_generic_build('coverage') > 0: print("Has the coverage extension been enabled?") return 1 - print() - print("Testing of coverage in the sources finished, look at the " - "results in %s." % self.builddir_join('coverage')) return 0 def build_xml(self): # type: () -> int if self.run_generic_build('xml') > 0: return 1 - print() - print('Build finished. The XML files are in %s.' % self.builddir_join('xml')) return 0 def build_pseudoxml(self): # type: () -> int if self.run_generic_build('pseudoxml') > 0: return 1 - print() - print('Build finished. The pseudo-XML files are in %s.' % - self.builddir_join('pseudoxml')) return 0 def run_generic_build(self, builder, doctreedir=None): diff --git a/sphinx/templates/quickstart/Makefile_t b/sphinx/templates/quickstart/Makefile_t index 2858d9bf7..77ce4afe8 100644 --- a/sphinx/templates/quickstart/Makefile_t +++ b/sphinx/templates/quickstart/Makefile_t @@ -52,82 +52,46 @@ clean: .PHONY: html html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." .PHONY: dirhtml dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." .PHONY: singlehtml singlehtml: $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." .PHONY: pickle pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." .PHONY: json json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." .PHONY: htmlhelp htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." .PHONY: qthelp qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/{{ project_fn }}.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/{{ project_fn }}.qhc" .PHONY: applehelp applehelp: $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp - @echo - @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." - @echo "N.B. You won't be able to view it unless you put it in" \ - "~/Library/Documentation/Help or install it in your application" \ - "bundle." .PHONY: devhelp devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/{{ project_fn }}" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/{{ project_fn }}" - @echo "# devhelp" .PHONY: epub epub: $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." .PHONY: latex latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." .PHONY: latexpdf latexpdf: @@ -160,22 +124,14 @@ xelatexpdf: .PHONY: text text: $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." .PHONY: man man: $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." .PHONY: texinfo texinfo: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." .PHONY: info info: @@ -187,49 +143,32 @@ info: .PHONY: gettext gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." .PHONY: changes changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." .PHONY: linkcheck linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." .PHONY: doctest doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." .PHONY: coverage coverage: $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage - @echo "Testing of coverage in the sources finished, look at the " \ - "results in $(BUILDDIR)/coverage/python.txt." .PHONY: xml xml: $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml - @echo - @echo "Build finished. The XML files are in $(BUILDDIR)/xml." .PHONY: pseudoxml pseudoxml: $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml - @echo - @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." .PHONY: dummy dummy: $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy - @echo - @echo "Build finished. Dummy builder generates no files." diff --git a/sphinx/templates/quickstart/make.bat_t b/sphinx/templates/quickstart/make.bat_t index 230977488..94d28461b 100644 --- a/sphinx/templates/quickstart/make.bat_t +++ b/sphinx/templates/quickstart/make.bat_t @@ -78,85 +78,60 @@ if errorlevel 9009 ( if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "singlehtml" ( %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\{{ project_fn }}.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\{{ project_fn }}.ghc goto end ) if "%1" == "devhelp" ( %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp if errorlevel 1 exit /b 1 - echo. - echo.Build finished. goto end ) if "%1" == "epub" ( %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The epub file is in %BUILDDIR%/epub. goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex if errorlevel 1 exit /b 1 - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) @@ -183,91 +158,66 @@ if "%1" == "latexpdfja" ( if "%1" == "text" ( %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The text files are in %BUILDDIR%/text. goto end ) if "%1" == "man" ( %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The manual pages are in %BUILDDIR%/man. goto end ) if "%1" == "texinfo" ( %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. goto end ) if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The message catalogs are in %BUILDDIR%/locale. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes if errorlevel 1 exit /b 1 - echo. - echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck if errorlevel 1 exit /b 1 - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest if errorlevel 1 exit /b 1 - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. goto end ) if "%1" == "coverage" ( %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage if errorlevel 1 exit /b 1 - echo. - echo.Testing of coverage in the sources finished, look at the ^ -results in %BUILDDIR%/coverage/python.txt. goto end ) if "%1" == "xml" ( %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The XML files are in %BUILDDIR%/xml. goto end ) if "%1" == "pseudoxml" ( %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. goto end ) if "%1" == "dummy" ( %SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy if errorlevel 1 exit /b 1 - echo. - echo.Build finished. Dummy builder generates no files. goto end ) From 221dffda3c00f5abf64057e350959d123c50ccac Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 28 Dec 2017 20:45:24 +0000 Subject: [PATCH 253/275] make_mode: Remove unnecessary 'make_*' functions These are handled by the default case. Signed-off-by: Stephen Finucane --- sphinx/make_mode.py | 107 -------------------------------------------- 1 file changed, 107 deletions(-) diff --git a/sphinx/make_mode.py b/sphinx/make_mode.py index 64268c2ec..4b325160f 100644 --- a/sphinx/make_mode.py +++ b/sphinx/make_mode.py @@ -97,66 +97,6 @@ class Make(object): if not osname or os.name == osname: print(' %s %s' % (blue(bname.ljust(10)), description)) - def build_html(self): - # type: () -> int - if self.run_generic_build('html') > 0: - return 1 - return 0 - - def build_dirhtml(self): - # type: () -> int - if self.run_generic_build('dirhtml') > 0: - return 1 - return 0 - - def build_singlehtml(self): - # type: () -> int - if self.run_generic_build('singlehtml') > 0: - return 1 - return 0 - - def build_pickle(self): - # type: () -> int - if self.run_generic_build('pickle') > 0: - return 1 - return 0 - - def build_json(self): - # type: () -> int - if self.run_generic_build('json') > 0: - return 1 - return 0 - - def build_htmlhelp(self): - # type: () -> int - if self.run_generic_build('htmlhelp') > 0: - return 1 - return 0 - - def build_qthelp(self): - # type: () -> int - if self.run_generic_build('qthelp') > 0: - return 1 - return 0 - - def build_devhelp(self): - # type: () -> int - if self.run_generic_build('devhelp') > 0: - return 1 - return 0 - - def build_epub(self): - # type: () -> int - if self.run_generic_build('epub') > 0: - return 1 - return 0 - - def build_latex(self): - # type: () -> int - if self.run_generic_build('latex') > 0: - return 1 - return 0 - def build_latexpdf(self): # type: () -> int if self.run_generic_build('latex') > 0: @@ -171,18 +111,6 @@ class Make(object): with cd(self.builddir_join('latex')): return subprocess.call([self.makecmd, 'all-pdf-ja']) - def build_text(self): - # type: () -> int - if self.run_generic_build('text') > 0: - return 1 - return 0 - - def build_texinfo(self): - # type: () -> int - if self.run_generic_build('texinfo') > 0: - return 1 - return 0 - def build_info(self): # type: () -> int if self.run_generic_build('texinfo') > 0: @@ -197,41 +125,6 @@ class Make(object): return 1 return 0 - def build_changes(self): - # type: () -> int - if self.run_generic_build('changes') > 0: - return 1 - return 0 - - def build_linkcheck(self): - # type: () -> int - res = self.run_generic_build('linkcheck') - return res - - def build_doctest(self): - # type: () -> int - res = self.run_generic_build('doctest') - return res - - def build_coverage(self): - # type: () -> int - if self.run_generic_build('coverage') > 0: - print("Has the coverage extension been enabled?") - return 1 - return 0 - - def build_xml(self): - # type: () -> int - if self.run_generic_build('xml') > 0: - return 1 - return 0 - - def build_pseudoxml(self): - # type: () -> int - if self.run_generic_build('pseudoxml') > 0: - return 1 - return 0 - def run_generic_build(self, builder, doctreedir=None): # type: (unicode, unicode) -> int # compatibility with old Makefile From aa2c5c906566076d3c52c684070b57950b65c7b9 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 28 Dec 2017 20:45:27 +0000 Subject: [PATCH 254/275] Makefile: Remove unnecessary targets Most of these are not necessary now that we're not printing different messages for various builders. Signed-off-by: Stephen Finucane --- sphinx/templates/quickstart/Makefile_t | 92 ++------------------------ 1 file changed, 7 insertions(+), 85 deletions(-) diff --git a/sphinx/templates/quickstart/Makefile_t b/sphinx/templates/quickstart/Makefile_t index 77ce4afe8..70925c471 100644 --- a/sphinx/templates/quickstart/Makefile_t +++ b/sphinx/templates/quickstart/Makefile_t @@ -10,9 +10,10 @@ BUILDDIR = {{ rbuilddir }} # Internal variables. PAPEROPT_a4 = -D latex_elements.papersize=a4 PAPEROPT_letter = -D latex_elements.papersize=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) {{ rsrcdir }} +# $(O) is meant as a shortcut for $(SPHINXOPTS) +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) {{ rsrcdir }} # the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) {{ rsrcdir }} +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) {{ rsrcdir }} .PHONY: help help: @@ -49,50 +50,6 @@ help: clean: rm -rf $(BUILDDIR)/* -.PHONY: html -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - -.PHONY: dirhtml -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - -.PHONY: singlehtml -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - -.PHONY: pickle -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - -.PHONY: json -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - -.PHONY: htmlhelp -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - -.PHONY: qthelp -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - -.PHONY: applehelp -applehelp: - $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp - -.PHONY: devhelp -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - -.PHONY: epub -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - -.PHONY: latex -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - .PHONY: latexpdf latexpdf: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @@ -121,18 +78,6 @@ xelatexpdf: $(MAKE) PDFLATEX=xelatex -C $(BUILDDIR)/latex all-pdf @echo "xelatex finished; the PDF files are in $(BUILDDIR)/latex." -.PHONY: text -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - -.PHONY: man -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - -.PHONY: texinfo -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - .PHONY: info info: $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @@ -144,31 +89,8 @@ info: gettext: $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale -.PHONY: changes -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - -.PHONY: linkcheck -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - -.PHONY: doctest -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - -.PHONY: coverage -coverage: - $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage - -.PHONY: xml -xml: - $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml - -.PHONY: pseudoxml -pseudoxml: - $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml - -.PHONY: dummy -dummy: - $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy +# Catch-all target: route all unknown targets to Sphinx +.PHONY: Makefile +%: Makefile + $(SPHINXBUILD) -b "$@" $(ALLSPHINXOPTS) "$(BUILDDIR)/$@" From 6f9a262f45a6c7f297bf0c6c4b8a642d0bb8f02a Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 28 Dec 2017 20:45:43 +0000 Subject: [PATCH 255/275] make.bat: Remove unnecessary targets As with the Makefile previously, these are not necessary now that we're not printing anything different for various builders. Signed-off-by: Stephen Finucane --- sphinx/templates/quickstart/make.bat_t | 123 +------------------------ 1 file changed, 2 insertions(+), 121 deletions(-) diff --git a/sphinx/templates/quickstart/make.bat_t b/sphinx/templates/quickstart/make.bat_t index 94d28461b..4af8fb8c2 100644 --- a/sphinx/templates/quickstart/make.bat_t +++ b/sphinx/templates/quickstart/make.bat_t @@ -50,7 +50,6 @@ if "%1" == "clean" ( goto end ) - REM Check if sphinx-build is available and fallback to Python version if any %SPHINXBUILD% 1>NUL 2>NUL if errorlevel 9009 goto sphinx_python @@ -74,67 +73,6 @@ if errorlevel 9009 ( :sphinx_ok - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "singlehtml" ( - %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "devhelp" ( - %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "epub" ( - %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - if errorlevel 1 exit /b 1 - goto end -) - if "%1" == "latexpdf" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex cd %BUILDDIR%/latex @@ -155,71 +93,14 @@ if "%1" == "latexpdfja" ( goto end ) -if "%1" == "text" ( - %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "man" ( - %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "texinfo" ( - %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo - if errorlevel 1 exit /b 1 - goto end -) - if "%1" == "gettext" ( %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale if errorlevel 1 exit /b 1 goto end ) -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "coverage" ( - %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "xml" ( - %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "pseudoxml" ( - %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml - if errorlevel 1 exit /b 1 - goto end -) - -if "%1" == "dummy" ( - %SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy - if errorlevel 1 exit /b 1 - goto end -) +%SPHINXBUILD% -b %1 %ALLSPHINXOPTS% %BUILDDIR%/%1 +goto end :end popd From f6a045d1714f122d9579f6bd71d0599b8a6d7acb Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 28 Dec 2017 20:45:50 +0000 Subject: [PATCH 256/275] Makefile: Make SOURCEDIR configurable It's unlikely that anyone will need to do this but at least give them the opportunity. Signed-off-by: Stephen Finucane --- sphinx/templates/quickstart/Makefile_t | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sphinx/templates/quickstart/Makefile_t b/sphinx/templates/quickstart/Makefile_t index 70925c471..bf752404e 100644 --- a/sphinx/templates/quickstart/Makefile_t +++ b/sphinx/templates/quickstart/Makefile_t @@ -5,15 +5,16 @@ SPHINXOPTS ?= SPHINXBUILD ?= sphinx-build PAPER ?= +SOURCEDIR = {{ rsrcdir }} BUILDDIR = {{ rbuilddir }} # Internal variables. PAPEROPT_a4 = -D latex_elements.papersize=a4 PAPEROPT_letter = -D latex_elements.papersize=letter # $(O) is meant as a shortcut for $(SPHINXOPTS) -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) {{ rsrcdir }} +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) $(SOURCEDIR) # the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) {{ rsrcdir }} +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) $(SOURCEDIR) .PHONY: help help: From b16fd2ce0191ada6158b87faf1473bd00315ec3d Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 28 Dec 2017 21:00:38 +0000 Subject: [PATCH 257/275] make.bat: Make SOURCEDIR configurable It's unlikely that anyone will need to do this but at least give them the opportunity. Signed-off-by: Stephen Finucane --- sphinx/templates/quickstart/make.bat_t | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sphinx/templates/quickstart/make.bat_t b/sphinx/templates/quickstart/make.bat_t index 4af8fb8c2..6e8665a49 100644 --- a/sphinx/templates/quickstart/make.bat_t +++ b/sphinx/templates/quickstart/make.bat_t @@ -8,8 +8,9 @@ if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR={{ rbuilddir }} -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% {{ rsrcdir }} -set I18NSPHINXOPTS=%SPHINXOPTS% {{ rsrcdir }} +set SOURCEDIR={{ rsrcdir }} +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% %SOURCEDIR% +set I18NSPHINXOPTS=%SPHINXOPTS% %SOURCEDIR% if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_elements.papersize=%PAPER% %ALLSPHINXOPTS% set I18NSPHINXOPTS=-D latex_elements.papersize=%PAPER% %I18NSPHINXOPTS% From 32aa664bdf892817f876a9689d7c31da168cf393 Mon Sep 17 00:00:00 2001 From: deoren Date: Thu, 11 Jan 2018 15:19:04 -0600 Subject: [PATCH 258/275] Small label/comma fix --- doc/intro.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/intro.rst b/doc/intro.rst index d3b191700..a789145fe 100644 --- a/doc/intro.rst +++ b/doc/intro.rst @@ -3,7 +3,7 @@ Introduction This is the documentation for the Sphinx documentation builder. Sphinx is a tool that translates a set of reStructuredText_ source files into various output -formats, automatically producing cross-references, indices etc. That is, if +formats, automatically producing cross-references, indices, etc. That is, if you have a directory containing a bunch of reST-formatted documents (and possibly subdirectories of docs in there as well), Sphinx can generate a nicely-organized arrangement of HTML files (in some other directory) for easy @@ -38,7 +38,7 @@ to reStructuredText/Sphinx from other documentation systems. code to convert Python-doc-style LaTeX markup to Sphinx reST. * Marcin Wojdyr has written a script to convert Docbook to reST with Sphinx - markup; it is at `Google Code `_. + markup; it is at `GitHub `_. * Christophe de Vienne wrote a tool to convert from Open/LibreOffice documents to Sphinx: `odt2sphinx `_. From 8f2d4bae86164456a32c68d4dda70b84bd26b303 Mon Sep 17 00:00:00 2001 From: jfbu Date: Fri, 12 Jan 2018 12:53:07 +0100 Subject: [PATCH 259/275] Eliminate comma from PDF header when project has no release number --- sphinx/texinputs/sphinx.sty | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 2b41673db..19d0a2e2d 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -504,7 +504,7 @@ \fancyfoot[LE,RO]{{\py@HeaderFamily\thepage}} \fancyfoot[LO]{{\py@HeaderFamily\nouppercase{\rightmark}}} \fancyfoot[RE]{{\py@HeaderFamily\nouppercase{\leftmark}}} - \fancyhead[LE,RO]{{\py@HeaderFamily \@title, \py@release}} + \fancyhead[LE,RO]{{\py@HeaderFamily \@title\sphinxheadercomma\py@release}} \renewcommand{\headrulewidth}{0.4pt} \renewcommand{\footrulewidth}{0.4pt} % define chaptermark with \@chappos when \@chappos is available for Japanese @@ -1401,18 +1401,29 @@ % \date{}. This allows the date to reflect the document's date and % release to specify the release that is documented. % -\newcommand{\py@release}{} -\newcommand{\version}{} +\newcommand{\py@release}{\releasename\space\version} +\newcommand{\version}{}% part of \py@release, used by title page and headers +% these two are not used and not documented: \newcommand{\shortversion}{} +\newcommand{\setshortversion}[1]{\renewcommand{\shortversion}{#1}} +% this one is not documented, but used in sphinxmanual.cls and sphinxhowto.cls \newcommand{\releaseinfo}{} -\newcommand{\releasename}{Release} -\newcommand{\release}[1]{% - \renewcommand{\py@release}{\releasename\space\version}% - \renewcommand{\version}{#1}} -\newcommand{\setshortversion}[1]{% - \renewcommand{\shortversion}{#1}} -\newcommand{\setreleaseinfo}[1]{% - \renewcommand{\releaseinfo}{#1}} +\newcommand{\setreleaseinfo}[1]{\renewcommand{\releaseinfo}{#1}}% not used +% this is inserted via template and #1=release config variable +\newcommand{\release}[1]{\renewcommand{\version}{#1}} +% this is defined by template to 'releasename' latex_elements key +\newcommand{\releasename}{} +% Fix issue in case release and releasename deliberately left blank +\newcommand{\sphinxheadercomma}{, }% used in fancyhdr header definition +\newcommand{\sphinxifemptyorblank}[1]{% +% test after one expansion of macro #1 if contents is empty or spaces + \if&\expandafter\@firstofone\detokenize\expandafter{#1}&% + \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}% +\AtBeginDocument {% + \sphinxifemptyorblank{\releasename} + {\sphinxifemptyorblank{\version}{\let\sphinxheadercomma\empty}{}} + {}% +}% % Allow specification of the author's address separately from the % author's name. This can be used to format them differently, which From 12a8d5c0bdd4c5c784846e76b20dc5b596802be5 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 13 Jan 2018 11:09:27 +0900 Subject: [PATCH 260/275] doc: make looks understandable --- doc/ext/inheritance.rst | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/doc/ext/inheritance.rst b/doc/ext/inheritance.rst index 87bfd9eef..0062a8afa 100644 --- a/doc/ext/inheritance.rst +++ b/doc/ext/inheritance.rst @@ -74,9 +74,8 @@ It adds this directive: If you have specified a module in the inheritance diagram like this:: - .. inheritance-diagram:: - dummy.test - :top-classes: dummy.test.B, dummy.test.C + .. inheritance-diagram:: dummy.test + :top-classes: dummy.test.B, dummy.test.C any base classes which are ancestors to ``top-classes`` and are also defined in the same module will be rendered as stand alone nodes. In this example @@ -86,11 +85,8 @@ It adds this directive: If you don't want class A (or any other ancestors) to be visible then specify only the classes you would like to generate the diagram for like this:: - .. inheritance-diagram:: - dummy.test.D - dummy.test.E - dummy.test.F - :top-classes: dummy.test.B, dummy.test.C + .. inheritance-diagram:: dummy.test.D dummy.test.E dummy.test.F + :top-classes: dummy.test.B, dummy.test.C .. versionchanged:: 1.7 Added ``top-classes`` option to limit the scope of inheritance graphs. From 7292386a03bc23f1dc31da3606af5268d949efe1 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 13 Jan 2018 11:23:33 +0900 Subject: [PATCH 261/275] Fix #3570: autodoc: Do not display typing. module for type hints --- CHANGES | 1 + sphinx/util/inspect.py | 14 +++++++++++--- tests/test_util_inspect.py | 12 ++++++------ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/CHANGES b/CHANGES index cbecd1df1..9f1684579 100644 --- a/CHANGES +++ b/CHANGES @@ -67,6 +67,7 @@ Features added * #4093: sphinx-build creates empty directories for unknown targets/builders * Add ``top-classes`` option for the ``sphinx.ext.inheritance_diagram`` extension to limit the scope of inheritance graphs. +* #3570: autodoc: Do not display 'typing.' module for type hints Features removed ---------------- diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index 62cd1a7e9..8c10b7aa5 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -404,10 +404,18 @@ class Signature(object): if annotation == Ellipsis: return '...' if not isinstance(annotation, type): - return repr(annotation) + qualified_name = repr(annotation) + if qualified_name.startswith('typing.'): # for typing.Union + return qualified_name.split('.', 1)[1] + else: + return qualified_name - qualified_name = (annotation.__module__ + '.' + annotation.__qualname__ # type: ignore - if annotation else repr(annotation)) + if not annotation: + qualified_name = repr(annotation) + elif annotation.__module__ == 'typing': + qualified_name = annotation.__qualname__ # type: ignore + else: + qualified_name = (annotation.__module__ + '.' + annotation.__qualname__) # type: ignore # NOQA if annotation.__module__ == 'builtins': return annotation.__qualname__ # type: ignore diff --git a/tests/test_util_inspect.py b/tests/test_util_inspect.py index f0188cafa..b5d50ed71 100644 --- a/tests/test_util_inspect.py +++ b/tests/test_util_inspect.py @@ -211,15 +211,15 @@ def test_Signature_annotations(): # Generic types with concrete parameters sig = inspect.Signature(f1).format_args() - assert sig == '(x: typing.List[int]) -> typing.List[int]' + assert sig == '(x: List[int]) -> List[int]' # TypeVars and generic types with TypeVars sig = inspect.Signature(f2).format_args() - assert sig == '(x: typing.List[T], y: typing.List[T_co], z: T) -> typing.List[T_contra]' + assert sig == '(x: List[T], y: List[T_co], z: T) -> List[T_contra]' # Union types sig = inspect.Signature(f3).format_args() - assert sig == '(x: typing.Union[str, numbers.Integral]) -> None' + assert sig == '(x: Union[str, numbers.Integral]) -> None' # Quoted annotations sig = inspect.Signature(f4).format_args() @@ -239,14 +239,14 @@ def test_Signature_annotations(): # Callable types sig = inspect.Signature(f8).format_args() - assert sig == '(x: typing.Callable[[int, str], int]) -> None' + assert sig == '(x: Callable[[int, str], int]) -> None' sig = inspect.Signature(f9).format_args() - assert sig == '(x: typing.Callable) -> None' + assert sig == '(x: Callable) -> None' # Tuple types sig = inspect.Signature(f10).format_args() - assert sig == '(x: typing.Tuple[int, str], y: typing.Tuple[int, ...]) -> None' + assert sig == '(x: Tuple[int, str], y: Tuple[int, ...]) -> None' # Instance annotations sig = inspect.Signature(f11).format_args() From 2324dee1432b757abe106851484356e4703d4005 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 13 Jan 2018 14:29:54 +0900 Subject: [PATCH 262/275] Update CHANGES for PR #4235 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index 19c56f35c..9a435bfd4 100644 --- a/CHANGES +++ b/CHANGES @@ -73,6 +73,7 @@ Features added * Add ``top-classes`` option for the ``sphinx.ext.inheritance_diagram`` extension to limit the scope of inheritance graphs. * #4183: doctest: ``:pyversion:`` option also follows PEP-440 specification +* #4235: html: Add :confval:`manpages_url` to make manpage roles to hyperlinks Features removed ---------------- From f2bc93859aea6e076420e8e7696cba1c42e8af06 Mon Sep 17 00:00:00 2001 From: jfbu Date: Sat, 13 Jan 2018 08:53:16 +0100 Subject: [PATCH 263/275] Remove unused and undocumented LaTeX macro ``\shortversion`` --- CHANGES | 2 ++ sphinx/texinputs/sphinx.sty | 7 ++----- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index b3e6283fd..a769e7211 100644 --- a/CHANGES +++ b/CHANGES @@ -95,6 +95,8 @@ Features removed * LaTeX environment ``notice``, use ``sphinxadmonition`` instead * LaTeX ``\sphinxstylethead``, use ``\sphinxstyletheadfamily`` * C++, support of function concepts. Thanks to mickk-on-cpp. +* Not used and previously not documented LaTeX macros ``\shortversion`` + and ``\setshortversion`` Bugs fixed diff --git a/sphinx/texinputs/sphinx.sty b/sphinx/texinputs/sphinx.sty index 19d0a2e2d..075ae408b 100644 --- a/sphinx/texinputs/sphinx.sty +++ b/sphinx/texinputs/sphinx.sty @@ -1403,12 +1403,9 @@ % \newcommand{\py@release}{\releasename\space\version} \newcommand{\version}{}% part of \py@release, used by title page and headers -% these two are not used and not documented: -\newcommand{\shortversion}{} -\newcommand{\setshortversion}[1]{\renewcommand{\shortversion}{#1}} -% this one is not documented, but used in sphinxmanual.cls and sphinxhowto.cls +% \releaseinfo is used on titlepage (sphinxmanual.cls, sphinxhowto.cls) \newcommand{\releaseinfo}{} -\newcommand{\setreleaseinfo}[1]{\renewcommand{\releaseinfo}{#1}}% not used +\newcommand{\setreleaseinfo}[1]{\renewcommand{\releaseinfo}{#1}} % this is inserted via template and #1=release config variable \newcommand{\release}[1]{\renewcommand{\version}{#1}} % this is defined by template to 'releasename' latex_elements key From db361c385156e9ae3b0bd91b6ed3f8524011c22d Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 13 Jan 2018 18:42:48 +0900 Subject: [PATCH 264/275] Update CHANGES for PR #4354 --- CHANGES | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES b/CHANGES index c76b3f1d9..fbb607b2a 100644 --- a/CHANGES +++ b/CHANGES @@ -75,6 +75,8 @@ Features added * #4183: doctest: ``:pyversion:`` option also follows PEP-440 specification * #4235: html: Add :confval:`manpages_url` to make manpage roles to hyperlinks * #3570: autodoc: Do not display 'typing.' module for type hints +* #4354: `sphinx-build` now emits finish message. Builders can modify it + through ``Builder.epilog`` attribute Features removed ---------------- From f57634a8b8f6f656266b2a967cc3e5626ba70659 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 13 Jan 2018 19:08:23 +0900 Subject: [PATCH 265/275] Fix mark up --- CHANGES | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index fbb607b2a..2c05a81fa 100644 --- a/CHANGES +++ b/CHANGES @@ -75,8 +75,8 @@ Features added * #4183: doctest: ``:pyversion:`` option also follows PEP-440 specification * #4235: html: Add :confval:`manpages_url` to make manpage roles to hyperlinks * #3570: autodoc: Do not display 'typing.' module for type hints -* #4354: `sphinx-build` now emits finish message. Builders can modify it - through ``Builder.epilog`` attribute +* #4354: sphinx-build now emits finish message. Builders can modify it through + ``Builder.epilog`` attribute Features removed ---------------- From 4d040abafb9e0626dcf7a420bbe32cbfa0896df6 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 13 Jan 2018 15:18:09 +0900 Subject: [PATCH 266/275] Fix #4079: Add notranslate class to let Google Translate know they are not translatable --- CHANGES | 2 ++ sphinx/ext/jsmath.py | 6 +++--- sphinx/ext/mathjax.py | 4 ++-- sphinx/writers/html.py | 6 +++--- sphinx/writers/html5.py | 6 +++--- tests/test_build_html.py | 16 ++++++++-------- tests/test_build_html5.py | 16 ++++++++-------- tests/test_ext_intersphinx.py | 3 ++- tests/test_ext_math.py | 18 +++++++++--------- tests/test_markup.py | 11 ++++++----- 10 files changed, 46 insertions(+), 42 deletions(-) diff --git a/CHANGES b/CHANGES index 2c05a81fa..eb91109a5 100644 --- a/CHANGES +++ b/CHANGES @@ -77,6 +77,8 @@ Features added * #3570: autodoc: Do not display 'typing.' module for type hints * #4354: sphinx-build now emits finish message. Builders can modify it through ``Builder.epilog`` attribute +* #4079: html: Add ``notranslate`` class to each code-blocks, literals and maths + to let Google Translate know they are not translatable Features removed ---------------- diff --git a/sphinx/ext/jsmath.py b/sphinx/ext/jsmath.py index a74f0641a..0858e4d5d 100644 --- a/sphinx/ext/jsmath.py +++ b/sphinx/ext/jsmath.py @@ -20,14 +20,14 @@ from sphinx.ext.mathbase import get_node_equation_number def html_visit_math(self, node): - self.body.append(self.starttag(node, 'span', '', CLASS='math')) + self.body.append(self.starttag(node, 'span', '', CLASS='math notranslate')) self.body.append(self.encode(node['latex']) + '') raise nodes.SkipNode def html_visit_displaymath(self, node): if node['nowrap']: - self.body.append(self.starttag(node, 'div', CLASS='math')) + self.body.append(self.starttag(node, 'div', CLASS='math notranslate')) self.body.append(self.encode(node['latex'])) self.body.append('') raise nodes.SkipNode @@ -40,7 +40,7 @@ def html_visit_displaymath(self, node): self.body.append('(%s)' % number) self.add_permalink_ref(node, _('Permalink to this equation')) self.body.append('') - self.body.append(self.starttag(node, 'div', CLASS='math')) + self.body.append(self.starttag(node, 'div', CLASS='math notranslate')) else: # but only once! self.body.append('
') diff --git a/sphinx/ext/mathjax.py b/sphinx/ext/mathjax.py index 8698e2801..bfbd34979 100644 --- a/sphinx/ext/mathjax.py +++ b/sphinx/ext/mathjax.py @@ -21,7 +21,7 @@ from sphinx.ext.mathbase import get_node_equation_number def html_visit_math(self, node): - self.body.append(self.starttag(node, 'span', '', CLASS='math')) + self.body.append(self.starttag(node, 'span', '', CLASS='math notranslate')) self.body.append(self.builder.config.mathjax_inline[0] + self.encode(node['latex']) + self.builder.config.mathjax_inline[1] + '') @@ -29,7 +29,7 @@ def html_visit_math(self, node): def html_visit_displaymath(self, node): - self.body.append(self.starttag(node, 'div', CLASS='math')) + self.body.append(self.starttag(node, 'div', CLASS='math notranslate')) if node['nowrap']: self.body.append(self.encode(node['latex'])) self.body.append('
') diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py index 84e7bfbc9..16fc69bea 100644 --- a/sphinx/writers/html.py +++ b/sphinx/writers/html.py @@ -444,7 +444,7 @@ class HTMLTranslator(BaseTranslator): location=(self.builder.current_docname, node.line), **highlight_args ) starttag = self.starttag(node, 'div', suffix='', - CLASS='highlight-%s' % lang) + CLASS='highlight-%s notranslate' % lang) self.body.append(starttag + highlighted + '\n') raise nodes.SkipNode @@ -494,10 +494,10 @@ class HTMLTranslator(BaseTranslator): # type: (nodes.Node) -> None if 'kbd' in node['classes']: self.body.append(self.starttag(node, 'kbd', '', - CLASS='docutils literal')) + CLASS='docutils literal notranslate')) else: self.body.append(self.starttag(node, 'code', '', - CLASS='docutils literal')) + CLASS='docutils literal notranslate')) self.protect_literal_text += 1 def depart_literal(self, node): diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py index 50bf2ea8c..c2810a898 100644 --- a/sphinx/writers/html5.py +++ b/sphinx/writers/html5.py @@ -390,7 +390,7 @@ class HTML5Translator(BaseTranslator): location=(self.builder.current_docname, node.line), **highlight_args ) starttag = self.starttag(node, 'div', suffix='', - CLASS='highlight-%s' % lang) + CLASS='highlight-%s notranslate' % lang) self.body.append(starttag + highlighted + '\n') raise nodes.SkipNode @@ -440,10 +440,10 @@ class HTML5Translator(BaseTranslator): # type: (nodes.Node) -> None if 'kbd' in node['classes']: self.body.append(self.starttag(node, 'kbd', '', - CLASS='docutils literal')) + CLASS='docutils literal notranslate')) else: self.body.append(self.starttag(node, 'code', '', - CLASS='docutils literal')) + CLASS='docutils literal notranslate')) self.protect_literal_text += 1 def depart_literal(self, node): diff --git a/tests/test_build_html.py b/tests/test_build_html.py index 153ff5165..2388b06ec 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -163,21 +163,21 @@ def test_html_warnings(app, warning): (".//pre/span", u'"quotes"'), (".//pre/span", u"'included'"), (".//pre/span[@class='s2']", u'üöä'), - (".//div[@class='inc-pyobj1 highlight-text']//pre", + (".//div[@class='inc-pyobj1 highlight-text notranslate']//pre", r'^class Foo:\n pass\n\s*$'), - (".//div[@class='inc-pyobj2 highlight-text']//pre", + (".//div[@class='inc-pyobj2 highlight-text notranslate']//pre", r'^ def baz\(\):\n pass\n\s*$'), - (".//div[@class='inc-lines highlight-text']//pre", + (".//div[@class='inc-lines highlight-text notranslate']//pre", r'^class Foo:\n pass\nclass Bar:\n$'), - (".//div[@class='inc-startend highlight-text']//pre", + (".//div[@class='inc-startend highlight-text notranslate']//pre", u'^foo = "Including Unicode characters: üöä"\\n$'), - (".//div[@class='inc-preappend highlight-text']//pre", + (".//div[@class='inc-preappend highlight-text notranslate']//pre", r'(?m)^START CODE$'), - (".//div[@class='inc-pyobj-dedent highlight-python']//span", + (".//div[@class='inc-pyobj-dedent highlight-python notranslate']//span", r'def'), - (".//div[@class='inc-tab3 highlight-text']//pre", + (".//div[@class='inc-tab3 highlight-text notranslate']//pre", r'-| |-'), - (".//div[@class='inc-tab8 highlight-python']//pre/span", + (".//div[@class='inc-tab8 highlight-python notranslate']//pre/span", r'-| |-'), ], 'autodoc.html': [ diff --git a/tests/test_build_html5.py b/tests/test_build_html5.py index 4ac70be51..168e516cf 100644 --- a/tests/test_build_html5.py +++ b/tests/test_build_html5.py @@ -72,21 +72,21 @@ def cached_etree_parse(): (".//pre/span", u'"quotes"'), (".//pre/span", u"'included'"), (".//pre/span[@class='s2']", u'üöä'), - (".//div[@class='inc-pyobj1 highlight-text']//pre", + (".//div[@class='inc-pyobj1 highlight-text notranslate']//pre", r'^class Foo:\n pass\n\s*$'), - (".//div[@class='inc-pyobj2 highlight-text']//pre", + (".//div[@class='inc-pyobj2 highlight-text notranslate']//pre", r'^ def baz\(\):\n pass\n\s*$'), - (".//div[@class='inc-lines highlight-text']//pre", + (".//div[@class='inc-lines highlight-text notranslate']//pre", r'^class Foo:\n pass\nclass Bar:\n$'), - (".//div[@class='inc-startend highlight-text']//pre", + (".//div[@class='inc-startend highlight-text notranslate']//pre", u'^foo = "Including Unicode characters: üöä"\\n$'), - (".//div[@class='inc-preappend highlight-text']//pre", + (".//div[@class='inc-preappend highlight-text notranslate']//pre", r'(?m)^START CODE$'), - (".//div[@class='inc-pyobj-dedent highlight-python']//span", + (".//div[@class='inc-pyobj-dedent highlight-python notranslate']//span", r'def'), - (".//div[@class='inc-tab3 highlight-text']//pre", + (".//div[@class='inc-tab3 highlight-text notranslate']//pre", r'-| |-'), - (".//div[@class='inc-tab8 highlight-python']//pre/span", + (".//div[@class='inc-tab8 highlight-python notranslate']//pre/span", r'-| |-'), ], 'autodoc.html': [ diff --git a/tests/test_ext_intersphinx.py b/tests/test_ext_intersphinx.py index 19f8613c6..aef495d30 100644 --- a/tests/test_ext_intersphinx.py +++ b/tests/test_ext_intersphinx.py @@ -236,7 +236,8 @@ def test_missing_reference_cppdomain(tempdir, app, status, warning): html = (app.outdir / 'index.html').text() assert ('' + ' title="(in foo v2.0)">' + '' 'Bar' in html) assert ('\na^2 + b^2 = c^2' in content - assert '
\n\\begin{split}a + 1 < b\\end{split}
' in content + assert '
\na^2 + b^2 = c^2
' in content + assert '
\n\\begin{split}a + 1 < b\\end{split}
' in content assert (u'(1)
\xb6' - u'
\ne^{i\\pi} = 1
' in content) + u'
\ne^{i\\pi} = 1
' in content) assert (u'(2)\xb6' - u'
\n' + u'
\n' u'e^{ix} = \\cos x + i\\sin x
' in content) - assert '
\nn \\in \\mathbb N
' in content - assert '
\na + 1 < b
' in content + assert '
\nn \\in \\mathbb N
' in content + assert '
\na + 1 < b
' in content @pytest.mark.skipif(not has_binary('dvipng'), @@ -89,7 +89,7 @@ def test_mathjax_align(app, status, warning): app.builder.build_all() content = (app.outdir / 'index.html').text() - html = (r'
\s*' + html = (r'
\s*' r'\\\[ \\begin\{align\}\\begin\{aligned\}S \&= \\pi r\^2\\\\' r'V \&= \\frac\{4\}\{3\} \\pi r\^3\\end\{aligned\}\\end\{align\} \\\]
') assert re.search(html, content, re.S) @@ -102,7 +102,7 @@ def test_math_number_all_mathjax(app, status, warning): app.builder.build_all() content = (app.outdir / 'index.html').text() - html = (r'
\s*' + html = (r'
\s*' r'\(1\)\xb6\\\[a\^2\+b\^2=c\^2\\\]
') assert re.search(html, content, re.S) @@ -167,7 +167,7 @@ def test_mathjax_numfig_html(app, status, warning): app.builder.build_all() content = (app.outdir / 'math.html').text() - html = ('
\n' + html = ('
\n' '(1.2)') assert html in content html = ('

Referencing equation ' + ('

' 'code   sample

'), r'\\sphinxcode{\\sphinxupquote{code sample}}', ), @@ -141,7 +141,7 @@ def get_verifier(verify, verify_re): # correct interpretation of code with whitespace 'verify_re', ':samp:`code sample`', - ('

' + ('

' 'code   sample

'), r'\\sphinxcode{\\sphinxupquote{code sample}}', ), @@ -149,7 +149,8 @@ def get_verifier(verify, verify_re): # interpolation of braces in samp and file roles (HTML only) 'verify', ':samp:`a{b}c`', - ('

a' + ('

' + 'a' 'b' 'c

'), '\\sphinxcode{\\sphinxupquote{a\\sphinxstyleemphasis{b}c}}', @@ -173,7 +174,7 @@ def get_verifier(verify, verify_re): # non-interpolation of dashes in option role 'verify_re', ':option:`--with-option`', - ('

' + ('

' '--with-option

$'), r'\\sphinxcode{\\sphinxupquote{-{-}with-option}}$', ), @@ -188,7 +189,7 @@ def get_verifier(verify, verify_re): # ... but not in literal text 'verify', '``"John"``', - ('

' + ('

' '"John"

'), '\\sphinxcode{\\sphinxupquote{"John"}}', ), From fa51a637a82d3cdd0ae58933013414347c341e93 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 13 Jan 2018 21:00:13 +0900 Subject: [PATCH 267/275] shebang line is removed from generated conf.py (refs: #4385) --- CHANGES | 1 + sphinx/templates/quickstart/conf.py_t | 3 --- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGES b/CHANGES index 2c05a81fa..a74447a48 100644 --- a/CHANGES +++ b/CHANGES @@ -21,6 +21,7 @@ Incompatible changes * #4389: output directory will be created after loading extensions * autodoc does not generate warnings messages to the generated document even if :confval:`keep_warnings` is True. They are only emitted to stderr. +* shebang line is removed from generated conf.py Deprecated ---------- diff --git a/sphinx/templates/quickstart/conf.py_t b/sphinx/templates/quickstart/conf.py_t index a1c00f8c7..2583b9891 100644 --- a/sphinx/templates/quickstart/conf.py_t +++ b/sphinx/templates/quickstart/conf.py_t @@ -1,6 +1,3 @@ -{% if PY3 -%} -#!/usr/bin/env python3 -{% endif -%} # -*- coding: utf-8 -*- # # {{ project }} documentation build configuration file, created by From 3663275755ac5e79cce72573d9cea5be88c29ae2 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 13 Jan 2018 21:42:18 +0900 Subject: [PATCH 268/275] Update CHANGES for PR #4245 --- CHANGES | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES b/CHANGES index a74447a48..8096e7d55 100644 --- a/CHANGES +++ b/CHANGES @@ -78,6 +78,7 @@ Features added * #3570: autodoc: Do not display 'typing.' module for type hints * #4354: sphinx-build now emits finish message. Builders can modify it through ``Builder.epilog`` attribute +* #4245: html themes: Add ``language`` to javascript vars list Features removed ---------------- From 87b03bf76fa40d2e3f85ce781dd97727cdd0b5ce Mon Sep 17 00:00:00 2001 From: Tim Hoffmann <2836374+timhoffm@users.noreply.github.com> Date: Sat, 13 Jan 2018 15:52:50 +0100 Subject: [PATCH 269/275] minor conf.py cleanup --- sphinx/templates/quickstart/conf.py_t | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/sphinx/templates/quickstart/conf.py_t b/sphinx/templates/quickstart/conf.py_t index 2583b9891..2f3f71b1e 100644 --- a/sphinx/templates/quickstart/conf.py_t +++ b/sphinx/templates/quickstart/conf.py_t @@ -1,13 +1,12 @@ # -*- coding: utf-8 -*- # -# {{ project }} documentation build configuration file, created by -# sphinx-quickstart on {{ now }}. +# Configuration file for the Sphinx documentation builder. # # This file does only contain a selection of the most common options. For a # full list see the documentation: # http://www.sphinx-doc.org/en/stable/config -# -- Path setup ----------------------------------------------------------- +# -- Path setup -------------------------------------------------------------- # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the @@ -27,7 +26,7 @@ sys.path.insert(0, u'{{ module_path }}') {% endif -%} {% endif %} -# -- Project information -------------------------------------------------- +# -- Project information ----------------------------------------------------- project = u'{{ project_str }}' copyright = u'{{ copyright_str }}' @@ -39,7 +38,7 @@ version = u'{{ version_str }}' release = u'{{ release_str }}' -# -- General configuration ------------------------------------------------ +# -- General configuration --------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. # @@ -82,7 +81,7 @@ exclude_patterns = [{{ exclude_patterns }}] pygments_style = 'sphinx' -# -- Options for HTML output ---------------------------------------------- +# -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. @@ -111,13 +110,13 @@ html_static_path = ['{{ dot }}static'] # html_sidebars = {} -# -- Options for HTMLHelp output ------------------------------------------ +# -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. htmlhelp_basename = '{{ project_fn }}doc' -# -- Options for LaTeX output --------------------------------------------- +# -- Options for LaTeX output ------------------------------------------------ latex_elements = { # The paper size ('letterpaper' or 'a4paper'). @@ -146,7 +145,7 @@ latex_documents = [ ] -# -- Options for manual page output --------------------------------------- +# -- Options for manual page output ------------------------------------------ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). @@ -156,7 +155,7 @@ man_pages = [ ] -# -- Options for Texinfo output ------------------------------------------- +# -- Options for Texinfo output ---------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, @@ -169,7 +168,7 @@ texinfo_documents = [ {%- if epub %} -# -- Options for Epub output ---------------------------------------------- +# -- Options for Epub output ------------------------------------------------- # Bibliographic Dublin Core info. epub_title = project @@ -192,18 +191,18 @@ epub_exclude_files = ['search.html'] {%- if extensions %} -# -- Extension configuration ---------------------------------------------- +# -- Extension configuration ------------------------------------------------- {%- endif %} {%- if 'sphinx.ext.intersphinx' in extensions %} -# -- Options for intersphinx extension ------------------------------------ +# -- Options for intersphinx extension --------------------------------------- # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {'https://docs.python.org/': None} {%- endif %} {%- if 'sphinx.ext.todo' in extensions %} -# -- Options for todo extension ------------------------------------------- +# -- Options for todo extension ---------------------------------------------- # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True From c24dffc5a8e67e87fb6ad79120427f19e5103cf3 Mon Sep 17 00:00:00 2001 From: Robin Jarry Date: Thu, 11 Jan 2018 20:53:35 +0100 Subject: [PATCH 270/275] autodoc: only mock specified modules with their descendants Do not mock the ancestors of the specified modules in autodoc_mock_imports. Only mock the modules themselves and their descendants (as specified in the docs). Fix the test configs accordingly. Signed-off-by: Robin Jarry --- sphinx/ext/autodoc/importer.py | 17 ++++++----------- .../roots/test-root/autodoc_missing_imports.py | 4 ++++ tests/roots/test-root/conf.py | 7 ++++--- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py index 101cb930f..cea1c12bd 100644 --- a/sphinx/ext/autodoc/importer.py +++ b/sphinx/ext/autodoc/importer.py @@ -23,7 +23,7 @@ from sphinx.util.inspect import isenumclass, safe_getattr if False: # For type annotation - from typing import Any, Callable, Dict, Generator, List, Optional, Set # NOQA + from typing import Any, Callable, Dict, Generator, List, Optional # NOQA logger = logging.getLogger(__name__) @@ -84,13 +84,7 @@ class _MockModule(ModuleType): class _MockImporter(object): def __init__(self, names): # type: (List[str]) -> None - self.base_packages = set() # type: Set[str] - for n in names: - # Convert module names: - # ['a.b.c', 'd.e'] - # to a set of base packages: - # set(['a', 'd']) - self.base_packages.add(n.split('.')[0]) + self.names = names self.mocked_modules = [] # type: List[str] # enable hook by adding itself to meta_path sys.meta_path = sys.meta_path + [self] @@ -106,9 +100,10 @@ class _MockImporter(object): def find_module(self, name, path=None): # type: (str, str) -> Any - base_package = name.split('.')[0] - if base_package in self.base_packages: - return self + # check if name is (or is a descendant of) one of our base_packages + for n in self.names: + if n == name or name.startswith(n + '.'): + return self return None def load_module(self, name): diff --git a/tests/roots/test-root/autodoc_missing_imports.py b/tests/roots/test-root/autodoc_missing_imports.py index 0901ce8e2..19d4c6a05 100644 --- a/tests/roots/test-root/autodoc_missing_imports.py +++ b/tests/roots/test-root/autodoc_missing_imports.py @@ -4,6 +4,8 @@ from missing_module import missing_name import missing_package1.missing_module1 from missing_package2 import missing_module2 from missing_package3.missing_module3 import missing_name +import sphinx.missing_module4 +from sphinx.missing_module4 import missing_name2 @missing_name def decoratedFunction(): @@ -16,3 +18,5 @@ class TestAutodoc(object): def decoratedMethod(self): """TestAutodoc::decoratedMethod docstring""" return None + +sphinx.missing_module4.missing_function(len(missing_name2)) diff --git a/tests/roots/test-root/conf.py b/tests/roots/test-root/conf.py index 0753fe19c..04cd87d7b 100644 --- a/tests/roots/test-root/conf.py +++ b/tests/roots/test-root/conf.py @@ -69,9 +69,10 @@ extlinks = {'issue': ('http://bugs.python.org/issue%s', 'issue '), autodoc_mock_imports = [ 'missing_module', - 'missing_package1.missing_module1', - 'missing_package2.missing_module2', - 'missing_package3.missing_module3', + 'missing_package1', + 'missing_package2', + 'missing_package3', + 'sphinx.missing_module4', ] # modify tags from conf.py From 8b74d93ad9c6b6f7dfe129c2481dd1676562b75e Mon Sep 17 00:00:00 2001 From: jfbu Date: Wed, 3 May 2017 23:52:29 +0200 Subject: [PATCH 271/275] Remove unneeded coding from LaTeXTranslator.visit_figure() --- sphinx/writers/latex.py | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 6c86e6174..74b1c52a6 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -1853,28 +1853,14 @@ class LaTeXTranslator(nodes.NodeVisitor): (node['align'] == 'right' and 'r' or 'l', length or '0pt')) self.context.append(ids + '\\end{wrapfigure}\n') elif self.in_minipage: - if ('align' not in node.attributes or - node.attributes['align'] == 'center'): - self.body.append('\n\\begin{center}') - self.context.append('\\end{center}\n') - else: - self.body.append('\n\\begin{flush%s}' % node.attributes['align']) - self.context.append('\\end{flush%s}\n' % node.attributes['align']) + self.body.append('\n\\begin{center}') + self.context.append('\\end{center}\n') else: - if ('align' not in node.attributes or - node.attributes['align'] == 'center'): - # centering does not add vertical space like center. - align = '\n\\centering' - align_end = '' - else: - # TODO non vertical space for other alignments. - align = '\\begin{flush%s}' % node.attributes['align'] - align_end = '\\end{flush%s}' % node.attributes['align'] - self.body.append('\n\\begin{figure}[%s]%s\n' % ( - self.elements['figure_align'], align)) + self.body.append('\n\\begin{figure}[%s]\n\\centering\n' % + self.elements['figure_align']) if any(isinstance(child, nodes.caption) for child in node): self.body.append('\\capstart\n') - self.context.append(ids + align_end + '\\end{figure}\n') + self.context.append(ids + '\\end{figure}\n') def depart_figure(self, node): # type: (nodes.Node) -> None From c399357f38a081cf5f75e98c9627b80928a1c035 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 31 Oct 2017 22:59:01 +0900 Subject: [PATCH 272/275] Show a notice if both tabularcolumns and :widths: are given (refs: #4196) --- doc/markup/misc.rst | 5 +++++ sphinx/writers/latex.py | 3 +++ 2 files changed, 8 insertions(+) diff --git a/doc/markup/misc.rst b/doc/markup/misc.rst index 35ed6375d..51e3a405c 100644 --- a/doc/markup/misc.rst +++ b/doc/markup/misc.rst @@ -323,6 +323,11 @@ following directive exists: Sphinx's merged cells interact well with ``p{width}``, ``\X{a}{b}``, ``Y{f}`` and tabulary's columns. + .. note:: + + :rst:dir:`tabularcolumns` conflicts with ``:widths:`` option of table + directives. If both are specified, ``:widths:`` option will be ignored. + Math ---- diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 6c86e6174..4741de92b 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -1376,6 +1376,9 @@ class LaTeXTranslator(nodes.NodeVisitor): self.table = Table(node) if self.next_table_colspec: self.table.colspec = '{%s}\n' % self.next_table_colspec + if 'colwidths-given' in node.get('classes', []): + logger.info('both tabularcolumns and :widths: option are given. ' + ':widths: is ignored.', location=node) self.next_table_colspec = None def depart_table(self, node): From 0d61b251c5a6d55eb8a0ce6977e72078664e0a06 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 14 Jan 2018 23:10:04 +0900 Subject: [PATCH 273/275] Update CHANGES for PR #4413 --- CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index fe964bb2e..41d512023 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,9 @@ Incompatible changes * autodoc does not generate warnings messages to the generated document even if :confval:`keep_warnings` is True. They are only emitted to stderr. * shebang line is removed from generated conf.py +* #2557: autodoc: :confval:`autodoc_mock_imports` only mocks specified modules + with their descendants. It does not mock their ancestors. If you want to + mock them, please specify the name of ancestors implicitly. Deprecated ---------- From de023f2dc0972fc398975c5614caf89149a2de16 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 14 Jan 2018 23:31:30 +0900 Subject: [PATCH 274/275] Fix #3620: html theme: move DOCUMENTATION_OPTIONS to independent JavaScript file (refs: #3620) --- CHANGES | 2 ++ sphinx/themes/basic/documentation_options.js_t | 9 +++++++++ sphinx/themes/basic/layout.html | 12 +----------- 3 files changed, 12 insertions(+), 11 deletions(-) create mode 100644 sphinx/themes/basic/documentation_options.js_t diff --git a/CHANGES b/CHANGES index 41d512023..26849effa 100644 --- a/CHANGES +++ b/CHANGES @@ -25,6 +25,8 @@ Incompatible changes * #2557: autodoc: :confval:`autodoc_mock_imports` only mocks specified modules with their descendants. It does not mock their ancestors. If you want to mock them, please specify the name of ancestors implicitly. +* #3620: html theme: move DOCUMENTATION_OPTIONS to independent JavaScript file + (refs: #4295) Deprecated ---------- diff --git a/sphinx/themes/basic/documentation_options.js_t b/sphinx/themes/basic/documentation_options.js_t new file mode 100644 index 000000000..e76f55a4e --- /dev/null +++ b/sphinx/themes/basic/documentation_options.js_t @@ -0,0 +1,9 @@ +var DOCUMENTATION_OPTIONS = { + URL_ROOT: '{{ url_root }}', + VERSION: '{{ release|e }}', + LANGUAGE: '{{ language }}', + COLLAPSE_INDEX: false, + FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}', + HAS_SOURCE: {{ has_source|lower }}, + SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}' +}; diff --git a/sphinx/themes/basic/layout.html b/sphinx/themes/basic/layout.html index 050de15df..dc05e980d 100644 --- a/sphinx/themes/basic/layout.html +++ b/sphinx/themes/basic/layout.html @@ -87,17 +87,7 @@ {%- endmacro %} {%- macro script() %} - + {%- for scriptfile in script_files %} {%- endfor %} From eebf9d0a0ecf7fa5bac9da8a6808c38047ca882a Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 12 Oct 2017 22:57:20 +0900 Subject: [PATCH 275/275] Fix #4137: doctest: Make doctest and testcode blocks highlighted --- CHANGES | 2 ++ sphinx/ext/doctest.py | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 26849effa..924773f76 100644 --- a/CHANGES +++ b/CHANGES @@ -86,6 +86,8 @@ Features added * #4245: html themes: Add ``language`` to javascript vars list * #4079: html: Add ``notranslate`` class to each code-blocks, literals and maths to let Google Translate know they are not translatable +* #4137: doctest: doctest block is always highlighted as python console (pycon) +* #4137: doctest: testcode block is always highlighted as python Features removed ---------------- diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py index 1a1c05998..cd35e789a 100644 --- a/sphinx/ext/doctest.py +++ b/sphinx/ext/doctest.py @@ -116,7 +116,11 @@ class TestDirective(Directive): if test is not None: # only save if it differs from code node['test'] = test - if self.name == 'testoutput': + if self.name == 'doctest': + node['language'] = 'pycon' + elif self.name == 'testcode': + node['language'] = 'python' + elif self.name == 'testoutput': # don't try to highlight output node['language'] = 'none' node['options'] = {}