diff --git a/CHANGES b/CHANGES
index 2bf062e9b..ed2f3e0f9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -10,6 +10,10 @@ Incompatible changes
Deprecated
----------
+* The ``info`` and ``warn`` arguments of
+ ``sphinx.ext.autosummary.generate.generate_autosummary_docs()``
+* ``sphinx.ext.autosummary.generate._simple_info()``
+* ``sphinx.ext.autosummary.generate._simple_warn()``
* ``sphinx.ext.todo.merge_info()``
* ``sphinx.ext.todo.process_todo_nodes()``
* ``sphinx.ext.todo.process_todos()``
@@ -21,10 +25,15 @@ Features added
Bugs fixed
----------
+* py domain: duplicated warning does not point the location of source code
+* #1125: html theme: scrollbar is hard to see on classic theme and macOS
+* #5502: linkcheck: Consider HTTP 503 response as not an error
+* #6439: Make generated download links reproducible
+
Testing
--------
-Release 2.1.1 (in development)
+Release 2.1.2 (in development)
==============================
Dependencies
@@ -45,6 +54,27 @@ Bugs fixed
Testing
--------
+Release 2.1.1 (released Jun 10, 2019)
+=====================================
+
+Incompatible changes
+--------------------
+
+* #6447: autodoc: Stop to generate document for undocumented module variables
+
+Bugs fixed
+----------
+
+* #6442: LaTeX: admonitions of :rst:dir:`note` type can get separated from
+ immediately preceding section title by pagebreak
+* #6448: autodoc: crashed when autodocumenting classes with ``__slots__ = None``
+* #6451: autodoc: generates docs for "optional import"ed modules as variables
+* #6452: autosummary: crashed when generating document of properties
+* #6455: napoleon: docstrings for properties are not processed
+* #6436: napoleon: "Unknown target name" error if variable name ends with
+ underscore
+* #6440: apidoc: missing blank lines between modules
+
Release 2.1.0 (released Jun 02, 2019)
=====================================
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 1807d3998..8c74b184a 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -250,7 +250,7 @@ the source and the compiled catalogs.
When a new locale is submitted, add a new directory with the ISO 639-1 language
identifier and put ``sphinx.po`` in there. Don't forget to update the possible
-values for :confval:`language` in ``doc/config.rst``.
+values for :confval:`language` in ``doc/usage/configuration.rst``.
The Sphinx core messages can also be translated on `Transifex
`_. There exists a client tool named ``tx`` in the
diff --git a/doc/extdev/deprecated.rst b/doc/extdev/deprecated.rst
index f67c94592..f83235b92 100644
--- a/doc/extdev/deprecated.rst
+++ b/doc/extdev/deprecated.rst
@@ -26,6 +26,22 @@ The following is a list of deprecated interfaces.
- (will be) Removed
- Alternatives
+ * - The ``info`` and ``warn`` arguments of
+ ``sphinx.ext.autosummary.generate.generate_autosummary_docs()``
+ - 2.2
+ - 4.0
+ - ``logging.info()`` and ``logging.warning()``
+
+ * - ``sphinx.ext.autosummary.generate._simple_info()``
+ - 2.2
+ - 4.0
+ - ``logging.info()``
+
+ * - ``sphinx.ext.autosummary.generate._simple_warn()``
+ - 2.2
+ - 4.0
+ - ``logging.warning()``
+
* - ``sphinx.ext.todo.merge_info()``
- 2.2
- 4.0
diff --git a/setup.cfg b/setup.cfg
index c91a31879..1f5bbd1cd 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -5,9 +5,6 @@ license_file = LICENSE
tag_build = .dev
tag_date = true
-[bdist_wheel]
-universal = 1
-
[aliases]
release = egg_info -Db ''
upload = upload --sign --identity=36580288
diff --git a/sphinx/builders/__init__.py b/sphinx/builders/__init__.py
index 8eaa0e215..546b9b0a8 100644
--- a/sphinx/builders/__init__.py
+++ b/sphinx/builders/__init__.py
@@ -11,22 +11,27 @@
import pickle
import time
from os import path
+from typing import Any, Dict, Iterable, List, Sequence, Set, Tuple, Type, Union
from docutils import nodes
+from docutils.nodes import Node
-from sphinx.environment import CONFIG_OK, CONFIG_CHANGED_REASON
+from sphinx.config import Config
+from sphinx.environment import BuildEnvironment, CONFIG_OK, CONFIG_CHANGED_REASON
from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.errors import SphinxError
+from sphinx.events import EventManager
from sphinx.io import read_doc
from sphinx.locale import __
from sphinx.util import import_object, logging, rst, progress_message, status_iterator
from sphinx.util.build_phase import BuildPhase
from sphinx.util.console import bold # type: ignore
from sphinx.util.docutils import sphinx_domains
-from sphinx.util.i18n import CatalogRepository, docname_to_domain
+from sphinx.util.i18n import CatalogInfo, CatalogRepository, docname_to_domain
from sphinx.util.osutil import SEP, ensuredir, relative_uri, relpath
from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, \
parallel_available
+from sphinx.util.tags import Tags
# side effect: registers roles and directives
from sphinx import roles # noqa
@@ -39,13 +44,7 @@ except ImportError:
if False:
# For type annotation
- from typing import Any, Dict, Iterable, List, Sequence, Set, Tuple, Type, Union # NOQA
- from sphinx.application import Sphinx # NOQA
- from sphinx.config import Config # NOQA
- from sphinx.environment import BuildEnvironment # NOQA
- from sphinx.events import EventManager # NOQA
- from sphinx.util.i18n import CatalogInfo # NOQA
- from sphinx.util.tags import Tags # NOQA
+ from sphinx.application import Sphinx
logger = logging.getLogger(__name__)
@@ -84,8 +83,7 @@ class Builder:
#: The builder supports data URIs or not.
supported_data_uri_images = False
- def __init__(self, app):
- # type: (Sphinx) -> None
+ def __init__(self, app: "Sphinx") -> None:
self.srcdir = app.srcdir
self.confdir = app.confdir
self.outdir = app.outdir
@@ -113,20 +111,17 @@ class Builder:
self.parallel_ok = False
self.finish_tasks = None # type: Any
- def set_environment(self, env):
- # type: (BuildEnvironment) -> None
+ def set_environment(self, env: BuildEnvironment) -> None:
"""Store BuildEnvironment object."""
self.env = env
self.env.set_versioning_method(self.versioning_method,
self.versioning_compare)
- def get_translator_class(self, *args):
- # type: (Any) -> Type[nodes.NodeVisitor]
+ def get_translator_class(self, *args) -> Type[nodes.NodeVisitor]:
"""Return a class of translator."""
return self.app.registry.get_translator_class(self)
- def create_translator(self, *args):
- # type: (Any) -> nodes.NodeVisitor
+ def create_translator(self, *args) -> nodes.NodeVisitor:
"""Return an instance of translator.
This method returns an instance of ``default_translator_class`` by default.
@@ -135,15 +130,13 @@ class Builder:
return self.app.registry.create_translator(self, *args)
# helper methods
- def init(self):
- # type: () -> None
+ def init(self) -> None:
"""Load necessary templates and perform initialization. The default
implementation does nothing.
"""
pass
- def create_template_bridge(self):
- # type: () -> None
+ def create_template_bridge(self) -> None:
"""Return the template bridge configured."""
if self.config.template_bridge:
self.templates = import_object(self.config.template_bridge,
@@ -152,8 +145,7 @@ class Builder:
from sphinx.jinja2glue import BuiltinTemplateLoader
self.templates = BuiltinTemplateLoader()
- def get_target_uri(self, docname, typ=None):
- # type: (str, str) -> str
+ def get_target_uri(self, docname: str, typ: str = None) -> str:
"""Return the target URI for a document name.
*typ* can be used to qualify the link characteristic for individual
@@ -161,8 +153,7 @@ class Builder:
"""
raise NotImplementedError
- def get_relative_uri(self, from_, to, typ=None):
- # type: (str, str, str) -> str
+ def get_relative_uri(self, from_: str, to: str, typ: str = None) -> str:
"""Return a relative URI between two source filenames.
May raise environment.NoUri if there's no way to return a sensible URI.
@@ -170,8 +161,7 @@ class Builder:
return relative_uri(self.get_target_uri(from_),
self.get_target_uri(to, typ))
- def get_outdated_docs(self):
- # type: () -> Union[str, Iterable[str]]
+ def get_outdated_docs(self) -> Union[str, Iterable[str]]:
"""Return an iterable of output files that are outdated, or a string
describing what an update build will build.
@@ -181,13 +171,11 @@ class Builder:
"""
raise NotImplementedError
- def get_asset_paths(self):
- # type: () -> List[str]
+ def get_asset_paths(self) -> List[str]:
"""Return list of paths for assets (ex. templates, CSS, etc.)."""
return []
- def post_process_images(self, doctree):
- # type: (nodes.Node) -> None
+ def post_process_images(self, doctree: Node) -> None:
"""Pick the best candidate for all image URIs."""
images = ImageAdapter(self.env)
for node in doctree.traverse(nodes.image):
@@ -220,13 +208,11 @@ class Builder:
# compile po methods
- def compile_catalogs(self, catalogs, message):
- # type: (Set[CatalogInfo], str) -> None
+ def compile_catalogs(self, catalogs: Set[CatalogInfo], message: str) -> None:
if not self.config.gettext_auto_build:
return
- def cat2relpath(cat):
- # type: (CatalogInfo) -> str
+ def cat2relpath(cat: CatalogInfo) -> str:
return relpath(cat.mo_path, self.env.srcdir).replace(path.sep, SEP)
logger.info(bold(__('building [mo]: ')) + message)
@@ -235,17 +221,14 @@ class Builder:
stringify_func=cat2relpath):
catalog.write_mo(self.config.language)
- def compile_all_catalogs(self):
- # type: () -> None
+ def compile_all_catalogs(self) -> None:
repo = CatalogRepository(self.srcdir, self.config.locale_dirs,
self.config.language, self.config.source_encoding)
message = __('all of %d po files') % len(list(repo.catalogs))
self.compile_catalogs(set(repo.catalogs), message)
- def compile_specific_catalogs(self, specified_files):
- # type: (List[str]) -> None
- def to_domain(fpath):
- # type: (str) -> str
+ def compile_specific_catalogs(self, specified_files: List[str]) -> None:
+ def to_domain(fpath: str) -> str:
docname = self.env.path2doc(path.abspath(fpath))
if docname:
return docname_to_domain(docname, self.config.gettext_compact)
@@ -262,8 +245,7 @@ class Builder:
message = __('targets for %d po files that are specified') % len(catalogs)
self.compile_catalogs(catalogs, message)
- def compile_update_catalogs(self):
- # type: () -> None
+ def compile_update_catalogs(self) -> None:
repo = CatalogRepository(self.srcdir, self.config.locale_dirs,
self.config.language, self.config.source_encoding)
catalogs = {c for c in repo.catalogs if c.is_outdated()}
@@ -272,13 +254,11 @@ class Builder:
# build methods
- def build_all(self):
- # type: () -> None
+ def build_all(self) -> None:
"""Build all source files."""
self.build(None, summary=__('all source files'), method='all')
- def build_specific(self, filenames):
- # type: (List[str]) -> None
+ def build_specific(self, filenames: List[str]) -> None:
"""Only rebuild as much as needed for changes in the *filenames*."""
# bring the filenames to the canonical format, that is,
# relative to the source directory and without source_suffix.
@@ -306,8 +286,7 @@ class Builder:
self.build(to_write, method='specific',
summary=__('%d source files given on command line') % len(to_write))
- def build_update(self):
- # type: () -> None
+ def build_update(self) -> None:
"""Only rebuild what was changed or added since last build."""
to_build = self.get_outdated_docs()
if isinstance(to_build, str):
@@ -318,8 +297,7 @@ class Builder:
summary=__('targets for %d source files that are out of date') %
len(to_build))
- def build(self, docnames, summary=None, method='update'):
- # type: (Iterable[str], str, str) -> None
+ def build(self, docnames: Iterable[str], summary: str = None, method: str = 'update') -> None: # NOQA
"""Main build method.
First updates the environment, and then calls :meth:`write`.
@@ -387,8 +365,7 @@ class Builder:
# wait for all tasks
self.finish_tasks.join()
- def read(self):
- # type: () -> List[str]
+ def read(self) -> List[str]:
"""(Re-)read all files new or changed since last update.
Store all environment docnames in the canonical format (ie using SEP as
@@ -450,8 +427,7 @@ class Builder:
return sorted(docnames)
- def _read_serial(self, docnames):
- # type: (List[str]) -> None
+ def _read_serial(self, docnames: List[str]) -> None:
for docname in status_iterator(docnames, __('reading sources... '), "purple",
len(docnames), self.app.verbosity):
# remove all inventory entries for that file
@@ -459,23 +435,20 @@ class Builder:
self.env.clear_doc(docname)
self.read_doc(docname)
- def _read_parallel(self, docnames, nproc):
- # type: (List[str], int) -> None
+ def _read_parallel(self, docnames: List[str], nproc: int) -> None:
# clear all outdated docs at once
for docname in docnames:
self.events.emit('env-purge-doc', self.env, docname)
self.env.clear_doc(docname)
- def read_process(docs):
- # type: (List[str]) -> bytes
+ def read_process(docs: List[str]) -> bytes:
self.env.app = self.app
for docname in docs:
self.read_doc(docname)
# allow pickling self to send it back
return pickle.dumps(self.env, pickle.HIGHEST_PROTOCOL)
- def merge(docs, otherenv):
- # type: (List[str], bytes) -> None
+ def merge(docs: List[str], otherenv: bytes) -> None:
env = pickle.loads(otherenv)
self.env.merge_info_from(docs, env, self.app)
@@ -490,8 +463,7 @@ class Builder:
logger.info(bold(__('waiting for workers...')))
tasks.join()
- def read_doc(self, docname):
- # type: (str) -> None
+ def read_doc(self, docname: str) -> None:
"""Parse a file and add/update inventory entries for the doctree."""
self.env.prepare_settings(docname)
@@ -516,8 +488,7 @@ class Builder:
self.write_doctree(docname, doctree)
- def write_doctree(self, docname, doctree):
- # type: (str, nodes.document) -> None
+ def write_doctree(self, docname: str, doctree: nodes.document) -> None:
"""Write the doctree to a file."""
# make it picklable
doctree.reporter = None
@@ -531,8 +502,7 @@ class Builder:
with open(doctree_filename, 'wb') as f:
pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
- def write(self, build_docnames, updated_docnames, method='update'):
- # type: (Iterable[str], Sequence[str], str) -> None
+ def write(self, build_docnames: Iterable[str], updated_docnames: Sequence[str], method: str = 'update') -> None: # NOQA
if build_docnames is None or build_docnames == ['__all__']:
# build_all
build_docnames = self.env.found_docs
@@ -561,8 +531,7 @@ class Builder:
else:
self._write_serial(sorted(docnames))
- def _write_serial(self, docnames):
- # type: (Sequence[str]) -> None
+ def _write_serial(self, docnames: Sequence[str]) -> None:
with logging.pending_warnings():
for docname in status_iterator(docnames, __('writing output... '), "darkgreen",
len(docnames), self.app.verbosity):
@@ -572,10 +541,8 @@ class Builder:
self.write_doc_serialized(docname, doctree)
self.write_doc(docname, doctree)
- def _write_parallel(self, docnames, nproc):
- # type: (Sequence[str], int) -> None
- def write_process(docs):
- # type: (List[Tuple[str, nodes.document]]) -> None
+ def _write_parallel(self, docnames: Sequence[str], nproc: int) -> None:
+ def write_process(docs: List[Tuple[str, nodes.document]]) -> None:
self.app.phase = BuildPhase.WRITING
for docname, doctree in docs:
self.write_doc(docname, doctree)
@@ -605,41 +572,35 @@ class Builder:
logger.info(bold(__('waiting for workers...')))
tasks.join()
- def prepare_writing(self, docnames):
- # type: (Set[str]) -> None
+ def prepare_writing(self, docnames: Set[str]) -> None:
"""A place where you can add logic before :meth:`write_doc` is run"""
raise NotImplementedError
- def write_doc(self, docname, doctree):
- # type: (str, nodes.document) -> None
+ def write_doc(self, docname: str, doctree: nodes.document) -> None:
"""Where you actually write something to the filesystem."""
raise NotImplementedError
- def write_doc_serialized(self, docname, doctree):
- # type: (str, nodes.document) -> None
+ def write_doc_serialized(self, docname: str, doctree: nodes.document) -> None:
"""Handle parts of write_doc that must be called in the main process
if parallel build is active.
"""
pass
- def finish(self):
- # type: () -> None
+ def finish(self) -> None:
"""Finish the building process.
The default implementation does nothing.
"""
pass
- def cleanup(self):
- # type: () -> None
+ def cleanup(self) -> None:
"""Cleanup any resources.
The default implementation does nothing.
"""
pass
- def get_builder_config(self, option, default):
- # type: (str, str) -> Any
+ def get_builder_config(self, option: str, default: str) -> Any:
"""Return a builder specific option.
This method allows customization of common builder settings by
diff --git a/sphinx/builders/_epub_base.py b/sphinx/builders/_epub_base.py
index 140f2748d..75e79936b 100644
--- a/sphinx/builders/_epub_base.py
+++ b/sphinx/builders/_epub_base.py
@@ -14,9 +14,11 @@ import re
import warnings
from collections import namedtuple
from os import path
+from typing import Any, Dict, List, Set, Tuple
from zipfile import ZIP_DEFLATED, ZIP_STORED, ZipFile
from docutils import nodes
+from docutils.nodes import Element, Node
from docutils.utils import smartquotes
from sphinx import addnodes
@@ -34,10 +36,6 @@ try:
except ImportError:
Image = None
-if False:
- # For type annotation
- from typing import Any, Dict, List, Set, Tuple # NOQA
-
logger = logging.getLogger(__name__)
@@ -93,8 +91,7 @@ Guide = namedtuple('Guide', ['type', 'title', 'uri'])
NavPoint = namedtuple('NavPoint', ['navpoint', 'playorder', 'text', 'refuri', 'children'])
-def sphinx_smarty_pants(t, language='en'):
- # type: (str, str) -> str
+def sphinx_smarty_pants(t: str, language: str = 'en') -> str:
t = t.replace('"', '"')
t = smartquotes.educateDashesOldSchool(t)
t = smartquotes.educateQuotes(t, language)
@@ -145,8 +142,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
template_dir = ""
doctype = ""
- def init(self):
- # type: () -> None
+ def init(self) -> None:
super().init()
# the output files for epub must be .html only
self.out_suffix = '.xhtml'
@@ -157,17 +153,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
self.use_index = self.get_builder_config('use_index', 'epub')
self.refnodes = [] # type: List[Dict[str, Any]]
- def create_build_info(self):
- # type: () -> BuildInfo
+ def create_build_info(self) -> BuildInfo:
return BuildInfo(self.config, self.tags, ['html', 'epub'])
- def get_theme_config(self):
- # type: () -> Tuple[str, Dict]
+ def get_theme_config(self) -> Tuple[str, Dict]:
return self.config.epub_theme, self.config.epub_theme_options
# generic support functions
- def make_id(self, name):
- # type: (str) -> str
+ def make_id(self, name: str) -> str:
# id_cache is intentionally mutable
"""Return a unique id for name."""
id = self.id_cache.get(name)
@@ -176,8 +169,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
self.id_cache[name] = id
return id
- def esc(self, name):
- # type: (str) -> str
+ def esc(self, name: str) -> str:
"""Replace all characters not allowed in text an attribute values."""
warnings.warn(
'%s.esc() is deprecated. Use html.escape() instead.' % self.__class__.__name__,
@@ -189,8 +181,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
name = name.replace('\'', ''')
return name
- def get_refnodes(self, doctree, result):
- # type: (nodes.Node, List[Dict[str, Any]]) -> List[Dict[str, Any]]
+ def get_refnodes(self, doctree: Node, result: List[Dict[str, Any]]) -> List[Dict[str, Any]]: # NOQA
"""Collect section titles, their depth in the toc and the refuri."""
# XXX: is there a better way than checking the attribute
# toctree-l[1-8] on the parent node?
@@ -213,8 +204,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
result = self.get_refnodes(elem, result)
return result
- def check_refnodes(self, nodes):
- # type: (List[Dict[str, Any]]) -> None
+ def check_refnodes(self, nodes: List[Dict[str, Any]]) -> None:
appeared = set() # type: Set[str]
for node in nodes:
if node['refuri'] in appeared:
@@ -222,8 +212,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
else:
appeared.add(node['refuri'])
- def get_toc(self):
- # type: () -> None
+ def get_toc(self) -> None:
"""Get the total table of contents, containing the master_doc
and pre and post files not managed by sphinx.
"""
@@ -238,8 +227,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
item['refuri'] = master_dir + item['refuri']
self.toc_add_files(self.refnodes)
- def toc_add_files(self, refnodes):
- # type: (List[Dict[str, Any]]) -> None
+ def toc_add_files(self, refnodes: List[Dict[str, Any]]) -> None:
"""Add the master_doc, pre and post files to a list of refnodes.
"""
refnodes.insert(0, {
@@ -261,13 +249,11 @@ class EpubBuilder(StandaloneHTMLBuilder):
'text': ssp(html.escape(text))
})
- def fix_fragment(self, prefix, fragment):
- # type: (str, str) -> str
+ def fix_fragment(self, prefix: str, fragment: str) -> str:
"""Return a href/id attribute with colons replaced by hyphens."""
return prefix + fragment.replace(':', '-')
- def fix_ids(self, tree):
- # type: (nodes.document) -> None
+ def fix_ids(self, tree: nodes.document) -> None:
"""Replace colons with hyphens in href and id attributes.
Some readers crash because they interpret the part as a
@@ -286,7 +272,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
if ':' in node_id:
target['ids'][i] = self.fix_fragment('', node_id)
- next_node = target.next_node(siblings=True) # type: nodes.Node
+ next_node = target.next_node(siblings=True) # type: Node
if isinstance(next_node, nodes.Element):
for i, node_id in enumerate(next_node['ids']):
if ':' in node_id:
@@ -299,20 +285,17 @@ class EpubBuilder(StandaloneHTMLBuilder):
newids.append(self.fix_fragment('', id))
desc_signature.attributes['ids'] = newids
- def add_visible_links(self, tree, show_urls='inline'):
- # type: (nodes.document, str) -> None
+ def add_visible_links(self, tree: nodes.document, show_urls: str = 'inline') -> None:
"""Add visible link targets for external links"""
- def make_footnote_ref(doc, label):
- # type: (nodes.document, str) -> nodes.footnote_reference
+ def make_footnote_ref(doc: nodes.document, label: str) -> nodes.footnote_reference:
"""Create a footnote_reference node with children"""
footnote_ref = nodes.footnote_reference('[#]_')
footnote_ref.append(nodes.Text(label))
doc.note_autofootnote_ref(footnote_ref)
return footnote_ref
- def make_footnote(doc, label, uri):
- # type: (nodes.document, str, str) -> nodes.footnote
+ def make_footnote(doc: nodes.document, label: str, uri: str) -> nodes.footnote:
"""Create a footnote node with children"""
footnote = nodes.footnote(uri)
para = nodes.paragraph()
@@ -322,8 +305,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
doc.note_autofootnote(footnote)
return footnote
- def footnote_spot(tree):
- # type: (nodes.document) -> Tuple[nodes.Element, int]
+ def footnote_spot(tree: nodes.document) -> Tuple[Element, int]:
"""Find or create a spot to place footnotes.
The function returns the tuple (parent, index)."""
@@ -371,8 +353,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
footnote.add_backref(footnote_ref['ids'][0])
fn_idx += 1
- def write_doc(self, docname, doctree):
- # type: (str, nodes.document) -> None
+ def write_doc(self, docname: str, doctree: nodes.document) -> None:
"""Write one document file.
This method is overwritten in order to fix fragment identifiers
@@ -382,8 +363,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
self.add_visible_links(doctree, self.config.epub_show_urls)
super().write_doc(docname, doctree)
- def fix_genindex(self, tree):
- # type: (List[Tuple[str, List[Tuple[str, Any]]]]) -> None
+ def fix_genindex(self, tree: List[Tuple[str, List[Tuple[str, Any]]]]) -> None:
"""Fix href attributes for genindex pages."""
# XXX: modifies tree inline
# Logic modeled from themes/basic/genindex.html
@@ -401,14 +381,12 @@ class EpubBuilder(StandaloneHTMLBuilder):
subentrylinks[i] = (ismain,
self.fix_fragment(m.group(1), m.group(2)))
- def is_vector_graphics(self, filename):
- # type: (str) -> bool
+ def is_vector_graphics(self, filename: str) -> bool:
"""Does the filename extension indicate a vector graphic format?"""
ext = path.splitext(filename)[-1]
return ext in VECTOR_GRAPHICS_EXTENSIONS
- def copy_image_files_pil(self):
- # type: () -> None
+ def copy_image_files_pil(self) -> None:
"""Copy images using Pillow, the Python Imaging Libary.
The method tries to read and write the files with Pillow, converting
the format and resizing the image if necessary/possible.
@@ -447,8 +425,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
logger.warning(__('cannot write image file %r: %s'),
path.join(self.srcdir, src), err)
- def copy_image_files(self):
- # type: () -> None
+ def copy_image_files(self) -> None:
"""Copy image files to destination directory.
This overwritten method can use Pillow to convert image files.
"""
@@ -462,13 +439,11 @@ class EpubBuilder(StandaloneHTMLBuilder):
else:
super().copy_image_files()
- def copy_download_files(self):
- # type: () -> None
+ def copy_download_files(self) -> None:
pass
- def handle_page(self, pagename, addctx, templatename='page.html',
- outfilename=None, event_arg=None):
- # type: (str, Dict, str, str, Any) -> None
+ def handle_page(self, pagename: str, addctx: Dict, templatename: str = 'page.html',
+ outfilename: str = None, event_arg: Any = None) -> None:
"""Create a rendered page.
This method is overwritten for genindex pages in order to fix href link
@@ -481,8 +456,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
addctx['doctype'] = self.doctype
super().handle_page(pagename, addctx, templatename, outfilename, event_arg)
- def build_mimetype(self, outdir=None, outname='mimetype'):
- # type: (str, str) -> None
+ def build_mimetype(self, outdir: str = None, outname: str = 'mimetype') -> None:
"""Write the metainfo file mimetype."""
if outdir:
warnings.warn('The arguments of EpubBuilder.build_mimetype() is deprecated.',
@@ -494,8 +468,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
copy_asset_file(path.join(self.template_dir, 'mimetype'),
path.join(outdir, outname))
- def build_container(self, outdir=None, outname='META-INF/container.xml'):
- # type: (str, str) -> None
+ def build_container(self, outdir: str = None, outname: str = 'META-INF/container.xml') -> None: # NOQA
"""Write the metainfo file META-INF/container.xml."""
if outdir:
warnings.warn('The arguments of EpubBuilder.build_container() is deprecated.',
@@ -508,8 +481,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
ensuredir(path.dirname(filename))
copy_asset_file(path.join(self.template_dir, 'container.xml'), filename)
- def content_metadata(self):
- # type: () -> Dict[str, Any]
+ def content_metadata(self) -> Dict[str, Any]:
"""Create a dictionary with all metadata for the content.opf
file properly escaped.
"""
@@ -528,8 +500,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
metadata['guides'] = []
return metadata
- def build_content(self, outdir=None, outname='content.opf'):
- # type: (str, str) -> None
+ def build_content(self, outdir: str = None, outname: str = 'content.opf') -> None:
"""Write the metainfo file content.opf It contains bibliographic data,
a file list and the spine (the reading order).
"""
@@ -648,8 +619,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
path.join(outdir, outname),
metadata)
- def new_navpoint(self, node, level, incr=True):
- # type: (Dict[str, Any], int, bool) -> NavPoint
+ def new_navpoint(self, node: Dict[str, Any], level: int, incr: bool = True) -> NavPoint:
"""Create a new entry in the toc from the node at given level."""
# XXX Modifies the node
if incr:
@@ -658,8 +628,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return NavPoint('navPoint%d' % self.tocid, self.playorder,
node['text'], node['refuri'], [])
- def build_navpoints(self, nodes):
- # type: (List[Dict[str, Any]]) -> List[NavPoint]
+ def build_navpoints(self, nodes: List[Dict[str, Any]]) -> List[NavPoint]:
"""Create the toc navigation structure.
Subelements of a node are nested inside the navpoint. For nested nodes
@@ -703,8 +672,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return navstack[0].children
- def toc_metadata(self, level, navpoints):
- # type: (int, List[NavPoint]) -> Dict[str, Any]
+ def toc_metadata(self, level: int, navpoints: List[NavPoint]) -> Dict[str, Any]:
"""Create a dictionary with all metadata for the toc.ncx file
properly escaped.
"""
@@ -715,8 +683,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
metadata['navpoints'] = navpoints
return metadata
- def build_toc(self, outdir=None, outname='toc.ncx'):
- # type: (str, str) -> None
+ def build_toc(self, outdir: str = None, outname: str = 'toc.ncx') -> None:
"""Write the metainfo file toc.ncx."""
if outdir:
warnings.warn('The arguments of EpubBuilder.build_toc() is deprecated.',
@@ -743,8 +710,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
path.join(outdir, outname),
self.toc_metadata(level, navpoints))
- def build_epub(self, outdir=None, outname=None):
- # type: (str, str) -> None
+ def build_epub(self, outdir: str = None, outname: str = None) -> None:
"""Write the epub file.
It is a zip file with the mimetype file stored uncompressed as the first
diff --git a/sphinx/builders/applehelp.py b/sphinx/builders/applehelp.py
index 0ee50ff56..d7dd336ca 100644
--- a/sphinx/builders/applehelp.py
+++ b/sphinx/builders/applehelp.py
@@ -9,6 +9,7 @@
"""
import warnings
+from typing import Any, Dict
from sphinxcontrib.applehelp import (
AppleHelpCodeSigningFailed,
@@ -16,13 +17,9 @@ from sphinxcontrib.applehelp import (
AppleHelpBuilder,
)
+from sphinx.application import Sphinx
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
-if False:
- # For type annotation
- from typing import Any, Dict # NOQA
- from sphinx.application import Sphinx # NOQA
-
deprecated_alias('sphinx.builders.applehelp',
{
@@ -33,8 +30,7 @@ deprecated_alias('sphinx.builders.applehelp',
RemovedInSphinx40Warning)
-def setup(app):
- # type: (Sphinx) -> Dict[str, Any]
+def setup(app: Sphinx) -> Dict[str, Any]:
warnings.warn('sphinx.builders.applehelp has been moved to sphinxcontrib-applehelp.',
RemovedInSphinx40Warning)
app.setup_extension('sphinxcontrib.applehelp')
diff --git a/sphinx/builders/changes.py b/sphinx/builders/changes.py
index 3b169e493..a42215fad 100644
--- a/sphinx/builders/changes.py
+++ b/sphinx/builders/changes.py
@@ -10,9 +10,11 @@
import html
from os import path
+from typing import Any, Dict, List, Tuple
from typing import cast
from sphinx import package_dir
+from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.domains.changeset import ChangeSetDomain
from sphinx.locale import _, __
@@ -22,11 +24,6 @@ from sphinx.util.console import bold # type: ignore
from sphinx.util.fileutil import copy_asset_file
from sphinx.util.osutil import ensuredir, os_path
-if False:
- # For type annotation
- from typing import Any, Dict, List, Tuple # NOQA
- from sphinx.application import Sphinx # NOQA
-
logger = logging.getLogger(__name__)
@@ -38,15 +35,13 @@ class ChangesBuilder(Builder):
name = 'changes'
epilog = __('The overview file is in %(outdir)s.')
- def init(self):
- # type: () -> None
+ def init(self) -> None:
self.create_template_bridge()
theme_factory = HTMLThemeFactory(self.app)
self.theme = theme_factory.create('default')
self.templates.init(self, self.theme)
- def get_outdated_docs(self):
- # type: () -> str
+ def get_outdated_docs(self) -> str:
return self.outdir
typemap = {
@@ -55,8 +50,7 @@ class ChangesBuilder(Builder):
'deprecated': 'deprecated',
}
- def write(self, *ignored):
- # type: (Any) -> None
+ def write(self, *ignored) -> None:
version = self.config.version
domain = cast(ChangeSetDomain, self.env.get_domain('changeset'))
libchanges = {} # type: Dict[str, List[Tuple[str, str, int]]]
@@ -121,8 +115,7 @@ class ChangesBuilder(Builder):
'.. versionchanged:: %s' % version,
'.. deprecated:: %s' % version]
- def hl(no, line):
- # type: (int, str) -> str
+ def hl(no: int, line: str) -> str:
line = ' ' % no + html.escape(line)
for x in hltext:
if x in line:
@@ -155,21 +148,18 @@ class ChangesBuilder(Builder):
copy_asset_file(path.join(package_dir, 'themes', 'basic', 'static', 'basic.css'),
self.outdir)
- def hl(self, text, version):
- # type: (str, str) -> str
+ def hl(self, text: str, version: str) -> str:
text = html.escape(text)
for directive in ['versionchanged', 'versionadded', 'deprecated']:
text = text.replace('.. %s:: %s' % (directive, version),
'.. %s:: %s' % (directive, version))
return text
- def finish(self):
- # type: () -> None
+ def finish(self) -> None:
pass
-def setup(app):
- # type: (Sphinx) -> Dict[str, Any]
+def setup(app: Sphinx) -> Dict[str, Any]:
app.add_builder(ChangesBuilder)
return {
diff --git a/sphinx/builders/devhelp.py b/sphinx/builders/devhelp.py
index 2306ddee2..17e861777 100644
--- a/sphinx/builders/devhelp.py
+++ b/sphinx/builders/devhelp.py
@@ -11,18 +11,14 @@
"""
import warnings
+from typing import Any, Dict
from sphinxcontrib.devhelp import DevhelpBuilder
+from sphinx.application import Sphinx
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
-if False:
- # For type annotation
- from typing import Any, Dict # NOQA
- from sphinx.application import Sphinx # NOQA
-
-
deprecated_alias('sphinx.builders.devhelp',
{
'DevhelpBuilder': DevhelpBuilder,
@@ -30,8 +26,7 @@ deprecated_alias('sphinx.builders.devhelp',
RemovedInSphinx40Warning)
-def setup(app):
- # type: (Sphinx) -> Dict[str, Any]
+def setup(app: Sphinx) -> Dict[str, Any]:
warnings.warn('sphinx.builders.devhelp has been moved to sphinxcontrib-devhelp.',
RemovedInSphinx40Warning)
app.setup_extension('sphinxcontrib.devhelp')
diff --git a/sphinx/builders/dirhtml.py b/sphinx/builders/dirhtml.py
index d5d61c273..40ec7b11f 100644
--- a/sphinx/builders/dirhtml.py
+++ b/sphinx/builders/dirhtml.py
@@ -9,17 +9,14 @@
"""
from os import path
+from typing import Any, Dict, Set
+from sphinx.application import Sphinx
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
from sphinx.util import logging
from sphinx.util.osutil import SEP, os_path
-if False:
- # For type annotation
- from typing import Any, Dict, Set # NOQA
- from sphinx.application import Sphinx # NOQA
-
logger = logging.getLogger(__name__)
@@ -31,16 +28,14 @@ class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
"""
name = 'dirhtml'
- def get_target_uri(self, docname, typ=None):
- # type: (str, str) -> str
+ def get_target_uri(self, docname: str, typ: str = None) -> str:
if docname == 'index':
return ''
if docname.endswith(SEP + 'index'):
return docname[:-5] # up to sep
return docname + SEP
- def get_outfilename(self, pagename):
- # type: (str) -> str
+ def get_outfilename(self, pagename: str) -> str:
if pagename == 'index' or pagename.endswith(SEP + 'index'):
outfilename = path.join(self.outdir, os_path(pagename) +
self.out_suffix)
@@ -50,8 +45,7 @@ class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
return outfilename
- def prepare_writing(self, docnames):
- # type: (Set[str]) -> None
+ def prepare_writing(self, docnames: Set[str]) -> None:
super().prepare_writing(docnames)
self.globalcontext['no_search_suffix'] = True
@@ -64,8 +58,7 @@ deprecated_alias('sphinx.builders.html',
RemovedInSphinx40Warning)
-def setup(app):
- # type: (Sphinx) -> Dict[str, Any]
+def setup(app: Sphinx) -> Dict[str, Any]:
app.setup_extension('sphinx.builders.html')
app.add_builder(DirectoryHTMLBuilder)
diff --git a/sphinx/builders/dummy.py b/sphinx/builders/dummy.py
index d5ae94a82..33d2506ac 100644
--- a/sphinx/builders/dummy.py
+++ b/sphinx/builders/dummy.py
@@ -8,16 +8,14 @@
:license: BSD, see LICENSE for details.
"""
+from typing import Any, Dict, Set
+from docutils.nodes import Node
+
+from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.locale import __
-if False:
- # For type annotation
- from typing import Any, Dict, Set # NOQA
- from docutils import nodes # NOQA
- from sphinx.application import Sphinx # NOQA
-
class DummyBuilder(Builder):
name = 'dummy'
@@ -25,33 +23,26 @@ class DummyBuilder(Builder):
allow_parallel = True
- def init(self):
- # type: () -> None
+ def init(self) -> None:
pass
- def get_outdated_docs(self):
- # type: () -> Set[str]
+ def get_outdated_docs(self) -> Set[str]:
return self.env.found_docs
- def get_target_uri(self, docname, typ=None):
- # type: (str, str) -> str
+ def get_target_uri(self, docname: str, typ: str = None) -> str:
return ''
- def prepare_writing(self, docnames):
- # type: (Set[str]) -> None
+ def prepare_writing(self, docnames: Set[str]) -> None:
pass
- def write_doc(self, docname, doctree):
- # type: (str, nodes.Node) -> None
+ def write_doc(self, docname: str, doctree: Node) -> None:
pass
- def finish(self):
- # type: () -> None
+ def finish(self) -> None:
pass
-def setup(app):
- # type: (Sphinx) -> Dict[str, Any]
+def setup(app: Sphinx) -> Dict[str, Any]:
app.add_builder(DummyBuilder)
return {
diff --git a/sphinx/builders/epub3.py b/sphinx/builders/epub3.py
index 9b3f58d7a..5d7121fe6 100644
--- a/sphinx/builders/epub3.py
+++ b/sphinx/builders/epub3.py
@@ -13,10 +13,12 @@ import html
import warnings
from collections import namedtuple
from os import path
+from typing import Any, Dict, List, Set, Tuple
from sphinx import package_dir
+from sphinx.application import Sphinx
from sphinx.builders import _epub_base
-from sphinx.config import ENUM
+from sphinx.config import Config, ENUM
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.locale import __
from sphinx.util import logging, xmlname_checker
@@ -24,12 +26,6 @@ from sphinx.util.fileutil import copy_asset_file
from sphinx.util.i18n import format_date
from sphinx.util.osutil import make_filename
-if False:
- # For type annotation
- from typing import Any, Dict, List, Set, Tuple # NOQA
- from sphinx.application import Sphinx # NOQA
- from sphinx.config import Config # NOQA
-
logger = logging.getLogger(__name__)
@@ -75,8 +71,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
use_meta_charset = True
# Finish by building the epub file
- def handle_finish(self):
- # type: () -> None
+ def handle_finish(self) -> None:
"""Create the metainfo files and finally the epub."""
self.get_toc()
self.build_mimetype()
@@ -86,13 +81,11 @@ class Epub3Builder(_epub_base.EpubBuilder):
self.build_toc()
self.build_epub()
- def validate_config_value(self):
- # type: () -> None
+ def validate_config_value(self) -> None:
warnings.warn('Epub3Builder.validate_config_value() is deprecated.',
RemovedInSphinx40Warning, stacklevel=2)
- def content_metadata(self):
- # type: () -> Dict
+ def content_metadata(self) -> Dict:
"""Create a dictionary with all metadata for the content.opf
file properly escaped.
"""
@@ -108,8 +101,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
metadata['epub_version'] = self.config.epub_version
return metadata
- def prepare_writing(self, docnames):
- # type: (Set[str]) -> None
+ def prepare_writing(self, docnames: Set[str]) -> None:
super().prepare_writing(docnames)
writing_mode = self.config.epub_writing_mode
@@ -118,8 +110,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
self.globalcontext['use_meta_charset'] = self.use_meta_charset
self.globalcontext['skip_ua_compatible'] = True
- def build_navlist(self, navnodes):
- # type: (List[Dict[str, Any]]) -> List[NavPoint]
+ def build_navlist(self, navnodes: List[Dict[str, Any]]) -> List[NavPoint]:
"""Create the toc navigation structure.
This method is almost same as build_navpoints method in epub.py.
@@ -161,8 +152,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
return navstack[0].children
- def navigation_doc_metadata(self, navlist):
- # type: (List[NavPoint]) -> Dict
+ def navigation_doc_metadata(self, navlist: List[NavPoint]) -> Dict:
"""Create a dictionary with all metadata for the nav.xhtml file
properly escaped.
"""
@@ -172,8 +162,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
metadata['navlist'] = navlist
return metadata
- def build_navigation_doc(self, outdir=None, outname='nav.xhtml'):
- # type: (str, str) -> None
+ def build_navigation_doc(self, outdir: str = None, outname: str = 'nav.xhtml') -> None:
"""Write the metainfo file nav.xhtml."""
if outdir:
warnings.warn('The arguments of Epub3Builder.build_navigation_doc() '
@@ -202,8 +191,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
self.files.append(outname)
-def validate_config_values(app):
- # type: (Sphinx) -> None
+def validate_config_values(app: Sphinx) -> None:
if app.builder.name != 'epub':
return
@@ -242,8 +230,7 @@ def validate_config_values(app):
logger.warning(__('conf value "version" should not be empty for EPUB3'))
-def convert_epub_css_files(app, config):
- # type: (Sphinx, Config) -> None
+def convert_epub_css_files(app: Sphinx, config: Config) -> None:
"""This converts string styled epub_css_files to tuple styled one."""
epub_css_files = [] # type: List[Tuple[str, Dict]]
for entry in config.epub_css_files:
@@ -260,8 +247,7 @@ def convert_epub_css_files(app, config):
config.epub_css_files = epub_css_files # type: ignore
-def setup(app):
- # type: (Sphinx) -> Dict[str, Any]
+def setup(app: Sphinx) -> Dict[str, Any]:
app.add_builder(Epub3Builder)
# config values
diff --git a/sphinx/builders/gettext.py b/sphinx/builders/gettext.py
index f26b831da..2beb4a5ce 100644
--- a/sphinx/builders/gettext.py
+++ b/sphinx/builders/gettext.py
@@ -14,27 +14,25 @@ from datetime import datetime, tzinfo, timedelta
from io import StringIO
from os import path, walk, getenv
from time import time
+from typing import Any, DefaultDict, Dict, Iterable, List, Set, Tuple, Union
from uuid import uuid4
+from docutils import nodes
+from docutils.nodes import Element
+
from sphinx import addnodes
+from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.domains.python import pairindextypes
from sphinx.errors import ThemeError
from sphinx.locale import __
from sphinx.util import split_index_msg, logging, status_iterator
from sphinx.util.console import bold # type: ignore
-from sphinx.util.i18n import docname_to_domain
+from sphinx.util.i18n import CatalogInfo, docname_to_domain
from sphinx.util.nodes import extract_messages, traverse_translatable_index
from sphinx.util.osutil import relpath, ensuredir, canon_path
from sphinx.util.tags import Tags
-if False:
- # For type annotation
- from typing import Any, DefaultDict, Dict, Iterable, List, Set, Tuple, Union # NOQA
- from docutils import nodes # NOQA
- from sphinx.application import Sphinx # NOQA
- from sphinx.util.i18n import CatalogInfo # NOQA
-
logger = logging.getLogger(__name__)
@@ -63,15 +61,13 @@ msgstr ""
class Catalog:
"""Catalog of translatable messages."""
- def __init__(self):
- # type: () -> None
+ def __init__(self) -> None:
self.messages = [] # type: List[str]
# retain insertion order, a la OrderedDict
self.metadata = OrderedDict() # type: Dict[str, List[Tuple[str, int, str]]]
# msgid -> file, line, uid
- def add(self, msg, origin):
- # type: (str, Union[nodes.Element, MsgOrigin]) -> None
+ def add(self, msg: str, origin: Union[Element, "MsgOrigin"]) -> None:
if not hasattr(origin, 'uid'):
# Nodes that are replicated like todo don't have a uid,
# however i18n is also unnecessary.
@@ -87,8 +83,7 @@ class MsgOrigin:
Origin holder for Catalog message origin.
"""
- def __init__(self, source, line):
- # type: (str, int) -> None
+ def __init__(self, source: str, line: int) -> None:
self.source = source
self.line = line
self.uid = uuid4().hex
@@ -100,8 +95,7 @@ class I18nTags(Tags):
To translate all text inside of only nodes, this class
always returns True value even if no tags are defined.
"""
- def eval_condition(self, condition):
- # type: (Any) -> bool
+ def eval_condition(self, condition: Any) -> bool:
return True
@@ -115,32 +109,26 @@ class I18nBuilder(Builder):
# be set by `gettext_uuid`
use_message_catalog = False
- def init(self):
- # type: () -> None
+ def init(self) -> None:
super().init()
self.env.set_versioning_method(self.versioning_method,
self.env.config.gettext_uuid)
self.tags = I18nTags()
self.catalogs = defaultdict(Catalog) # type: DefaultDict[str, Catalog]
- def get_target_uri(self, docname, typ=None):
- # type: (str, str) -> str
+ def get_target_uri(self, docname: str, typ: str = None) -> str:
return ''
- def get_outdated_docs(self):
- # type: () -> Set[str]
+ def get_outdated_docs(self) -> Set[str]:
return self.env.found_docs
- def prepare_writing(self, docnames):
- # type: (Set[str]) -> None
+ def prepare_writing(self, docnames: Set[str]) -> None:
return
- def compile_catalogs(self, catalogs, message):
- # type: (Set[CatalogInfo], str) -> None
+ def compile_catalogs(self, catalogs: Set[CatalogInfo], message: str) -> None:
return
- def write_doc(self, docname, doctree):
- # type: (str, nodes.document) -> None
+ def write_doc(self, docname: str, doctree: nodes.document) -> None:
catalog = self.catalogs[docname_to_domain(docname, self.config.gettext_compact)]
for toctree in self.env.tocs[docname].traverse(addnodes.toctree):
@@ -176,26 +164,21 @@ if source_date_epoch is not None:
class LocalTimeZone(tzinfo):
-
- def __init__(self, *args, **kw):
- # type: (Any, Any) -> None
+ def __init__(self, *args, **kw) -> None:
super().__init__(*args, **kw) # type: ignore
self.tzdelta = tzdelta
- def utcoffset(self, dt):
- # type: (datetime) -> timedelta
+ def utcoffset(self, dt: datetime) -> timedelta:
return self.tzdelta
- def dst(self, dt):
- # type: (datetime) -> timedelta
+ def dst(self, dt: datetime) -> timedelta:
return timedelta(0)
ltz = LocalTimeZone()
-def should_write(filepath, new_content):
- # type: (str, str) -> bool
+def should_write(filepath: str, new_content: str):
if not path.exists(filepath):
return True
try:
@@ -220,14 +203,12 @@ class MessageCatalogBuilder(I18nBuilder):
name = 'gettext'
epilog = __('The message catalogs are in %(outdir)s.')
- def init(self):
- # type: () -> None
+ def init(self) -> None:
super().init()
self.create_template_bridge()
self.templates.init(self)
- def _collect_templates(self):
- # type: () -> Set[str]
+ def _collect_templates(self) -> Set[str]:
template_files = set()
for template_path in self.config.templates_path:
tmpl_abs_path = path.join(self.app.srcdir, template_path)
@@ -238,8 +219,7 @@ class MessageCatalogBuilder(I18nBuilder):
template_files.add(filename)
return template_files
- def _extract_from_template(self):
- # type: () -> None
+ def _extract_from_template(self) -> None:
files = list(self._collect_templates())
files.sort()
logger.info(bold(__('building [%s]: ') % self.name), nonl=True)
@@ -258,13 +238,11 @@ class MessageCatalogBuilder(I18nBuilder):
except Exception as exc:
raise ThemeError('%s: %r' % (template, exc))
- def build(self, docnames, summary=None, method='update'):
- # type: (Iterable[str], str, str) -> None
+ def build(self, docnames: Iterable[str], summary: str = None, method: str = 'update') -> None: # NOQA
self._extract_from_template()
super().build(docnames, summary, method)
- def finish(self):
- # type: () -> None
+ def finish(self) -> None:
super().finish()
data = {
'version': self.config.version,
@@ -310,8 +288,7 @@ class MessageCatalogBuilder(I18nBuilder):
pofile.write(content)
-def setup(app):
- # type: (Sphinx) -> Dict[str, Any]
+def setup(app: Sphinx) -> Dict[str, Any]:
app.add_builder(MessageCatalogBuilder)
app.add_config_value('gettext_compact', True, 'gettext')
diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py
index 504bbc598..1fd9e6cac 100644
--- a/sphinx/builders/html.py
+++ b/sphinx/builders/html.py
@@ -15,16 +15,21 @@ import sys
import warnings
from hashlib import md5
from os import path
+from typing import Any, Dict, IO, Iterable, Iterator, List, Set, Type, Tuple
from docutils import nodes
from docutils.core import publish_parts
from docutils.frontend import OptionParser
from docutils.io import DocTreeInput, StringOutput
+from docutils.nodes import Node
from docutils.utils import relative_path
from sphinx import package_dir, __display_version__
+from sphinx.application import Sphinx
from sphinx.builders import Builder
+from sphinx.config import Config
from sphinx.deprecation import RemovedInSphinx30Warning, RemovedInSphinx40Warning
+from sphinx.domains import Domain, Index, IndexEntry
from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.environment.adapters.indexentries import IndexEntries
from sphinx.environment.adapters.toctree import TocTree
@@ -41,16 +46,9 @@ from sphinx.util.i18n import format_date
from sphinx.util.inventory import InventoryFile
from sphinx.util.matching import patmatch, Matcher, DOTFILES
from sphinx.util.osutil import os_path, relative_uri, ensuredir, movefile, copyfile
+from sphinx.util.tags import Tags
from sphinx.writers.html import HTMLWriter, HTMLTranslator
-if False:
- # For type annotation
- from typing import Any, Dict, IO, Iterable, Iterator, List, Set, Type, Tuple # NOQA
- from sphinx.application import Sphinx # NOQA
- from sphinx.config import Config # NOQA
- from sphinx.domains import Domain, Index, IndexEntry # NOQA
- from sphinx.util.tags import Tags # NOQA
-
# HTML5 Writer is avialable or not
if is_html5_writer_available():
from sphinx.writers.html5 import HTML5Translator
@@ -65,8 +63,7 @@ logger = logging.getLogger(__name__)
return_codes_re = re.compile('[\r\n]+')
-def get_stable_hash(obj):
- # type: (Any) -> str
+def get_stable_hash(obj: Any) -> str:
"""
Return a stable hash for a Python data structure. We can't just use
the md5 of str(obj) since for example dictionary items are enumerated
@@ -89,8 +86,7 @@ class Stylesheet(str):
attributes = None # type: Dict[str, str]
filename = None # type: str
- def __new__(cls, filename, *args, **attributes):
- # type: (str, str, str) -> None
+ def __new__(cls, filename: str, *args: str, **attributes: str) -> None:
self = str.__new__(cls, filename) # type: ignore
self.filename = filename
self.attributes = attributes
@@ -105,23 +101,20 @@ class Stylesheet(str):
class JSContainer(list):
"""The container for JavaScript scripts."""
- def insert(self, index, obj):
- # type: (int, str) -> None
+ def insert(self, index: int, obj: str) -> None:
warnings.warn('To modify script_files in the theme is deprecated. '
'Please insert a