From d17f3955a5546a9eb30ee9161946f8bb900441c5 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 7 May 2018 01:09:26 +0900 Subject: [PATCH 01/13] Fix #4877: latex: Don't use Babel.get_language() --- sphinx/writers/latex.py | 51 ++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 15bfa477b..6c4b66881 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -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,13 +242,14 @@ 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': - return 'spelling=new' - elif language == 'german': - return 'spelling=old' + elif self.language == 'german': + language = super(ExtBabel, self).language_name(self.language_code) + if language == 'ngerman': + return 'spelling=new' + else: + return 'spelling=old' else: return None From fad03ea0503d67a87b1407aec66c3903393aa45d Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 2 Apr 2018 12:32:07 +0900 Subject: [PATCH 02/13] Rename viewcode_import to viewcode_follow_imported_members (refs: #4035) --- CHANGES | 2 ++ doc/ext/viewcode.rst | 16 +++++++++------- doc/extdev/index.rst | 5 +++++ sphinx/ext/viewcode.py | 16 ++++++++++++++-- tests/roots/test-ext-viewcode-find/conf.py | 2 +- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index 60a0c6f4f..d2d36dd23 100644 --- a/CHANGES +++ b/CHANGES @@ -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 ---------- diff --git a/doc/ext/viewcode.rst b/doc/ext/viewcode.rst index 9ea1262fa..7571c985d 100644 --- a/doc/ext/viewcode.rst +++ b/doc/ext/viewcode.rst @@ -17,12 +17,11 @@ 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. + If :confval:`viewcode_follow_imported_members` 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. If you document scripts (as opposed to library modules), make sure their main routine is protected by a ``if __name__ == '__main__'`` condition. @@ -34,7 +33,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 +42,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 diff --git a/doc/extdev/index.rst b/doc/extdev/index.rst index dfe8dbaf0..6178b106c 100644 --- a/doc/extdev/index.rst +++ b/doc/extdev/index.rst @@ -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 diff --git a/sphinx/ext/viewcode.py b/sphinx/ext/viewcode.py index f1ae4bf57..6d3c3c1c0 100644 --- a/sphinx/ext/viewcode.py +++ b/sphinx/ext/viewcode.py @@ -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) diff --git a/tests/roots/test-ext-viewcode-find/conf.py b/tests/roots/test-ext-viewcode-find/conf.py index c23c0762c..3f5ddc175 100644 --- a/tests/roots/test-ext-viewcode-find/conf.py +++ b/tests/roots/test-ext-viewcode-find/conf.py @@ -6,4 +6,4 @@ import sys extensions = ['sphinx.ext.viewcode'] master_doc = 'index' exclude_patterns = ['_build'] -viewcode_import = False +viewcode_follow_imported_members = False From ed871965e9ac42b3d226b6f14ed276db6756dc4e Mon Sep 17 00:00:00 2001 From: Shengjing Zhu Date: Wed, 9 May 2018 13:08:31 +0800 Subject: [PATCH 03/13] fix lang_COUNTRY not fallback correctly for IndexBuilder In IndexBuilder, it will fallback to when the lang is passed as , and will fallback to en when not found. :: lang_class = languages.get(lang) # type: Type[SearchLanguage] # add language-specific SearchLanguage instance # fallback; try again with language-code if lang_class is None and '_' in lang: lang_class = languages.get(lang.split('_')[0]) if lang_class is None: self.lang = SearchEnglish(options) # type: SearchLanguage So there's no need to check lang before creating the IndexBuilder instance. Signed-off-by: Shengjing Zhu --- CHANGES | 1 + sphinx/builders/html.py | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 60a0c6f4f..f114349aa 100644 --- a/CHANGES +++ b/CHANGES @@ -103,6 +103,7 @@ Bugs fixed * i18n: message catalogs were reset on each initialization * #4850: latex: footnote inside footnote was not rendered +* i18n: fix lang_COUNTRY not fallback correctly for IndexBuilder Testing -------- diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index 2c8ac42ea..d5dd0597e 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -444,9 +444,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, From 9f1fead9c559e56bf6436de447e9046954184398 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 9 May 2018 22:59:32 +0900 Subject: [PATCH 04/13] Fix wrong argument for Domain.process_doc --- sphinx/transforms/references.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sphinx/transforms/references.py b/sphinx/transforms/references.py index c3b122e02..40efbf615 100644 --- a/sphinx/transforms/references.py +++ b/sphinx/transforms/references.py @@ -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) From ea2017294c1a27244e9e7771673b0400e4f83714 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 10 May 2018 22:59:21 +0900 Subject: [PATCH 05/13] refactor: Fill types column for default config_values --- sphinx/config.py | 74 +++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/sphinx/config.py b/sphinx/config.py index 58e5be277..67bd9b870 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -91,57 +91,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): @@ -203,7 +203,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, ' @@ -395,9 +395,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 From a41db7d2d06b1a398c25cca387203cc5af9ec850 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Mon, 15 Jan 2018 18:23:34 +0900 Subject: [PATCH 06/13] autodoc: Remove unused dummy class; testcls --- sphinx/ext/autodoc/__init__.py | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 825f993bf..1ebf6399b 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -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.""" From dad20201db1af2ccb108bf0c195d9fd1d64e18ee Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Fri, 11 May 2018 02:09:38 +0900 Subject: [PATCH 07/13] refactor: Convert the form of html_css_files --- sphinx/application.py | 2 -- sphinx/builders/epub3.py | 26 +++++++++++++++++++++++- sphinx/builders/html.py | 43 +++++++++++++++++++++++++++------------- 3 files changed, 54 insertions(+), 17 deletions(-) diff --git a/sphinx/application.py b/sphinx/application.py index 97b9944d2..004acd7b3 100644 --- a/sphinx/application.py +++ b/sphinx/application.py @@ -1057,8 +1057,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): diff --git a/sphinx/builders/epub3.py b/sphinx/builders/epub3.py index 895d2f5f5..5d3384b46 100644 --- a/sphinx/builders/epub3.py +++ b/sphinx/builders/epub3.py @@ -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, diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index 2c8ac42ea..eace1ce5a 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -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) - if '://' not in filename: - filename = posixpath.join('_static', filename) + 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): @@ -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, From f101bb6615e7dea6f20fa2bc6ae144d961005cb7 Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Thu, 10 May 2018 13:23:45 -0700 Subject: [PATCH 08/13] Remove unused SPHINXPROJ from new Makefile/make.bat. --- sphinx/make_mode.py | 2 -- sphinx/templates/quickstart/Makefile.new_t | 1 - sphinx/templates/quickstart/make.bat.new_t | 1 - 3 files changed, 4 deletions(-) diff --git a/sphinx/make_mode.py b/sphinx/make_mode.py index 23fb4ce64..ae19e93ee 100644 --- a/sphinx/make_mode.py +++ b/sphinx/make_mode.py @@ -30,8 +30,6 @@ if False: # For type annotation from typing import List # NOQA -proj_name = os.getenv('SPHINXPROJ', '') - BUILDERS = [ ("", "html", "to make standalone HTML files"), diff --git a/sphinx/templates/quickstart/Makefile.new_t b/sphinx/templates/quickstart/Makefile.new_t index c7cd62dda..16a9d482f 100644 --- a/sphinx/templates/quickstart/Makefile.new_t +++ b/sphinx/templates/quickstart/Makefile.new_t @@ -4,7 +4,6 @@ # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build -SPHINXPROJ = {{ project_fn }} SOURCEDIR = {{ rsrcdir }} BUILDDIR = {{ rbuilddir }} diff --git a/sphinx/templates/quickstart/make.bat.new_t b/sphinx/templates/quickstart/make.bat.new_t index e49ffbe78..50a12e7af 100644 --- a/sphinx/templates/quickstart/make.bat.new_t +++ b/sphinx/templates/quickstart/make.bat.new_t @@ -9,7 +9,6 @@ if "%SPHINXBUILD%" == "" ( ) set SOURCEDIR={{ rsrcdir }} set BUILDDIR={{ rbuilddir }} -set SPHINXPROJ={{ project_fn }} if "%1" == "" goto help From 6c08963f25c0834eab7d31543810c82f4e09daf5 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Wed, 9 May 2018 22:58:00 +0900 Subject: [PATCH 09/13] refactor: Replace Directive by SphinxDirective --- sphinx/directives/__init__.py | 4 +-- sphinx/domains/cpp.py | 46 ++++++++++++++---------------- sphinx/domains/javascript.py | 12 ++++---- sphinx/domains/python.py | 25 ++++++++-------- sphinx/domains/std.py | 30 +++++++++---------- sphinx/ext/autodoc/directive.py | 12 ++++---- sphinx/ext/autosummary/__init__.py | 15 ++++------ sphinx/ext/doctest.py | 5 ++-- sphinx/ext/graphviz.py | 17 +++++------ sphinx/ext/ifconfig.py | 4 +-- sphinx/ext/inheritance_diagram.py | 12 ++++---- sphinx/ext/mathbase.py | 18 ++++++------ sphinx/ext/todo.py | 11 ++++--- 13 files changed, 101 insertions(+), 110 deletions(-) diff --git a/sphinx/directives/__init__.py b/sphinx/directives/__init__.py index 81978b722..1177a258e 100644 --- a/sphinx/directives/__init__.py +++ b/sphinx/directives/__init__.py @@ -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. """ diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py index f4234b0db..2998792ae 100644 --- a/sphinx/domains/cpp.py +++ b/sphinx/domains/cpp.py @@ -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 [] diff --git a/sphinx/domains/javascript.py b/sphinx/domains/javascript.py index 0ea6114d6..511a058c8 100644 --- a/sphinx/domains/javascript.py +++ b/sphinx/domains/javascript.py @@ -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) diff --git a/sphinx/domains/python.py b/sphinx/domains/python.py index 1daac3227..0fe4b5eb4 100644 --- a/sphinx/domains/python.py +++ b/sphinx/domains/python.py @@ -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.options.get('synopsis', ''), - self.options.get('platform', ''), - 'deprecated' in self.options) + 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 [] diff --git a/sphinx/domains/std.py b/sphinx/domains/std.py index 6518091f6..bc6b4de6c 100644 --- a/sphinx/domains/std.py +++ b/sphinx/domains/std.py @@ -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 diff --git a/sphinx/ext/autodoc/directive.py b/sphinx/ext/autodoc/directive.py index 77b3f7aaf..64d19fcc7 100644 --- a/sphinx/ext/autodoc/directive.py +++ b/sphinx/ext/autodoc/directive.py @@ -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: diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py index 80a2b4e63..8c6bafbd9 100644 --- a/sphinx/ext/autosummary/__init__.py +++ b/sphinx/ext/autosummary/__init__.py @@ -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]] diff --git a/sphinx/ext/doctest.py b/sphinx/ext/doctest.py index b86775d5e..68877371c 100644 --- a/sphinx/ext/doctest.py +++ b/sphinx/ext/doctest.py @@ -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. """ diff --git a/sphinx/ext/graphviz.py b/sphinx/ext/graphviz.py index 127146f94..11d9e54a0 100644 --- a/sphinx/ext/graphviz.py +++ b/sphinx/ext/graphviz.py @@ -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. """ diff --git a/sphinx/ext/ifconfig.py b/sphinx/ext/ifconfig.py index 864e7a185..f22a37e92 100644 --- a/sphinx/ext/ifconfig.py +++ b/sphinx/ext/ifconfig.py @@ -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 diff --git a/sphinx/ext/inheritance_diagram.py b/sphinx/ext/inheritance_diagram.py index 14593ac99..d91848aa1 100644 --- a/sphinx/ext/inheritance_diagram.py +++ b/sphinx/ext/inheritance_diagram.py @@ -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], diff --git a/sphinx/ext/mathbase.py b/sphinx/ext/mathbase.py index 4789b117e..e6a6929e6 100644 --- a/sphinx/ext/mathbase.py +++ b/sphinx/ext/mathbase.py @@ -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 diff --git a/sphinx/ext/todo.py b/sphinx/ext/todo.py index c7ef16b51..d7413ac61 100644 --- a/sphinx/ext/todo.py +++ b/sphinx/ext/todo.py @@ -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. """ From 0ed86d37a5fe4184c42057ae5e67936c04c17872 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sat, 12 May 2018 11:35:54 +0900 Subject: [PATCH 10/13] doc: viewcode --- doc/ext/viewcode.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/ext/viewcode.rst b/doc/ext/viewcode.rst index 7571c985d..87071144f 100644 --- a/doc/ext/viewcode.rst +++ b/doc/ext/viewcode.rst @@ -17,15 +17,17 @@ from the source to the description will also be inserted. .. warning:: - If :confval:`viewcode_follow_imported_members` 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 + 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 From 576c0bc90b795e0780f57dedb9b71de857e07ba1 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 22 Apr 2018 13:33:34 +0900 Subject: [PATCH 11/13] Give better default settings for LoggingReporter --- sphinx/util/docutils.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sphinx/util/docutils.py b/sphinx/util/docutils.py index b09d4e841..b6262d793 100644 --- a/sphinx/util/docutils.py +++ b/sphinx/util/docutils.py @@ -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, From e373e6c74e3f1f8925dcfffe0cf6511972082ef0 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 22 Apr 2018 13:34:28 +0900 Subject: [PATCH 12/13] Replace raw Reporter object by LoggingReporter --- sphinx/environment/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sphinx/environment/__init__.py b/sphinx/environment/__init__.py index e8d9dd9d4..7e5855fe2 100644 --- a/sphinx/environment/__init__.py +++ b/sphinx/environment/__init__.py @@ -18,7 +18,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, class_types, next from six.moves import cPickle as pickle @@ -31,7 +31,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 @@ -652,7 +652,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, From 236d763ec26aa817552881777e5fa37aa74f31e7 Mon Sep 17 00:00:00 2001 From: shimizukawa Date: Sat, 12 May 2018 16:56:27 +0900 Subject: [PATCH 13/13] Update CHANGES for #4945. --- CHANGES | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 598384b78..796d9b6ed 100644 --- a/CHANGES +++ b/CHANGES @@ -105,7 +105,8 @@ Bugs fixed * i18n: message catalogs were reset on each initialization * #4850: latex: footnote inside footnote was not rendered -* i18n: fix lang_COUNTRY not fallback correctly for IndexBuilder +* #4945: i18n: fix lang_COUNTRY not fallback correctly for IndexBuilder. Thanks + to Shengjing Zhu. Testing --------