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

View File

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

View File

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

View File

@ -13,6 +13,8 @@
from collections import namedtuple from collections import namedtuple
from os import path from os import path
from six import string_types
from sphinx import package_dir from sphinx import package_dir
from sphinx.builders import _epub_base from sphinx.builders import _epub_base
from sphinx.config import string_classes, ENUM from sphinx.config import string_classes, ENUM
@ -24,9 +26,10 @@ from sphinx.util.osutil import make_filename
if False: if False:
# For type annotation # 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 docutils import nodes # NOQA
from sphinx.application import Sphinx # NOQA from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -226,6 +229,24 @@ class Epub3Builder(_epub_base.EpubBuilder):
self.files.append(outname) 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): def setup(app):
# type: (Sphinx) -> Dict[unicode, Any] # type: (Sphinx) -> Dict[unicode, Any]
app.add_builder(Epub3Builder) app.add_builder(Epub3Builder)
@ -261,6 +282,9 @@ def setup(app):
app.add_config_value('epub_writing_mode', 'horizontal', 'epub', app.add_config_value('epub_writing_mode', 'horizontal', 'epub',
ENUM('horizontal', 'vertical')) ENUM('horizontal', 'vertical'))
# event handlers
app.connect('config-inited', convert_epub_css_files)
return { return {
'version': 'builtin', 'version': 'builtin',
'parallel_read_safe': True, 'parallel_read_safe': True,

View File

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

View File

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

View File

@ -12,7 +12,7 @@
import re import re
from docutils import nodes 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 import addnodes
from sphinx.util.docfields import DocFieldTransformer from sphinx.util.docfields import DocFieldTransformer
@ -217,7 +217,7 @@ class DefaultRole(SphinxDirective):
return messages return messages
class DefaultDomain(Directive): class DefaultDomain(SphinxDirective):
""" """
Directive to (re-)set the default domain for this source file. Directive to (re-)set the default domain for this source file.
""" """

View File

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

View File

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

View File

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

View File

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

View File

@ -17,7 +17,7 @@ from collections import defaultdict
from copy import copy from copy import copy
from os import path 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 import BytesIO, next
from six.moves import cPickle as pickle from six.moves import cPickle as pickle
@ -30,7 +30,7 @@ from sphinx.locale import __
from sphinx.transforms import SphinxTransformer from sphinx.transforms import SphinxTransformer
from sphinx.util import get_matching_docs, FilenameUniqDict from sphinx.util import get_matching_docs, FilenameUniqDict
from sphinx.util import logging 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.i18n import find_catalog_files
from sphinx.util.matching import compile_matchers from sphinx.util.matching import compile_matchers
from sphinx.util.nodes import is_translatable from sphinx.util.nodes import is_translatable
@ -599,7 +599,7 @@ class BuildEnvironment(object):
with open(doctree_filename, 'rb') as f: with open(doctree_filename, 'rb') as f:
doctree = pickle.load(f) doctree = pickle.load(f)
doctree.settings.env = self doctree.settings.env = self
doctree.reporter = Reporter(self.doc2path(docname), 2, 5, stream=WarningStream()) doctree.reporter = LoggingReporter(self.doc2path(docname))
return doctree return doctree
def get_and_resolve_doctree(self, docname, builder, doctree=None, 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') app.add_event('autodoc-skip-member')
return {'version': sphinx.__display_version__, 'parallel_read_safe': True} 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 import nodes
from docutils.parsers.rst import Directive
from docutils.statemachine import ViewList from docutils.statemachine import ViewList
from docutils.utils import assemble_option_dict from docutils.utils import assemble_option_dict
from sphinx.ext.autodoc import Options, get_documenters from sphinx.ext.autodoc import Options, get_documenters
from sphinx.util import logging 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 from sphinx.util.nodes import nested_parse_with_titles
if False: if False:
@ -91,7 +90,7 @@ def parse_generated_content(state, content, documenter):
return node.children return node.children
class AutodocDirective(Directive): class AutodocDirective(SphinxDirective):
"""A directive class for all autodoc directives. It works as a dispatcher of Documenters. """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 It invokes a Documenter on running. After the processing, it parses and returns
@ -105,7 +104,6 @@ class AutodocDirective(Directive):
def run(self): def run(self):
# type: () -> List[nodes.Node] # type: () -> List[nodes.Node]
env = self.state.document.settings.env
reporter = self.state.document.reporter reporter = self.state.document.reporter
try: try:
@ -116,11 +114,11 @@ class AutodocDirective(Directive):
# look up target Documenter # look up target Documenter
objtype = self.name[4:] # strip prefix (auto-). 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 # process the options with the selected documenter's option_spec
try: 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: except (KeyError, ValueError, TypeError) as exc:
# an option is either unknown or has a wrong type # 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' % logger.error('An option to %s is either unknown or has an invalid value: %s' %
@ -128,7 +126,7 @@ class AutodocDirective(Directive):
return [] return []
# generate the output # 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 = doccls(params, self.arguments[0])
documenter.generate(more_content=self.content) documenter.generate(more_content=self.content)
if not params.result: if not params.result:

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -35,4 +35,4 @@ class SphinxDomains(SphinxTransform):
def apply(self): def apply(self):
# type: () -> None # type: () -> None
for domain in itervalues(self.env.domains): 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, return cls(reporter.source, reporter.report_level, reporter.halt_level,
reporter.debug_flag, reporter.error_handler) reporter.debug_flag, reporter.error_handler)
def __init__(self, source, report_level, halt_level, def __init__(self, source, report_level=Reporter.WARNING_LEVEL,
debug=False, error_handler='backslashreplace'): halt_level=Reporter.SEVERE_LEVEL, debug=False,
error_handler='backslashreplace'):
# type: (unicode, int, int, bool, unicode) -> None # type: (unicode, int, int, bool, unicode) -> None
stream = WarningStream() stream = WarningStream()
Reporter.__init__(self, source, report_level, halt_level, Reporter.__init__(self, source, report_level, halt_level,

View File

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

View File

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