Merge branch 'master' into refactor_env2

This commit is contained in:
Takeshi KOMIYA 2018-05-12 22:42:29 +09:00 committed by GitHub
commit 5493bc1612
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 265 additions and 220 deletions

View File

@ -29,6 +29,8 @@ Incompatible changes
* #4811: The files under :confval:`html_static_path` are excluded from source
files.
* latex: Use ``\sphinxcite`` for citation references instead ``\hyperref``
* The config value ``viewcode_import`` is renamed to
:confval:`viewcode_follow_imported_members` (refs: #4035)
Deprecated
----------
@ -109,6 +111,8 @@ Bugs fixed
* i18n: message catalogs were reset on each initialization
* #4850: latex: footnote inside footnote was not rendered
* #4945: i18n: fix lang_COUNTRY not fallback correctly for IndexBuilder. Thanks
to Shengjing Zhu.
Testing
--------

View File

@ -17,16 +17,17 @@ from the source to the description will also be inserted.
.. warning::
If :confval:`viewcode_import` is True,
or if the :event:`viewcode-find-source` event does not find source code
for the given module,
``viewcode`` will import the modules being linked to.
If any modules have side effects on import, these will be
executed by ``viewcode`` when ``sphinx-build`` is run.
Basically, ``viewcode`` extension will import the modules being linked to.
If any modules have side effects on import, these will be executed when
``sphinx-build`` is run.
If you document scripts (as opposed to library modules), make sure their
main routine is protected by a ``if __name__ == '__main__'`` condition.
In addition, if you don't want to import the modules by ``viewcode``,
you can tell the location of the location of source code to ``viewcode``
using :event:`viewcode-find-source` event.
This extension works only on HTML related builders like ``html``,
``applehelp``, ``devhelp``, ``htmlhelp``, ``qthelp`` and so on except
``singlehtml``. By default ``epub`` builder doesn't
@ -34,7 +35,7 @@ support this extension (see :confval:`viewcode_enable_epub`).
There is an additional config value:
.. confval:: viewcode_import
.. confval:: viewcode_follow_imported_members
If this is ``True``, viewcode extension will follow alias objects that
imported from another module such as functions, classes and attributes.
@ -43,6 +44,9 @@ There is an additional config value:
.. versionadded:: 1.3
.. versionchanged:: 1.8
Renamed from ``viewcode_import`` to ``viewcode_follow_imported_members``.
.. confval:: viewcode_enable_epub
If this is ``True``, viewcode extension is also enabled even if you use

View File

@ -126,6 +126,11 @@ The following is a list of deprecated interface.
- 4.0
- :meth:`~sphinx.application.Sphinx.add_css_file()`
* - ``viewcode_import`` (config value)
- 1.8
- 3.0
- :confval:`viewcode_follow_imported_members`
* - ``sphinx.writers.latex.Table.caption_footnotetexts``
- 1.8
- 3.0

View File

@ -1061,8 +1061,6 @@ class Sphinx(object):
And it allows keyword arguments as attributes of link tag.
"""
logger.debug('[app] adding stylesheet: %r', filename)
if '://' not in filename:
filename = posixpath.join('_static', filename)
self.registry.add_css_files(filename, **kwargs)
def add_stylesheet(self, filename, alternate=False, title=None):

View File

@ -13,6 +13,8 @@
from collections import namedtuple
from os import path
from six import string_types
from sphinx import package_dir
from sphinx.builders import _epub_base
from sphinx.config import string_classes, ENUM
@ -24,9 +26,10 @@ from sphinx.util.osutil import make_filename
if False:
# For type annotation
from typing import Any, Dict, Iterable, List # NOQA
from typing import Any, Dict, Iterable, List, Tuple # NOQA
from docutils import nodes # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA
logger = logging.getLogger(__name__)
@ -226,6 +229,24 @@ class Epub3Builder(_epub_base.EpubBuilder):
self.files.append(outname)
def convert_epub_css_files(app, config):
# type: (Sphinx, Config) -> None
"""This converts string styled epub_css_files to tuple styled one."""
epub_css_files = [] # type: List[Tuple[unicode, Dict]]
for entry in config.epub_css_files:
if isinstance(entry, string_types):
epub_css_files.append((entry, {}))
else:
try:
filename, attrs = entry
epub_css_files.append((filename, attrs))
except Exception:
logger.warning(__('invalid css_file: %r, ignored'), entry)
continue
config.epub_css_files = epub_css_files # type: ignore
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.add_builder(Epub3Builder)
@ -261,6 +282,9 @@ def setup(app):
app.add_config_value('epub_writing_mode', 'horizontal', 'epub',
ENUM('horizontal', 'vertical'))
# event handlers
app.connect('config-inited', convert_epub_css_files)
return {
'version': 'builtin',
'parallel_read_safe': True,

View File

@ -341,23 +341,17 @@ class StandaloneHTMLBuilder(Builder):
def init_css_files(self):
# type: () -> None
for filename, attrs in self.app.registry.css_files:
self.css_files.append(Stylesheet(filename, **attrs)) # type: ignore
self.add_css_file(filename, **attrs)
for entry in self.get_builder_config('css_files', 'html'):
if isinstance(entry, string_types):
filename = entry
attrs = {}
else:
try:
filename, attrs = entry
except (TypeError, ValueError):
logger.warning('invalid css_file: %r', entry)
continue
for filename, attrs in self.get_builder_config('css_files', 'html'):
self.add_css_file(filename, **attrs)
def add_css_file(self, filename, **kwargs):
# type: (unicode, **unicode) -> None
if '://' not in filename:
filename = posixpath.join('_static', filename)
self.css_files.append(Stylesheet(filename, **attrs)) # type: ignore
self.css_files.append(Stylesheet(filename, **kwargs)) # type: ignore
@property
def default_translator_class(self):
@ -444,9 +438,9 @@ class StandaloneHTMLBuilder(Builder):
# create the search indexer
self.indexer = None
if self.search:
from sphinx.search import IndexBuilder, languages
from sphinx.search import IndexBuilder
lang = self.config.html_search_language or self.config.language
if not lang or lang not in languages:
if not lang:
lang = 'en'
self.indexer = IndexBuilder(self.env, lang,
self.config.html_search_options,
@ -1467,6 +1461,24 @@ class JSONHTMLBuilder(SerializingHTMLBuilder):
SerializingHTMLBuilder.init(self)
def convert_html_css_files(app, config):
# type: (Sphinx, Config) -> None
"""This converts string styled html_css_files to tuple styled one."""
html_css_files = [] # type: List[Tuple[unicode, Dict]]
for entry in config.html_css_files:
if isinstance(entry, string_types):
html_css_files.append((entry, {}))
else:
try:
filename, attrs = entry
html_css_files.append((filename, attrs))
except Exception:
logger.warning(__('invalid css_file: %r, ignored'), entry)
continue
config.html_css_files = html_css_files # type: ignore
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
# builders
@ -1515,6 +1527,9 @@ def setup(app):
app.add_config_value('html_scaled_image_link', True, 'html')
app.add_config_value('html_experimental_html5_writer', None, 'html')
# event handlers
app.connect('config-inited', convert_html_css_files)
return {
'version': 'builtin',
'parallel_read_safe': True,

View File

@ -95,57 +95,57 @@ class Config(object):
config_values = dict(
# general options
project = ('Python', 'env'),
author = ('unknown', 'env'),
copyright = ('', 'html'),
version = ('', 'env'),
release = ('', 'env'),
today = ('', 'env'),
project = ('Python', 'env', []),
author = ('unknown', 'env', []),
copyright = ('', 'html', []),
version = ('', 'env', []),
release = ('', 'env', []),
today = ('', 'env', []),
# the real default is locale-dependent
today_fmt = (None, 'env', string_classes),
language = (None, 'env', string_classes),
locale_dirs = (['locales'], 'env'),
locale_dirs = (['locales'], 'env', []),
figure_language_filename = (u'{root}.{language}{ext}', 'env', [str]),
master_doc = ('contents', 'env'),
master_doc = ('contents', 'env', []),
source_suffix = ({'.rst': 'restructuredtext'}, 'env', Any),
source_encoding = ('utf-8-sig', 'env'),
source_parsers = ({}, 'env'),
exclude_patterns = ([], 'env'),
source_encoding = ('utf-8-sig', 'env', []),
source_parsers = ({}, 'env', []),
exclude_patterns = ([], 'env', []),
default_role = (None, 'env', string_classes),
add_function_parentheses = (True, 'env'),
add_module_names = (True, 'env'),
trim_footnote_reference_space = (False, 'env'),
show_authors = (False, 'env'),
add_function_parentheses = (True, 'env', []),
add_module_names = (True, 'env', []),
trim_footnote_reference_space = (False, 'env', []),
show_authors = (False, 'env', []),
pygments_style = (None, 'html', string_classes),
highlight_language = ('default', 'env'),
highlight_options = ({}, 'env'),
templates_path = ([], 'html'),
highlight_language = ('default', 'env', []),
highlight_options = ({}, 'env', []),
templates_path = ([], 'html', []),
template_bridge = (None, 'html', string_classes),
keep_warnings = (False, 'env'),
suppress_warnings = ([], 'env'),
modindex_common_prefix = ([], 'html'),
keep_warnings = (False, 'env', []),
suppress_warnings = ([], 'env', []),
modindex_common_prefix = ([], 'html', []),
rst_epilog = (None, 'env', string_classes),
rst_prolog = (None, 'env', string_classes),
trim_doctest_flags = (True, 'env'),
trim_doctest_flags = (True, 'env', []),
primary_domain = ('py', 'env', [NoneType]),
needs_sphinx = (None, None, string_classes),
needs_extensions = ({}, None),
manpages_url = (None, 'env'),
nitpicky = (False, None),
nitpick_ignore = ([], None),
numfig = (False, 'env'),
numfig_secnum_depth = (1, 'env'),
numfig_format = ({}, 'env'), # will be initialized in init_numfig_format()
needs_extensions = ({}, None, []),
manpages_url = (None, 'env', []),
nitpicky = (False, None, []),
nitpick_ignore = ([], None, []),
numfig = (False, 'env', []),
numfig_secnum_depth = (1, 'env', []),
numfig_format = ({}, 'env', []), # will be initialized in init_numfig_format()
tls_verify = (True, 'env'),
tls_cacerts = (None, 'env'),
smartquotes = (True, 'env'),
smartquotes_action = ('qDe', 'env'),
tls_verify = (True, 'env', []),
tls_cacerts = (None, 'env', []),
smartquotes = (True, 'env', []),
smartquotes_action = ('qDe', 'env', []),
smartquotes_excludes = ({'languages': ['ja'],
'builders': ['man', 'text']},
'env'),
'env', []),
) # type: Dict[unicode, Tuple]
def __init__(self, *args):
@ -207,7 +207,7 @@ class Config(object):
return value
else:
defvalue = self.values[name][0]
if self.values[name][-1] == Any:
if self.values[name][2] == Any:
return value
elif isinstance(defvalue, dict):
raise ValueError(__('cannot override dictionary config setting %r, '
@ -427,9 +427,7 @@ def check_confval_types(app, config):
that can result in TypeErrors all over the place NB.
"""
for confval in config:
settings = config.values[confval.name]
default = settings[0]
annotations = settings[2] if len(settings) == 3 else ()
default, rebuild, annotations = config.values[confval.name]
if hasattr(default, '__call__'):
default = default(config) # evaluate default value

View File

@ -12,7 +12,7 @@
import re
from docutils import nodes
from docutils.parsers.rst import Directive, directives, roles
from docutils.parsers.rst import directives, roles
from sphinx import addnodes
from sphinx.util.docfields import DocFieldTransformer
@ -217,7 +217,7 @@ class DefaultRole(SphinxDirective):
return messages
class DefaultDomain(Directive):
class DefaultDomain(SphinxDirective):
"""
Directive to (re-)set the default domain for this source file.
"""

View File

@ -13,7 +13,7 @@ import re
from copy import deepcopy
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst import directives
from six import iteritems, text_type
from sphinx import addnodes
@ -24,6 +24,7 @@ from sphinx.locale import _, __
from sphinx.roles import XRefRole
from sphinx.util import logging
from sphinx.util.docfields import Field, GroupedField
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import make_refnode
from sphinx.util.pycompat import UnicodeMixin
@ -5828,7 +5829,7 @@ class CPPEnumeratorObject(CPPObject):
return parser.parse_declaration("enumerator")
class CPPNamespaceObject(Directive):
class CPPNamespaceObject(SphinxDirective):
"""
This directive is just to tell Sphinx that we're documenting stuff in
namespace foo.
@ -5846,13 +5847,12 @@ class CPPNamespaceObject(Directive):
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
rootSymbol = env.domaindata['cpp']['root_symbol']
rootSymbol = self.env.domaindata['cpp']['root_symbol']
if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
symbol = rootSymbol
stack = [] # type: List[Symbol]
else:
parser = DefinitionParser(self.arguments[0], self, env.config)
parser = DefinitionParser(self.arguments[0], self, self.config)
try:
ast = parser.parse_namespace_object()
parser.assert_end()
@ -5862,13 +5862,13 @@ class CPPNamespaceObject(Directive):
ast = ASTNamespace(name, None)
symbol = rootSymbol.add_name(ast.nestedName, ast.templatePrefix)
stack = [symbol]
env.temp_data['cpp:parent_symbol'] = symbol
env.temp_data['cpp:namespace_stack'] = stack
env.ref_context['cpp:parent_key'] = symbol.get_lookup_key()
self.env.temp_data['cpp:parent_symbol'] = symbol
self.env.temp_data['cpp:namespace_stack'] = stack
self.env.ref_context['cpp:parent_key'] = symbol.get_lookup_key()
return []
class CPPNamespacePushObject(Directive):
class CPPNamespacePushObject(SphinxDirective):
has_content = False
required_arguments = 1
optional_arguments = 0
@ -5881,10 +5881,9 @@ class CPPNamespacePushObject(Directive):
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
return []
parser = DefinitionParser(self.arguments[0], self, env.config)
parser = DefinitionParser(self.arguments[0], self, self.config)
try:
ast = parser.parse_namespace_object()
parser.assert_end()
@ -5892,19 +5891,19 @@ class CPPNamespacePushObject(Directive):
self.warn(e.description)
name = _make_phony_error_name()
ast = ASTNamespace(name, None)
oldParent = env.temp_data.get('cpp:parent_symbol', None)
oldParent = self.env.temp_data.get('cpp:parent_symbol', None)
if not oldParent:
oldParent = env.domaindata['cpp']['root_symbol']
oldParent = self.env.domaindata['cpp']['root_symbol']
symbol = oldParent.add_name(ast.nestedName, ast.templatePrefix)
stack = env.temp_data.get('cpp:namespace_stack', [])
stack = self.env.temp_data.get('cpp:namespace_stack', [])
stack.append(symbol)
env.temp_data['cpp:parent_symbol'] = symbol
env.temp_data['cpp:namespace_stack'] = stack
env.ref_context['cpp:parent_key'] = symbol.get_lookup_key()
self.env.temp_data['cpp:parent_symbol'] = symbol
self.env.temp_data['cpp:namespace_stack'] = stack
self.env.ref_context['cpp:parent_key'] = symbol.get_lookup_key()
return []
class CPPNamespacePopObject(Directive):
class CPPNamespacePopObject(SphinxDirective):
has_content = False
required_arguments = 0
optional_arguments = 0
@ -5917,8 +5916,7 @@ class CPPNamespacePopObject(Directive):
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
stack = env.temp_data.get('cpp:namespace_stack', None)
stack = self.env.temp_data.get('cpp:namespace_stack', None)
if not stack or len(stack) == 0:
self.warn("C++ namespace pop on empty stack. Defaulting to gobal scope.")
stack = []
@ -5927,10 +5925,10 @@ class CPPNamespacePopObject(Directive):
if len(stack) > 0:
symbol = stack[-1]
else:
symbol = env.domaindata['cpp']['root_symbol']
env.temp_data['cpp:parent_symbol'] = symbol
env.temp_data['cpp:namespace_stack'] = stack
env.ref_context['cpp:parent_key'] = symbol.get_lookup_key()
symbol = self.env.domaindata['cpp']['root_symbol']
self.env.temp_data['cpp:parent_symbol'] = symbol
self.env.temp_data['cpp:namespace_stack'] = stack
self.env.ref_context['cpp:parent_key'] = symbol.get_lookup_key()
return []

View File

@ -10,7 +10,7 @@
"""
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst import directives
from sphinx import addnodes
from sphinx.directives import ObjectDescription
@ -19,6 +19,7 @@ from sphinx.domains.python import _pseudo_parse_arglist
from sphinx.locale import _
from sphinx.roles import XRefRole
from sphinx.util.docfields import Field, GroupedField, TypedField
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import make_refnode
if False:
@ -220,7 +221,7 @@ class JSConstructor(JSCallable):
allow_nesting = True
class JSModule(Directive):
class JSModule(SphinxDirective):
"""
Directive to mark description of a new JavaScript module.
@ -249,16 +250,15 @@ class JSModule(Directive):
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
mod_name = self.arguments[0].strip()
env.ref_context['js:module'] = mod_name
self.env.ref_context['js:module'] = mod_name
noindex = 'noindex' in self.options
ret = []
if not noindex:
env.domaindata['js']['modules'][mod_name] = env.docname
self.env.domaindata['js']['modules'][mod_name] = self.env.docname
# Make a duplicate entry in 'objects' to facilitate searching for
# the module in JavaScriptDomain.find_obj()
env.domaindata['js']['objects'][mod_name] = (env.docname, 'module')
self.env.domaindata['js']['objects'][mod_name] = (self.env.docname, 'module')
targetnode = nodes.target('', '', ids=['module-' + mod_name],
ismod=True)
self.state.document.note_explicit_target(targetnode)

View File

@ -12,7 +12,7 @@
import re
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst import directives
from six import iteritems
from sphinx import addnodes, locale
@ -23,6 +23,7 @@ from sphinx.locale import _, __
from sphinx.roles import XRefRole
from sphinx.util import logging
from sphinx.util.docfields import Field, GroupedField, TypedField
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import make_refnode
if False:
@ -555,7 +556,7 @@ class PyDecoratorMethod(PyDecoratorMixin, PyClassmember):
return PyClassmember.run(self)
class PyModule(Directive):
class PyModule(SphinxDirective):
"""
Directive to mark description of a new module.
"""
@ -573,19 +574,18 @@ class PyModule(Directive):
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
modname = self.arguments[0].strip()
noindex = 'noindex' in self.options
env.ref_context['py:module'] = modname
self.env.ref_context['py:module'] = modname
ret = []
if not noindex:
env.domaindata['py']['modules'][modname] = (env.docname,
self.env.domaindata['py']['modules'][modname] = (self.env.docname,
self.options.get('synopsis', ''),
self.options.get('platform', ''),
'deprecated' in self.options)
# make a duplicate entry in 'objects' to facilitate searching for
# the module in PythonDomain.find_obj()
env.domaindata['py']['objects'][modname] = (env.docname, 'module')
self.env.domaindata['py']['objects'][modname] = (self.env.docname, 'module')
targetnode = nodes.target('', '', ids=['module-' + modname],
ismod=True)
self.state.document.note_explicit_target(targetnode)
@ -599,7 +599,7 @@ class PyModule(Directive):
return ret
class PyCurrentModule(Directive):
class PyCurrentModule(SphinxDirective):
"""
This directive is just to tell Sphinx that we're documenting
stuff in module foo, but links to module foo won't lead here.
@ -613,12 +613,11 @@ class PyCurrentModule(Directive):
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
modname = self.arguments[0].strip()
if modname == 'None':
env.ref_context.pop('py:module', None)
self.env.ref_context.pop('py:module', None)
else:
env.ref_context['py:module'] = modname
self.env.ref_context['py:module'] = modname
return []

View File

@ -15,7 +15,7 @@ import warnings
from copy import copy
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst import directives
from docutils.statemachine import ViewList
from six import iteritems
@ -26,11 +26,13 @@ from sphinx.domains import Domain, ObjType
from sphinx.locale import _, __
from sphinx.roles import XRefRole
from sphinx.util import ws_re, logging, docname_join
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import clean_astext, make_refnode
if False:
# For type annotation
from typing import Any, Callable, Dict, Iterator, List, Tuple, Type, Union # NOQA
from docutils.parsers.rst import Directive # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
@ -107,7 +109,7 @@ class EnvVarXRefRole(XRefRole):
return [indexnode, targetnode, node], []
class Target(Directive):
class Target(SphinxDirective):
"""
Generic target for user-defined cross-reference types.
"""
@ -121,7 +123,6 @@ class Target(Directive):
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
# normalize whitespace in fullname like XRefRole does
fullname = ws_re.sub(' ', self.arguments[0].strip())
targetname = '%s-%s' % (self.name, fullname)
@ -141,8 +142,8 @@ class Target(Directive):
name = self.name
if ':' in self.name:
_, name = self.name.split(':', 1)
env.domaindata['std']['objects'][name, fullname] = \
env.docname, targetname
self.env.domaindata['std']['objects'][name, fullname] = \
self.env.docname, targetname
return ret
@ -204,7 +205,7 @@ class Cmdoption(ObjectDescription):
signode['ids'][0], '', None))
class Program(Directive):
class Program(SphinxDirective):
"""
Directive to name the program for which options are documented.
"""
@ -217,12 +218,11 @@ class Program(Directive):
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
program = ws_re.sub('-', self.arguments[0].strip())
if program == 'None':
env.ref_context.pop('std:program', None)
self.env.ref_context.pop('std:program', None)
else:
env.ref_context['std:program'] = program
self.env.ref_context['std:program'] = program
return []
@ -270,7 +270,7 @@ def make_glossary_term(env, textnodes, index_key, source, lineno, new_id=None):
return term
class Glossary(Directive):
class Glossary(SphinxDirective):
"""
Directive to create a glossary with cross-reference targets for :term:
roles.
@ -286,7 +286,6 @@ class Glossary(Directive):
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
node = addnodes.glossary()
node.document = self.state.document
@ -358,7 +357,7 @@ class Glossary(Directive):
textnodes, sysmsg = self.state.inline_text(parts[0], lineno)
# use first classifier as a index key
term = make_glossary_term(env, textnodes, parts[1], source, lineno)
term = make_glossary_term(self.env, textnodes, parts[1], source, lineno)
term.rawsource = line
system_messages.extend(sysmsg)
termtexts.append(term.astext())
@ -403,7 +402,7 @@ def token_xrefs(text):
return retnodes
class ProductionList(Directive):
class ProductionList(SphinxDirective):
"""
Directive to list grammar productions.
"""
@ -416,8 +415,7 @@ class ProductionList(Directive):
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
objects = env.domaindata['std']['objects']
objects = self.env.domaindata['std']['objects']
node = addnodes.productionlist()
messages = [] # type: List[nodes.Node]
i = 0
@ -438,7 +436,7 @@ class ProductionList(Directive):
if idname not in self.state.document.ids:
subnode['ids'].append(idname)
self.state.document.note_implicit_target(subnode, subnode)
objects['token', subnode['tokenname']] = env.docname, idname
objects['token', subnode['tokenname']] = self.env.docname, idname
subnode.extend(token_xrefs(tokens))
node.append(subnode)
return [node] + messages

View File

@ -17,7 +17,7 @@ from collections import defaultdict
from copy import copy
from os import path
from docutils.utils import Reporter, get_source_line
from docutils.utils import get_source_line
from six import BytesIO, next
from six.moves import cPickle as pickle
@ -30,7 +30,7 @@ from sphinx.locale import __
from sphinx.transforms import SphinxTransformer
from sphinx.util import get_matching_docs, FilenameUniqDict
from sphinx.util import logging
from sphinx.util.docutils import WarningStream
from sphinx.util.docutils import LoggingReporter
from sphinx.util.i18n import find_catalog_files
from sphinx.util.matching import compile_matchers
from sphinx.util.nodes import is_translatable
@ -599,7 +599,7 @@ class BuildEnvironment(object):
with open(doctree_filename, 'rb') as f:
doctree = pickle.load(f)
doctree.settings.env = self
doctree.reporter = Reporter(self.doc2path(docname), 2, 5, stream=WarningStream())
doctree.reporter = LoggingReporter(self.doc2path(docname))
return doctree
def get_and_resolve_doctree(self, docname, builder, doctree=None,

View File

@ -1538,15 +1538,3 @@ def setup(app):
app.add_event('autodoc-skip-member')
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
class testcls:
"""test doc string"""
def __getattr__(self, x):
# type: (Any) -> Any
return x
def __setattr__(self, x, y):
# type: (Any, Any) -> None
"""Attr setter."""

View File

@ -8,13 +8,12 @@
"""
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 Options, get_documenters
from sphinx.util import logging
from sphinx.util.docutils import switch_source_input
from sphinx.util.docutils import SphinxDirective, switch_source_input
from sphinx.util.nodes import nested_parse_with_titles
if False:
@ -91,7 +90,7 @@ def parse_generated_content(state, content, documenter):
return node.children
class AutodocDirective(Directive):
class AutodocDirective(SphinxDirective):
"""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
@ -105,7 +104,6 @@ class AutodocDirective(Directive):
def run(self):
# type: () -> List[nodes.Node]
env = self.state.document.settings.env
reporter = self.state.document.reporter
try:
@ -116,11 +114,11 @@ class AutodocDirective(Directive):
# look up target Documenter
objtype = self.name[4:] # strip prefix (auto-).
doccls = get_documenters(env.app)[objtype]
doccls = get_documenters(self.env.app)[objtype]
# process the options with the selected documenter's option_spec
try:
documenter_options = process_documenter_options(doccls, env.config, self.options)
documenter_options = process_documenter_options(doccls, self.config, self.options)
except (KeyError, ValueError, TypeError) as exc:
# an option is either unknown or has a wrong type
logger.error('An option to %s is either unknown or has an invalid value: %s' %
@ -128,7 +126,7 @@ class AutodocDirective(Directive):
return []
# generate the output
params = DocumenterBridge(env, reporter, documenter_options, lineno)
params = DocumenterBridge(self.env, reporter, documenter_options, lineno)
documenter = doccls(params, self.arguments[0])
documenter.generate(more_content=self.content)
if not params.result:

View File

@ -62,7 +62,7 @@ import warnings
from types import ModuleType
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst import directives
from docutils.parsers.rst.states import RSTStateMachine, state_classes
from docutils.statemachine import ViewList
from six import string_types
@ -78,7 +78,7 @@ from sphinx.ext.autodoc.importer import import_module
from sphinx.locale import __
from sphinx.pycode import ModuleAnalyzer, PycodeError
from sphinx.util import import_object, rst, logging
from sphinx.util.docutils import NullReporter, new_document
from sphinx.util.docutils import NullReporter, SphinxDirective, new_document
if False:
# For type annotation
@ -220,7 +220,7 @@ def get_documenter(*args):
# -- .. autosummary:: ----------------------------------------------------------
class Autosummary(Directive):
class Autosummary(SphinxDirective):
"""
Pretty table containing short signatures and summaries of functions etc.
@ -244,7 +244,6 @@ class Autosummary(Directive):
def run(self):
# type: () -> List[nodes.Node]
self.env = env = self.state.document.settings.env
self.genopt = Options()
self.warnings = [] # type: List[nodes.Node]
self.result = ViewList()
@ -255,14 +254,14 @@ class Autosummary(Directive):
nodes = self.get_table(items)
if 'toctree' in self.options:
dirname = posixpath.dirname(env.docname)
dirname = posixpath.dirname(self.env.docname)
tree_prefix = self.options['toctree'].strip()
docnames = []
for name, sig, summary, real_name in items:
docname = posixpath.join(tree_prefix, real_name)
docname = posixpath.normpath(posixpath.join(dirname, docname))
if docname not in env.found_docs:
if docname not in self.env.found_docs:
self.warn('toctree references unknown document %r'
% docname)
docnames.append(docname)
@ -283,9 +282,7 @@ class Autosummary(Directive):
"""Try to import the given names, and return a list of
``[(name, signature, summary_string, real_name), ...]``.
"""
env = self.state.document.settings.env
prefixes = get_import_prefixes_from_env(env)
prefixes = get_import_prefixes_from_env(self.env)
items = [] # type: List[Tuple[unicode, unicode, unicode, unicode]]

View File

@ -19,7 +19,7 @@ import time
from os import path
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst import directives
from packaging.specifiers import SpecifierSet, InvalidSpecifier
from packaging.version import Version
from six import itervalues, StringIO, binary_type, text_type, PY2
@ -29,6 +29,7 @@ from sphinx.builders import Builder
from sphinx.locale import __
from sphinx.util import force_decode, logging
from sphinx.util.console import bold # type: ignore
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import set_source_info
from sphinx.util.osutil import fs_encoding, relpath
@ -77,7 +78,7 @@ def is_allowed_version(spec, version):
# set up the necessary directives
class TestDirective(Directive):
class TestDirective(SphinxDirective):
"""
Base class for doctest-related directives.
"""

View File

@ -18,7 +18,7 @@ from os import path
from subprocess import Popen, PIPE
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst import directives
from docutils.statemachine import ViewList
from six import text_type
@ -26,11 +26,13 @@ import sphinx
from sphinx.errors import SphinxError
from sphinx.locale import _, __
from sphinx.util import logging
from sphinx.util.docutils import SphinxDirective
from sphinx.util.i18n import search_image_for_language
from sphinx.util.osutil import ensuredir, ENOENT, EPIPE, EINVAL
if False:
# For type annotation
from docutils.parsers.rst import Directive # NOQA
from typing import Any, Dict, List, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
@ -111,7 +113,7 @@ def align_spec(argument):
return directives.choice(argument, ('left', 'center', 'right'))
class Graphviz(Directive):
class Graphviz(SphinxDirective):
"""
Directive to insert arbitrary dot markup.
"""
@ -135,12 +137,11 @@ class Graphviz(Directive):
return [document.reporter.warning(
__('Graphviz directive cannot have both content and '
'a filename argument'), line=self.lineno)]
env = self.state.document.settings.env
argument = search_image_for_language(self.arguments[0], env)
rel_filename, filename = env.relfn2path(argument)
env.note_dependency(rel_filename)
argument = search_image_for_language(self.arguments[0], self.env)
rel_filename, filename = self.env.relfn2path(argument)
self.env.note_dependency(rel_filename)
try:
with codecs.open(filename, 'r', 'utf-8') as fp:
with codecs.open(filename, 'r', 'utf-8') as fp: # type: ignore
dotcode = fp.read()
except (IOError, OSError):
return [document.reporter.warning(
@ -170,7 +171,7 @@ class Graphviz(Directive):
return [node]
class GraphvizSimple(Directive):
class GraphvizSimple(SphinxDirective):
"""
Directive to insert arbitrary dot markup.
"""

View File

@ -21,9 +21,9 @@
"""
from docutils import nodes
from docutils.parsers.rst import Directive
import sphinx
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import set_source_info
if False:
@ -36,7 +36,7 @@ class ifconfig(nodes.Element):
pass
class IfConfig(Directive):
class IfConfig(SphinxDirective):
has_content = True
required_arguments = 1

View File

@ -42,7 +42,7 @@ import sys
from hashlib import md5
from docutils import nodes
from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst import directives
from six import text_type
from six.moves import builtins
@ -51,6 +51,7 @@ from sphinx.ext.graphviz import render_dot_html, render_dot_latex, \
render_dot_texinfo, figure_wrapper
from sphinx.pycode import ModuleAnalyzer
from sphinx.util import force_decode
from sphinx.util.docutils import SphinxDirective
if False:
# For type annotation
@ -322,7 +323,7 @@ class inheritance_diagram(nodes.General, nodes.Element):
pass
class InheritanceDiagram(Directive):
class InheritanceDiagram(SphinxDirective):
"""
Run when the inheritance_diagram directive is first encountered.
"""
@ -341,9 +342,8 @@ class InheritanceDiagram(Directive):
# type: () -> List[nodes.Node]
node = inheritance_diagram()
node.document = self.state.document
env = self.state.document.settings.env
class_names = self.arguments[0].split()
class_role = env.get_domain('py').role('class')
class_role = self.env.get_domain('py').role('class')
# Store the original content for use as a hash
node['parts'] = self.options.get('parts', 0)
node['content'] = ', '.join(class_names)
@ -356,10 +356,10 @@ class InheritanceDiagram(Directive):
# Create a graph starting with the list of classes
try:
graph = InheritanceGraph(
class_names, env.ref_context.get('py:module'),
class_names, self.env.ref_context.get('py:module'),
parts=node['parts'],
private_bases='private-bases' in self.options,
aliases=env.config.inheritance_alias,
aliases=self.config.inheritance_alias,
top_classes=node['top-classes'])
except InheritanceException as err:
return [node.document.reporter.warning(err.args[0],

View File

@ -11,13 +11,14 @@
from docutils import nodes, utils
from docutils.nodes import make_id
from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst import directives
from sphinx.config import string_classes
from sphinx.domains import Domain
from sphinx.locale import __
from sphinx.roles import XRefRole
from sphinx.util import logging
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import make_refnode, set_source_info
if False:
@ -212,7 +213,7 @@ def is_in_section_title(node):
return False
class MathDirective(Directive):
class MathDirective(SphinxDirective):
has_content = True
required_arguments = 0
@ -238,7 +239,7 @@ class MathDirective(Directive):
if 'label' in self.options:
node['label'] = self.options['label']
node['nowrap'] = 'nowrap' in self.options
node['docname'] = self.state.document.settings.env.docname
node['docname'] = self.env.docname
ret = [node]
set_source_info(self, node)
if hasattr(self, 'src'):
@ -249,21 +250,20 @@ class MathDirective(Directive):
def add_target(self, ret):
# type: (List[nodes.Node]) -> None
node = ret[0]
env = self.state.document.settings.env
# assign label automatically if math_number_all enabled
if node['label'] == '' or (env.config.math_number_all and not node['label']):
seq = env.new_serialno('sphinx.ext.math#equations')
node['label'] = "%s:%d" % (env.docname, seq)
if node['label'] == '' or (self.config.math_number_all and not node['label']):
seq = self.env.new_serialno('sphinx.ext.math#equations')
node['label'] = "%s:%d" % (self.env.docname, seq)
# no targets and numbers are needed
if not node['label']:
return
# register label to domain
domain = env.get_domain('math')
domain = self.env.get_domain('math')
try:
eqno = domain.add_equation(env, env.docname, node['label'])
eqno = domain.add_equation(self.env, self.env.docname, node['label']) # type: ignore # NOQA
node['number'] = eqno
# add target node

View File

@ -13,7 +13,6 @@
"""
from docutils import nodes
from docutils.parsers.rst import Directive
from docutils.parsers.rst import directives
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
@ -21,6 +20,7 @@ import sphinx
from sphinx.environment import NoUri
from sphinx.locale import _, __
from sphinx.util import logging
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import set_source_info
from sphinx.util.texescape import tex_escape_map
@ -41,7 +41,7 @@ class todolist(nodes.General, nodes.Element):
pass
class Todo(BaseAdmonition):
class Todo(BaseAdmonition, SphinxDirective):
"""
A todo entry, displayed (if configured) in the form of an admonition.
"""
@ -67,10 +67,9 @@ class Todo(BaseAdmonition):
todo.insert(0, nodes.title(text=_('Todo')))
set_source_info(self, todo)
env = self.state.document.settings.env
targetid = 'index-%s' % env.new_serialno('index')
targetid = 'index-%s' % self.env.new_serialno('index')
# Stash the target to be retrieved later in latex_visit_todo_node.
todo['targetref'] = '%s:%s' % (env.docname, targetid)
todo['targetref'] = '%s:%s' % (self.env.docname, targetid)
targetnode = nodes.target('', '', ids=[targetid])
return [targetnode, todo]
@ -107,7 +106,7 @@ def process_todos(app, doctree):
location=node)
class TodoList(Directive):
class TodoList(SphinxDirective):
"""
A list of all todo entries.
"""

View File

@ -10,12 +10,14 @@
"""
import traceback
import warnings
from docutils import nodes
from six import iteritems, text_type
import sphinx
from sphinx import addnodes
from sphinx.deprecation import RemovedInSphinx30Warning
from sphinx.locale import _
from sphinx.pycode import ModuleAnalyzer
from sphinx.util import get_full_modname, logging, status_iterator
@ -25,6 +27,7 @@ if False:
# For type annotation
from typing import Any, Dict, Iterable, Iterator, Set, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA
from sphinx.environment import BuildEnvironment # NOQA
logger = logging.getLogger(__name__)
@ -100,7 +103,7 @@ def doctree_read(app, doctree):
modname = signode.get('module')
fullname = signode.get('fullname')
refname = modname
if env.config.viewcode_import:
if env.config.viewcode_follow_imported_members:
modname = _get_full_modname(app, modname, fullname)
if not modname:
continue
@ -239,10 +242,19 @@ def collect_pages(app):
yield ('_modules/index', context, 'page.html')
def migrate_viewcode_import(app, config):
# type: (Sphinx, Config) -> None
if config.viewcode_import is not None:
warnings.warn('viewcode_import was renamed to viewcode_follow_imported_members. '
'Please update your configuration.',
RemovedInSphinx30Warning)
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.add_config_value('viewcode_import', True, False)
app.add_config_value('viewcode_import', None, False)
app.add_config_value('viewcode_enable_epub', False, False)
app.add_config_value('viewcode_follow_imported_members', True, False)
app.connect('doctree-read', doctree_read)
app.connect('env-merge-info', env_merge_info)
app.connect('html-collect-pages', collect_pages)

View File

@ -30,8 +30,6 @@ if False:
# For type annotation
from typing import List # NOQA
proj_name = os.getenv('SPHINXPROJ', '<project>')
BUILDERS = [
("", "html", "to make standalone HTML files"),

View File

@ -4,7 +4,6 @@
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SPHINXPROJ = {{ project_fn }}
SOURCEDIR = {{ rsrcdir }}
BUILDDIR = {{ rbuilddir }}

View File

@ -9,7 +9,6 @@ if "%SPHINXBUILD%" == "" (
)
set SOURCEDIR={{ rsrcdir }}
set BUILDDIR={{ rbuilddir }}
set SPHINXPROJ={{ project_fn }}
if "%1" == "" goto help

View File

@ -35,4 +35,4 @@ class SphinxDomains(SphinxTransform):
def apply(self):
# type: () -> None
for domain in itervalues(self.env.domains):
domain.process_doc(self, self.env.docname, self.document)
domain.process_doc(self.env, self.env.docname, self.document)

View File

@ -241,8 +241,9 @@ class LoggingReporter(Reporter):
return cls(reporter.source, reporter.report_level, reporter.halt_level,
reporter.debug_flag, reporter.error_handler)
def __init__(self, source, report_level, halt_level,
debug=False, error_handler='backslashreplace'):
def __init__(self, source, report_level=Reporter.WARNING_LEVEL,
halt_level=Reporter.SEVERE_LEVEL, debug=False,
error_handler='backslashreplace'):
# type: (unicode, int, int, bool, unicode) -> None
stream = WarningStream()
Reporter.__init__(self, source, report_level, halt_level,

View File

@ -190,43 +190,51 @@ class LaTeXWriter(writers.Writer):
# Helper classes
class ExtBabel(Babel):
cyrillic_languages = ('bulgarian', 'kazakh', 'mongolian', 'russian', 'ukrainian')
shorthands = {
'ngerman': '"',
'slovene': '"',
'portuges': '"',
'spanish': '"',
'dutch': '"',
'polish': '"',
'italian': '"',
}
def __init__(self, language_code, use_polyglossia=False):
# type: (unicode, bool) -> None
super(ExtBabel, self).__init__(language_code or '')
self.language_code = language_code
self.use_polyglossia = use_polyglossia
self.supported = True
super(ExtBabel, self).__init__(language_code or '')
def get_shorthandoff(self):
# type: () -> unicode
shortlang = self.language.split('_')[0]
if shortlang in ('de', 'ngerman', 'sl', 'slovene', 'pt', 'portuges',
'es', 'spanish', 'nl', 'dutch', 'pl', 'polish', 'it',
'italian'):
return '\\ifnum\\catcode`\\"=\\active\\shorthandoff{"}\\fi'
elif shortlang in ('tr', 'turkish'):
shorthand = self.shorthands.get(self.language)
if shorthand:
return r'\ifnum\catcode`\%s=\active\shorthandoff{%s}\fi' % (shorthand, shorthand)
elif self.language == 'turkish':
# memo: if ever Sphinx starts supporting 'Latin', do as for Turkish
return '\\ifnum\\catcode`\\=\\string=\\active\\shorthandoff{=}\\fi'
return r'\ifnum\catcode`\=\string=\active\shorthandoff{=}\fi'
return ''
def uses_cyrillic(self):
# type: () -> bool
shortlang = self.language.split('_')[0]
return shortlang in ('bg', 'bulgarian', 'kk', 'kazakh',
'mn', 'mongolian', 'ru', 'russian',
'uk', 'ukrainian')
return self.language in self.cyrillic_languages
def is_supported_language(self):
# type: () -> bool
return bool(super(ExtBabel, self).get_language())
return self.supported
def get_language(self):
# type: () -> unicode
language = super(ExtBabel, self).get_language()
def language_name(self, language_code):
# type: (unicode) -> unicode
language = super(ExtBabel, self).language_name(language_code)
if language == 'ngerman' and self.use_polyglossia:
# polyglossia calls new orthography (Neue Rechtschreibung) as
# german (with new spelling option).
return 'german'
elif not language:
self.supported = False
return 'english' # fallback to english
else:
return language
@ -234,12 +242,13 @@ class ExtBabel(Babel):
def get_mainlanguage_options(self):
# type: () -> unicode
"""Return options for polyglossia's ``\setmainlanguage``."""
language = super(ExtBabel, self).get_language()
if self.use_polyglossia is False:
return None
elif language == 'ngerman':
elif self.language == 'german':
language = super(ExtBabel, self).language_name(self.language_code)
if language == 'ngerman':
return 'spelling=new'
elif language == 'german':
else:
return 'spelling=old'
else:
return None

View File

@ -6,4 +6,4 @@ import sys
extensions = ['sphinx.ext.viewcode']
master_doc = 'index'
exclude_patterns = ['_build']
viewcode_import = False
viewcode_follow_imported_members = False