From 7fc43d336574a305cd119981256e93d7a4a2ce7e Mon Sep 17 00:00:00 2001 From: Oliver Jahn Date: Thu, 5 Oct 2017 12:41:05 -0400 Subject: [PATCH 001/139] 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 002/139] 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 003/139] 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 9158a5be1b0af4bd515e7d3c9b56d2151933e8e3 Mon Sep 17 00:00:00 2001 From: Matthew Fernandez Date: Sun, 5 Nov 2017 13:58:27 -0800 Subject: [PATCH 004/139] 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 005/139] 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 006/139] 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 ed1f47e1908b322de1ac0348ad42c61366cd131d Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 1 May 2017 13:09:15 +0900 Subject: [PATCH 007/139] 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 008/139] 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 009/139] 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 010/139] 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 011/139] 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 012/139] 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 013/139] 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 fe07365a8cea7186261930f19b7f15735e545c57 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Fri, 15 Dec 2017 22:17:03 +0900 Subject: [PATCH 014/139] 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 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 015/139] 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 016/139] 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 017/139] 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 018/139] 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 019/139] 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 020/139] 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 021/139] 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 022/139] 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 023/139] 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 024/139] 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 025/139] 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 026/139] 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 027/139] 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 41f9cb200acfa506b8cebed37841fa39a625a719 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 17 Dec 2017 23:44:28 +0900 Subject: [PATCH 028/139] 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 029/139] 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 030/139] 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 031/139] 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 032/139] 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 033/139] 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 034/139] 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 035/139] 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 036/139] 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 037/139] 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 038/139] 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 039/139] 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 040/139] 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 041/139] 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 042/139] 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 043/139] 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 044/139] 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 045/139] 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 046/139] 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 047/139] 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 048/139] 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 049/139] 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 050/139] 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 051/139] 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 052/139] 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 053/139] 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 054/139] 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 221aa470fa26ae369627b1b301cc16de754a44f5 Mon Sep 17 00:00:00 2001 From: Paul V Craven Date: Tue, 19 Dec 2017 17:28:28 -0600 Subject: [PATCH 055/139] 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 056/139] 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 057/139] 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 058/139] 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 059/139] 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 060/139] 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 061/139] 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 062/139] 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 063/139] 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 064/139] 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 065/139] 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 066/139] 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 067/139] 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 068/139] 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 069/139] 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 070/139] 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 071/139] 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 072/139] 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 073/139] 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 074/139] 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 075/139] 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 076/139] 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 077/139] 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 078/139] 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 079/139] 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 080/139] 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 081/139] 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 082/139] 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 083/139] 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 084/139] 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 085/139] 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 086/139] 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 087/139] 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 088/139] 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 089/139] 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 090/139] 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 091/139] 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 092/139] 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 093/139] 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 094/139] 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 095/139] 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 096/139] 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 097/139] 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 098/139] 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 099/139] 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 100/139] 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 101/139] 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 102/139] 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 103/139] 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 104/139] 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 105/139] 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 106/139] 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 107/139] 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 108/139] 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 109/139] 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 110/139] 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 111/139] 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 112/139] 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 113/139] 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 114/139] 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 115/139] 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 116/139] 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 117/139] 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 118/139] 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 119/139] 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 120/139] 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 3736768a59dd1d13b205b894385eadd9791b1ac4 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 6 Jan 2018 13:22:47 +0900 Subject: [PATCH 121/139] 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 122/139] 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 123/139] 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 124/139] 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 125/139] 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 126/139] 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 127/139] 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 128/139] 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 129/139] 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 2ae7f26fe531c29cedfa01e2f0c3595a4c680972 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 7 Jan 2018 12:09:41 +0900 Subject: [PATCH 130/139] 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 131/139] 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 132/139] 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 133/139] 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 134/139] 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 135/139] 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 273f834157a90806e0cd2031e8974c43f9787a6f Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 8 Jan 2018 12:19:08 +0900 Subject: [PATCH 136/139] 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 137/139] 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 6448d9b1536ea03f614cb3cb6a83b7f9bda63039 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 8 Jan 2018 18:03:48 +0900 Subject: [PATCH 138/139] 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 139/139] 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