Merge branch '2.0' into refactor_todo2

This commit is contained in:
Takeshi KOMIYA 2019-06-15 16:45:17 +09:00 committed by GitHub
commit f6dfab33d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
135 changed files with 1931 additions and 2331 deletions

32
CHANGES
View File

@ -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)
=====================================

View File

@ -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
<https://www.transifex.com/>`_. There exists a client tool named ``tx`` in the

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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('&quot;', '"')
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('\'', '&#39;')
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

View File

@ -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')

View File

@ -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 = '<a name="L%s"> </a>' % 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),
'<b>.. %s:: %s</b>' % (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 {

View File

@ -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')

View File

@ -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)

View File

@ -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 {

View File

@ -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

View File

@ -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')

View File

@ -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 <script> tag directly in your theme instead.',
RemovedInSphinx30Warning, stacklevel=3)
super().insert(index, obj)
def extend(self, other): # type: ignore
# type: (List[str]) -> None
def extend(self, other: List[str]) -> None: # type: ignore
warnings.warn('To modify script_files in the theme is deprecated. '
'Please insert a <script> tag directly in your theme instead.',
RemovedInSphinx30Warning, stacklevel=3)
for item in other:
self.append(item)
def __iadd__(self, other): # type: ignore
# type: (List[str]) -> JSContainer
def __iadd__(self, other: List[str]) -> "JSContainer": # type: ignore
warnings.warn('To modify script_files in the theme is deprecated. '
'Please insert a <script> tag directly in your theme instead.',
RemovedInSphinx30Warning, stacklevel=3)
@ -129,8 +122,7 @@ class JSContainer(list):
self.append(item)
return self
def __add__(self, other):
# type: (List[str]) -> JSContainer
def __add__(self, other: List[str]) -> "JSContainer":
ret = JSContainer(self)
ret += other
return ret
@ -146,8 +138,7 @@ class JavaScript(str):
attributes = None # type: Dict[str, str]
filename = None # type: str
def __new__(cls, filename, **attributes):
# type: (str, **str) -> None
def __new__(cls, filename: str, **attributes: str) -> None:
self = str.__new__(cls, filename) # type: ignore
self.filename = filename
self.attributes = attributes
@ -164,8 +155,7 @@ class BuildInfo:
"""
@classmethod
def load(cls, f):
# type: (IO) -> BuildInfo
def load(cls, f: IO) -> "BuildInfo":
try:
lines = f.readlines()
assert lines[0].rstrip() == '# Sphinx build info version 1'
@ -179,8 +169,7 @@ class BuildInfo:
except Exception as exc:
raise ValueError(__('build info file is broken: %r') % exc)
def __init__(self, config=None, tags=None, config_categories=[]):
# type: (Config, Tags, List[str]) -> None
def __init__(self, config: Config = None, tags: Tags = None, config_categories: List[str] = []) -> None: # NOQA
self.config_hash = ''
self.tags_hash = ''
@ -191,13 +180,11 @@ class BuildInfo:
if tags:
self.tags_hash = get_stable_hash(sorted(tags))
def __eq__(self, other): # type: ignore
# type: (BuildInfo) -> bool
def __eq__(self, other: "BuildInfo") -> bool: # type: ignore
return (self.config_hash == other.config_hash and
self.tags_hash == other.tags_hash)
def dump(self, f):
# type: (IO) -> None
def dump(self, f: IO) -> None:
f.write('# Sphinx build info version 1\n'
'# This file hashes the configuration used when building these files.'
' When it is not found, a full rebuild will be done.\n'
@ -237,8 +224,7 @@ class StandaloneHTMLBuilder(Builder):
imgpath = None # type: str
domain_indices = [] # type: List[Tuple[str, Type[Index], List[Tuple[str, List[IndexEntry]]], bool]] # NOQA
def __init__(self, app):
# type: (Sphinx) -> None
def __init__(self, app: Sphinx) -> None:
super().__init__(app)
# CSS files
@ -247,8 +233,7 @@ class StandaloneHTMLBuilder(Builder):
# JS files
self.script_files = JSContainer() # type: List[JavaScript]
def init(self):
# type: () -> None
def init(self) -> None:
self.build_info = self.create_build_info()
# basename of images directory
self.imagedir = '_images'
@ -274,12 +259,10 @@ class StandaloneHTMLBuilder(Builder):
self.use_index = self.get_builder_config('use_index', 'html')
def create_build_info(self):
# type: () -> BuildInfo
def create_build_info(self) -> BuildInfo:
return BuildInfo(self.config, self.tags, ['html'])
def _get_translations_js(self):
# type: () -> str
def _get_translations_js(self) -> str:
candidates = [path.join(dir, self.config.language,
'LC_MESSAGES', 'sphinx.js')
for dir in self.config.locale_dirs] + \
@ -293,12 +276,10 @@ class StandaloneHTMLBuilder(Builder):
return jsfile
return None
def get_theme_config(self):
# type: () -> Tuple[str, Dict]
def get_theme_config(self) -> Tuple[str, Dict]:
return self.config.html_theme, self.config.html_theme_options
def init_templates(self):
# type: () -> None
def init_templates(self) -> None:
theme_factory = HTMLThemeFactory(self.app)
themename, themeoptions = self.get_theme_config()
self.theme = theme_factory.create(themename)
@ -306,8 +287,7 @@ class StandaloneHTMLBuilder(Builder):
self.create_template_bridge()
self.templates.init(self, self.theme)
def init_highlighter(self):
# type: () -> None
def init_highlighter(self) -> None:
# determine Pygments style and create the highlighter
if self.config.pygments_style is not None:
style = self.config.pygments_style
@ -317,23 +297,20 @@ class StandaloneHTMLBuilder(Builder):
style = 'sphinx'
self.highlighter = PygmentsBridge('html', style)
def init_css_files(self):
# type: () -> None
def init_css_files(self) -> None:
for filename, attrs in self.app.registry.css_files:
self.add_css_file(filename, **attrs)
for filename, attrs in self.get_builder_config('css_files', 'html'):
self.add_css_file(filename, **attrs)
def add_css_file(self, filename, **kwargs):
# type: (str, **str) -> None
def add_css_file(self, filename: str, **kwargs: str) -> None:
if '://' not in filename:
filename = posixpath.join('_static', filename)
self.css_files.append(Stylesheet(filename, **kwargs)) # type: ignore
def init_js_files(self):
# type: () -> None
def init_js_files(self) -> None:
self.add_js_file('jquery.js')
self.add_js_file('underscore.js')
self.add_js_file('doctools.js')
@ -348,24 +325,21 @@ class StandaloneHTMLBuilder(Builder):
if self.config.language and self._get_translations_js():
self.add_js_file('translations.js')
def add_js_file(self, filename, **kwargs):
# type: (str, **str) -> None
def add_js_file(self, filename: str, **kwargs: str) -> None:
if filename and '://' not in filename:
filename = posixpath.join('_static', filename)
self.script_files.append(JavaScript(filename, **kwargs))
@property
def default_translator_class(self): # type: ignore
# type: () -> Type[nodes.NodeVisitor]
def default_translator_class(self) -> Type[nodes.NodeVisitor]: # type: ignore
if not html5_ready or self.config.html4_writer:
return HTMLTranslator
else:
return HTML5Translator
@property
def math_renderer_name(self):
# type: () -> str
def math_renderer_name(self) -> str:
name = self.get_builder_config('math_renderer', 'html')
if name is not None:
# use given name
@ -384,8 +358,7 @@ class StandaloneHTMLBuilder(Builder):
# many math_renderers are registered. can't choose automatically!
return None
def get_outdated_docs(self):
# type: () -> Iterator[str]
def get_outdated_docs(self) -> Iterator[str]:
try:
with open(path.join(self.outdir, '.buildinfo')) as fp:
buildinfo = BuildInfo.load(fp)
@ -421,12 +394,10 @@ class StandaloneHTMLBuilder(Builder):
# source doesn't exist anymore
pass
def get_asset_paths(self):
# type: () -> List[str]
def get_asset_paths(self) -> List[str]:
return self.config.html_extra_path + self.config.html_static_path
def render_partial(self, node):
# type: (nodes.Node) -> Dict[str, str]
def render_partial(self, node: Node) -> Dict[str, str]:
"""Utility: Render a lone doctree node."""
if node is None:
return {'fragment': ''}
@ -440,8 +411,7 @@ class StandaloneHTMLBuilder(Builder):
settings_overrides={'output_encoding': 'unicode'},
source=doc)
def prepare_writing(self, docnames):
# type: (Set[str]) -> None
def prepare_writing(self, docnames: Set[str]) -> None:
# create the search indexer
self.indexer = None
if self.search:
@ -550,8 +520,7 @@ class StandaloneHTMLBuilder(Builder):
self.theme.get_options(self.theme_options).items())
self.globalcontext.update(self.config.html_context)
def get_doc_context(self, docname, body, metatags):
# type: (str, str, str) -> Dict[str, Any]
def get_doc_context(self, docname: str, body: str, metatags: str) -> Dict[str, Any]:
"""Collect items for the template context of a page."""
# find out relations
prev = next = None
@ -631,8 +600,7 @@ class StandaloneHTMLBuilder(Builder):
'page_source_suffix': source_suffix,
}
def write_doc(self, docname, doctree):
# type: (str, nodes.document) -> None
def write_doc(self, docname: str, doctree: nodes.document) -> None:
destination = StringOutput(encoding='utf-8')
doctree.settings = self.docsettings
@ -649,16 +617,14 @@ class StandaloneHTMLBuilder(Builder):
ctx = self.get_doc_context(docname, body, metatags)
self.handle_page(docname, ctx, event_arg=doctree)
def write_doc_serialized(self, docname, doctree):
# type: (str, nodes.document) -> None
def write_doc_serialized(self, docname: str, doctree: nodes.document) -> None:
self.imgpath = relative_uri(self.get_target_uri(docname), self.imagedir)
self.post_process_images(doctree)
title_node = self.env.longtitles.get(docname)
title = title_node and self.render_partial(title_node)['title'] or ''
self.index_page(docname, doctree, title)
def finish(self):
# type: () -> None
def finish(self) -> None:
self.finish_tasks.add_task(self.gen_indices)
self.finish_tasks.add_task(self.gen_additional_pages)
self.finish_tasks.add_task(self.copy_image_files)
@ -670,8 +636,7 @@ class StandaloneHTMLBuilder(Builder):
# dump the search index
self.handle_finish()
def gen_indices(self):
# type: () -> None
def gen_indices(self) -> None:
logger.info(bold(__('generating indices...')), nonl=True)
# the global general index
@ -683,8 +648,7 @@ class StandaloneHTMLBuilder(Builder):
logger.info('')
def gen_additional_pages(self):
# type: () -> None
def gen_additional_pages(self) -> None:
# pages from extensions
for pagelist in self.events.emit('html-collect-pages'):
for pagename, context, template in pagelist:
@ -710,8 +674,7 @@ class StandaloneHTMLBuilder(Builder):
logger.info('')
def write_genindex(self):
# type: () -> None
def write_genindex(self) -> None:
# the total count of lines for each index letter, used to distribute
# the entries into two columns
genindex = IndexEntries(self.env).create_index(self)
@ -740,8 +703,7 @@ class StandaloneHTMLBuilder(Builder):
else:
self.handle_page('genindex', genindexcontext, 'genindex.html')
def write_domain_indices(self):
# type: () -> None
def write_domain_indices(self) -> None:
for indexname, indexcls, content, collapse in self.domain_indices:
indexcontext = {
'indextitle': indexcls.localname,
@ -751,8 +713,7 @@ class StandaloneHTMLBuilder(Builder):
logger.info(' ' + indexname, nonl=True)
self.handle_page(indexname, indexcontext, 'domainindex.html')
def copy_image_files(self):
# type: () -> None
def copy_image_files(self) -> None:
if self.images:
stringify_func = ImageAdapter(self.app.env).get_original_image_uri
ensuredir(path.join(self.outdir, self.imagedir))
@ -767,11 +728,10 @@ class StandaloneHTMLBuilder(Builder):
logger.warning(__('cannot copy image file %r: %s'),
path.join(self.srcdir, src), err)
def copy_download_files(self):
# type: () -> None
def to_relpath(f):
# type: (str) -> str
def copy_download_files(self) -> None:
def to_relpath(f: str) -> str:
return relative_path(self.srcdir, f)
# copy downloadable files
if self.env.dlfiles:
ensuredir(path.join(self.outdir, '_downloads'))
@ -786,8 +746,7 @@ class StandaloneHTMLBuilder(Builder):
logger.warning(__('cannot copy downloadable file %r: %s'),
path.join(self.srcdir, src), err)
def copy_static_files(self):
# type: () -> None
def copy_static_files(self) -> None:
try:
# copy static files
logger.info(bold(__('copying static files... ')), nonl=True)
@ -851,8 +810,7 @@ class StandaloneHTMLBuilder(Builder):
except OSError as err:
logger.warning(__('cannot copy static file %r'), err)
def copy_extra_files(self):
# type: () -> None
def copy_extra_files(self) -> None:
try:
# copy html_extra_path files
logger.info(bold(__('copying extra files... ')), nonl=True)
@ -869,22 +827,19 @@ class StandaloneHTMLBuilder(Builder):
except OSError as err:
logger.warning(__('cannot copy extra file %r'), err)
def write_buildinfo(self):
# type: () -> None
def write_buildinfo(self) -> None:
try:
with open(path.join(self.outdir, '.buildinfo'), 'w') as fp:
self.build_info.dump(fp)
except OSError as exc:
logger.warning(__('Failed to write build info file: %r'), exc)
def cleanup(self):
# type: () -> None
def cleanup(self) -> None:
# clean up theme stuff
if self.theme:
self.theme.cleanup()
def post_process_images(self, doctree):
# type: (nodes.Node) -> None
def post_process_images(self, doctree: Node) -> None:
"""Pick the best candidate for an image and link down-scaled images to
their high res version.
"""
@ -909,8 +864,7 @@ class StandaloneHTMLBuilder(Builder):
node.replace_self(reference)
reference.append(node)
def load_indexer(self, docnames):
# type: (Iterable[str]) -> None
def load_indexer(self, docnames: Iterable[str]) -> None:
keep = set(self.env.all_docs) - set(docnames)
try:
searchindexfn = path.join(self.outdir, self.searchindex_filename)
@ -928,8 +882,7 @@ class StandaloneHTMLBuilder(Builder):
# delete all entries for files that will be rebuilt
self.indexer.prune(keep)
def index_page(self, pagename, doctree, title):
# type: (str, nodes.document, str) -> None
def index_page(self, pagename: str, doctree: nodes.document, title: str) -> None:
# only index pages with title
if self.indexer is not None and title:
filename = self.env.doc2path(pagename, base=None)
@ -945,22 +898,19 @@ class StandaloneHTMLBuilder(Builder):
indexer_name, indexer_name),
RemovedInSphinx40Warning)
def _get_local_toctree(self, docname, collapse=True, **kwds):
# type: (str, bool, Any) -> str
def _get_local_toctree(self, docname: str, collapse: bool = True, **kwds) -> str:
if 'includehidden' not in kwds:
kwds['includehidden'] = False
return self.render_partial(TocTree(self.env).get_toctree_for(
docname, self, collapse, **kwds))['fragment']
def get_outfilename(self, pagename):
# type: (str) -> str
def get_outfilename(self, pagename: str) -> str:
return path.join(self.outdir, os_path(pagename) + self.out_suffix)
def add_sidebars(self, pagename, ctx):
# type: (str, Dict) -> None
def has_wildcard(pattern):
# type: (str) -> bool
def add_sidebars(self, pagename: str, ctx: Dict) -> None:
def has_wildcard(pattern: str) -> bool:
return any(char in pattern for char in '*?[')
sidebars = None
matched = None
customsidebar = None
@ -1009,13 +959,11 @@ class StandaloneHTMLBuilder(Builder):
# --------- these are overwritten by the serialization builder
def get_target_uri(self, docname, typ=None):
# type: (str, str) -> str
def get_target_uri(self, docname: str, typ: str = None) -> str:
return docname + self.link_suffix
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:
ctx = self.globalcontext.copy()
# current_page_name is backwards compatibility
ctx['pagename'] = ctx['current_page_name'] = pagename
@ -1031,8 +979,7 @@ class StandaloneHTMLBuilder(Builder):
else:
ctx['pageurl'] = None
def pathto(otheruri, resource=False, baseuri=default_baseuri):
# type: (str, bool, str) -> str
def pathto(otheruri: str, resource: bool = False, baseuri: str = default_baseuri) -> str: # NOQA
if resource and '://' in otheruri:
# allow non-local resources given by scheme
return otheruri
@ -1044,8 +991,7 @@ class StandaloneHTMLBuilder(Builder):
return uri
ctx['pathto'] = pathto
def css_tag(css):
# type: (Stylesheet) -> str
def css_tag(css: Stylesheet) -> str:
attrs = []
for key in sorted(css.attributes):
value = css.attributes[key]
@ -1055,8 +1001,7 @@ class StandaloneHTMLBuilder(Builder):
return '<link %s />' % ' '.join(attrs)
ctx['css_tag'] = css_tag
def hasdoc(name):
# type: (str) -> bool
def hasdoc(name: str) -> bool:
if name in self.env.all_docs:
return True
elif name == 'search' and self.search:
@ -1066,8 +1011,7 @@ class StandaloneHTMLBuilder(Builder):
return False
ctx['hasdoc'] = hasdoc
def warn(*args, **kwargs):
# type: (Any, Any) -> str
def warn(*args, **kwargs) -> str:
"""Simple warn() wrapper for themes."""
warnings.warn('The template function warn() was deprecated. '
'Use warning() instead.',
@ -1114,24 +1058,21 @@ class StandaloneHTMLBuilder(Builder):
ensuredir(path.dirname(source_name))
copyfile(self.env.doc2path(pagename), source_name)
def update_page_context(self, pagename, templatename, ctx, event_arg):
# type: (str, str, Dict, Any) -> None
def update_page_context(self, pagename: str, templatename: str,
ctx: Dict, event_arg: Any) -> None:
pass
def handle_finish(self):
# type: () -> None
def handle_finish(self) -> None:
if self.indexer:
self.finish_tasks.add_task(self.dump_search_index)
self.finish_tasks.add_task(self.dump_inventory)
def dump_inventory(self):
# type: () -> None
def dump_inventory(self) -> None:
logger.info(bold(__('dumping object inventory... ')), nonl=True)
InventoryFile.dump(path.join(self.outdir, INVENTORY_FILENAME), self.env, self)
logger.info(__('done'))
def dump_search_index(self):
# type: () -> None
def dump_search_index(self) -> None:
logger.info(
bold(__('dumping search index in %s ... ') % self.indexer.label()),
nonl=True)
@ -1149,8 +1090,7 @@ class StandaloneHTMLBuilder(Builder):
logger.info(__('done'))
def convert_html_css_files(app, config):
# type: (Sphinx, Config) -> None
def convert_html_css_files(app: Sphinx, config: Config) -> None:
"""This converts string styled html_css_files to tuple styled one."""
html_css_files = [] # type: List[Tuple[str, Dict]]
for entry in config.html_css_files:
@ -1167,8 +1107,7 @@ def convert_html_css_files(app, config):
config.html_css_files = html_css_files # type: ignore
def convert_html_js_files(app, config):
# type: (Sphinx, Config) -> None
def convert_html_js_files(app: Sphinx, config: Config) -> None:
"""This converts string styled html_js_files to tuple styled one."""
html_js_files = [] # type: List[Tuple[str, Dict]]
for entry in config.html_js_files:
@ -1185,16 +1124,15 @@ def convert_html_js_files(app, config):
config.html_js_files = html_js_files # type: ignore
def setup_js_tag_helper(app, pagename, templatexname, context, doctree):
# type: (Sphinx, str, str, Dict, nodes.Node) -> None
def setup_js_tag_helper(app: Sphinx, pagename: str, templatexname: str,
context: Dict, doctree: Node) -> None:
"""Set up js_tag() template helper.
.. note:: This set up function is added to keep compatibility with webhelper.
"""
pathto = context.get('pathto')
def js_tag(js):
# type: (JavaScript) -> str
def js_tag(js: JavaScript) -> str:
attrs = []
body = ''
if isinstance(js, JavaScript):
@ -1216,8 +1154,7 @@ def setup_js_tag_helper(app, pagename, templatexname, context, doctree):
context['js_tag'] = js_tag
def validate_math_renderer(app):
# type: (Sphinx) -> None
def validate_math_renderer(app: Sphinx) -> None:
if app.builder.format != 'html':
return
@ -1235,8 +1172,7 @@ import sphinx.builders.singlehtml # NOQA
import sphinxcontrib.serializinghtml # NOQA
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
# builders
app.add_builder(StandaloneHTMLBuilder)

View File

@ -10,20 +10,16 @@
"""
import warnings
from typing import Any, Dict
from sphinxcontrib.htmlhelp import (
chm_locales, chm_htmlescape, HTMLHelpBuilder, default_htmlhelp_basename
)
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.htmlhelp',
{
'chm_locales': chm_locales,
@ -34,8 +30,7 @@ deprecated_alias('sphinx.builders.htmlhelp',
RemovedInSphinx40Warning)
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
warnings.warn('sphinx.builders.htmlhelp has been moved to sphinxcontrib-htmlhelp.',
RemovedInSphinx40Warning)
app.setup_extension('sphinxcontrib.htmlhelp')

View File

@ -11,14 +11,17 @@
import os
import warnings
from os import path
from typing import Any, Dict, Iterable, List, Tuple, Union
from docutils.frontend import OptionParser
from docutils.nodes import Node
import sphinx.builders.latex.nodes # NOQA # Workaround: import this before writer to avoid ImportError
from sphinx import package_dir, addnodes, highlighting
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.builders.latex.util import ExtBabel
from sphinx.config import ENUM
from sphinx.config import Config, ENUM
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.errors import NoUri, SphinxError
@ -38,12 +41,6 @@ from sphinx.writers.latex import (
# load docutils.nodes after loading sphinx.builders.latex.nodes
from docutils import nodes # NOQA
if False:
# For type annotation
from typing import Any, Dict, Iterable, List, Tuple, Union # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA
XINDY_LANG_OPTIONS = {
# language codes from docutils.writers.latex2e.Babel
@ -125,8 +122,7 @@ class LaTeXBuilder(Builder):
supported_remote_images = False
default_translator_class = LaTeXTranslator
def init(self):
# type: () -> None
def init(self) -> None:
self.babel = None # type: ExtBabel
self.context = {} # type: Dict[str, Any]
self.docnames = [] # type: Iterable[str]
@ -137,24 +133,20 @@ class LaTeXBuilder(Builder):
self.init_context()
self.init_babel()
def get_outdated_docs(self):
# type: () -> Union[str, List[str]]
def get_outdated_docs(self) -> Union[str, List[str]]:
return 'all documents' # for now
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 not in self.docnames:
raise NoUri
else:
return '%' + docname
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:
# ignore source path
return self.get_target_uri(to, typ)
def init_document_data(self):
# type: () -> None
def init_document_data(self) -> None:
preliminary_document_data = [list(x) for x in self.config.latex_documents]
if not preliminary_document_data:
logger.warning(__('no "latex_documents" config value found; no documents '
@ -173,8 +165,7 @@ class LaTeXBuilder(Builder):
docname = docname[:-5]
self.titles.append((docname, entry[2]))
def init_context(self):
# type: () -> None
def init_context(self) -> None:
self.context = DEFAULT_SETTINGS.copy()
# Add special settings for latex_engine
@ -208,8 +199,7 @@ class LaTeXBuilder(Builder):
# Show the release label only if release value exists
self.context.setdefault('releasename', _('Release'))
def init_babel(self):
# type: () -> None
def init_babel(self) -> None:
self.babel = ExtBabel(self.config.language, not self.context['babel'])
if self.config.language and not self.babel.is_supported_language():
# emit warning if specified language is invalid
@ -217,8 +207,7 @@ class LaTeXBuilder(Builder):
logger.warning(__('no Babel option known for language %r'),
self.config.language)
def write_stylesheet(self):
# type: () -> None
def write_stylesheet(self) -> None:
highlighter = highlighting.PygmentsBridge('latex', self.config.pygments_style)
stylesheet = path.join(self.outdir, 'sphinxhighlight.sty')
with open(stylesheet, 'w') as f:
@ -227,8 +216,7 @@ class LaTeXBuilder(Builder):
'[2016/05/29 stylesheet for highlighting with pygments]\n\n')
f.write(highlighter.get_stylesheet())
def write(self, *ignored):
# type: (Any) -> None
def write(self, *ignored) -> None:
docwriter = LaTeXWriter(self)
docsettings = OptionParser(
defaults=self.env.settings,
@ -271,8 +259,7 @@ class LaTeXBuilder(Builder):
doctree.settings = docsettings
docwriter.write(doctree, destination)
def get_contentsname(self, indexfile):
# type: (str) -> str
def get_contentsname(self, indexfile: str) -> str:
tree = self.env.get_doctree(indexfile)
contentsname = None
for toctree in tree.traverse(addnodes.toctree):
@ -282,13 +269,11 @@ class LaTeXBuilder(Builder):
return contentsname
def update_doc_context(self, title, author):
# type: (str, str) -> None
def update_doc_context(self, title: str, author: str) -> None:
self.context['title'] = title
self.context['author'] = author
def assemble_doctree(self, indexfile, toctree_only, appendices):
# type: (str, bool, List[str]) -> nodes.document
def assemble_doctree(self, indexfile: str, toctree_only: bool, appendices: List[str]) -> nodes.document: # NOQA
self.docnames = set([indexfile] + appendices)
logger.info(darkgreen(indexfile) + " ", nonl=True)
tree = self.env.get_doctree(indexfile)
@ -319,7 +304,7 @@ class LaTeXBuilder(Builder):
for pendingnode in largetree.traverse(addnodes.pending_xref):
docname = pendingnode['refdocname']
sectname = pendingnode['refsectname']
newnodes = [nodes.emphasis(sectname, sectname)] # type: List[nodes.Node]
newnodes = [nodes.emphasis(sectname, sectname)] # type: List[Node]
for subdir, title in self.titles:
if docname.startswith(subdir):
newnodes.append(nodes.Text(_(' (in '), _(' (in ')))
@ -331,13 +316,11 @@ class LaTeXBuilder(Builder):
pendingnode.replace_self(newnodes)
return largetree
def apply_transforms(self, doctree):
# type: (nodes.document) -> None
def apply_transforms(self, doctree: nodes.document) -> None:
warnings.warn('LaTeXBuilder.apply_transforms() is deprecated.',
RemovedInSphinx40Warning)
def finish(self):
# type: () -> None
def finish(self) -> None:
self.copy_image_files()
self.write_message_catalog()
self.copy_support_files()
@ -346,8 +329,7 @@ class LaTeXBuilder(Builder):
self.copy_latex_additional_files()
@progress_message(__('copying TeX support files'))
def copy_support_files(self):
# type: () -> None
def copy_support_files(self) -> None:
"""copy TeX support files from texinputs."""
# configure usage of xindy (impacts Makefile and latexmkrc)
# FIXME: convert this rather to a confval with suitable default
@ -387,14 +369,12 @@ class LaTeXBuilder(Builder):
copy_asset_file(path.join(self.confdir, self.config.latex_logo), self.outdir)
@progress_message(__('copying additional files'))
def copy_latex_additional_files(self):
# type: () -> None
def copy_latex_additional_files(self) -> None:
for filename in self.config.latex_additional_files:
logger.info(' ' + filename, nonl=True)
copy_asset_file(path.join(self.confdir, filename), self.outdir)
def copy_image_files(self):
# type: () -> None
def copy_image_files(self) -> None:
if self.images:
stringify_func = ImageAdapter(self.app.env).get_original_image_uri
for src in status_iterator(self.images, __('copying images... '), "brown",
@ -408,8 +388,7 @@ class LaTeXBuilder(Builder):
logger.warning(__('cannot copy image file %r: %s'),
path.join(self.srcdir, src), err)
def write_message_catalog(self):
# type: () -> None
def write_message_catalog(self) -> None:
formats = self.config.numfig_format
context = {
'addtocaptions': r'\@iden',
@ -425,8 +404,7 @@ class LaTeXBuilder(Builder):
copy_asset_file(filename, self.outdir, context=context, renderer=LaTeXRenderer())
def validate_config_values(app, config):
# type: (Sphinx, Config) -> None
def validate_config_values(app: Sphinx, config: Config) -> None:
for key in list(config.latex_elements):
if key not in DEFAULT_SETTINGS:
msg = __("Unknown configure key: latex_elements[%r]. ignored.")
@ -434,8 +412,7 @@ def validate_config_values(app, config):
config.latex_elements.pop(key)
def default_latex_engine(config):
# type: (Config) -> str
def default_latex_engine(config: Config) -> str:
""" Better default latex_engine settings for specific languages. """
if config.language == 'ja':
return 'platex'
@ -445,8 +422,7 @@ def default_latex_engine(config):
return 'pdflatex'
def default_latex_docclass(config):
# type: (Config) -> Dict[str, str]
def default_latex_docclass(config: Config) -> Dict[str, str]:
""" Better default latex_docclass settings for specific languages. """
if config.language == 'ja':
return {'manual': 'jsbook',
@ -455,14 +431,12 @@ def default_latex_docclass(config):
return {}
def default_latex_use_xindy(config):
# type: (Config) -> bool
def default_latex_use_xindy(config: Config) -> bool:
""" Better default latex_use_xindy settings for specific engines. """
return config.latex_engine in {'xelatex', 'lualatex'}
def default_latex_documents(config):
# type: (Config) -> List[Tuple[str, str, str, str, str]]
def default_latex_documents(config: Config) -> List[Tuple[str, str, str, str, str]]:
""" Better default latex_documents settings. """
return [(config.master_doc,
make_filename_from_project(config.project) + '.tex',
@ -471,8 +445,7 @@ def default_latex_documents(config):
'manual')]
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
app.setup_extension('sphinx.builders.latex.transforms')
app.add_builder(LaTeXBuilder)

View File

@ -8,11 +8,14 @@
:license: BSD, see LICENSE for details.
"""
from typing import Any, Dict, List, Set, Tuple
from typing import cast
from docutils import nodes
from docutils.nodes import Element, Node
from sphinx import addnodes
from sphinx.application import Sphinx
from sphinx.builders.latex.nodes import (
captioned_literal_block, footnotemark, footnotetext, math_reference, thebibliography
)
@ -21,11 +24,6 @@ from sphinx.transforms import SphinxTransform
from sphinx.transforms.post_transforms import SphinxPostTransform
from sphinx.util.nodes import NodeMatcher
if False:
# For type annotation
from typing import Any, Dict, List, Set, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
URI_SCHEMES = ('mailto:', 'http:', 'https:', 'ftp:')
@ -34,8 +32,7 @@ class FootnoteDocnameUpdater(SphinxTransform):
default_priority = 700
TARGET_NODES = (nodes.footnote, nodes.footnote_reference)
def apply(self, **kwargs):
# type: (Any) -> None
def apply(self, **kwargs) -> None:
matcher = NodeMatcher(*self.TARGET_NODES)
for node in self.document.traverse(matcher): # type: nodes.Element
node['docname'] = self.env.docname
@ -54,8 +51,7 @@ class ShowUrlsTransform(SphinxPostTransform):
# references are expanded to footnotes (or not)
expanded = False
def run(self, **kwargs):
# type: (Any) -> None
def run(self, **kwargs) -> None:
try:
# replace id_prefix temporarily
settings = self.document.settings # type: Any
@ -69,8 +65,7 @@ class ShowUrlsTransform(SphinxPostTransform):
# restore id_prefix
settings.id_prefix = id_prefix
def expand_show_urls(self):
# type: () -> None
def expand_show_urls(self) -> None:
show_urls = self.config.latex_show_urls
if show_urls is False or show_urls == 'no':
return
@ -93,8 +88,7 @@ class ShowUrlsTransform(SphinxPostTransform):
textnode = nodes.Text(" (%s)" % uri)
node.parent.insert(index + 1, textnode)
def get_docname_for_node(self, node):
# type: (nodes.Node) -> str
def get_docname_for_node(self, node: Node) -> str:
while node:
if isinstance(node, nodes.document):
return self.env.path2doc(node['source'])
@ -105,8 +99,7 @@ class ShowUrlsTransform(SphinxPostTransform):
return None # never reached here. only for type hinting
def create_footnote(self, uri, docname):
# type: (str, str) -> Tuple[nodes.footnote, nodes.footnote_reference]
def create_footnote(self, uri: str, docname: str) -> Tuple[nodes.footnote, nodes.footnote_reference]: # NOQA
reference = nodes.reference('', nodes.Text(uri), refuri=uri, nolinkurl=True)
footnote = nodes.footnote(uri, auto=1, docname=docname)
footnote['names'].append('#')
@ -122,8 +115,7 @@ class ShowUrlsTransform(SphinxPostTransform):
return footnote, footnote_ref
def renumber_footnotes(self):
# type: () -> None
def renumber_footnotes(self) -> None:
collector = FootnoteCollector(self.document)
self.document.walkabout(collector)
@ -153,31 +145,26 @@ class ShowUrlsTransform(SphinxPostTransform):
class FootnoteCollector(nodes.NodeVisitor):
"""Collect footnotes and footnote references on the document"""
def __init__(self, document):
# type: (nodes.document) -> None
def __init__(self, document: nodes.document) -> None:
self.auto_footnotes = [] # type: List[nodes.footnote]
self.used_footnote_numbers = set() # type: Set[str]
self.footnote_refs = [] # type: List[nodes.footnote_reference]
super().__init__(document)
def unknown_visit(self, node):
# type: (nodes.Node) -> None
def unknown_visit(self, node: Node) -> None:
pass
def unknown_departure(self, node):
# type: (nodes.Node) -> None
def unknown_departure(self, node: Node) -> None:
pass
def visit_footnote(self, node):
# type: (nodes.footnote) -> None
def visit_footnote(self, node: nodes.footnote) -> None:
if node.get('auto'):
self.auto_footnotes.append(node)
else:
for name in node['names']:
self.used_footnote_numbers.add(name)
def visit_footnote_reference(self, node):
# type: (nodes.footnote_reference) -> None
def visit_footnote_reference(self, node: nodes.footnote_reference) -> None:
self.footnote_refs.append(node)
@ -351,8 +338,7 @@ class LaTeXFootnoteTransform(SphinxPostTransform):
default_priority = 600
builders = ('latex',)
def run(self, **kwargs):
# type: (Any) -> None
def run(self, **kwargs) -> None:
footnotes = list(self.document.traverse(nodes.footnote))
for node in footnotes:
node.parent.remove(node)
@ -362,8 +348,7 @@ class LaTeXFootnoteTransform(SphinxPostTransform):
class LaTeXFootnoteVisitor(nodes.NodeVisitor):
def __init__(self, document, footnotes):
# type: (nodes.document, List[nodes.footnote]) -> None
def __init__(self, document: nodes.document, footnotes: List[nodes.footnote]) -> None:
self.appeared = set() # type: Set[Tuple[str, str]]
self.footnotes = footnotes # type: List[nodes.footnote]
self.pendings = [] # type: List[nodes.footnote]
@ -371,21 +356,17 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
self.restricted = None # type: nodes.Element
super().__init__(document)
def unknown_visit(self, node):
# type: (nodes.Node) -> None
def unknown_visit(self, node: Node) -> None:
pass
def unknown_departure(self, node):
# type: (nodes.Node) -> None
def unknown_departure(self, node: Node) -> None:
pass
def restrict(self, node):
# type: (nodes.Element) -> None
def restrict(self, node: Element) -> None:
if self.restricted is None:
self.restricted = node
def unrestrict(self, node):
# type: (nodes.Element) -> None
def unrestrict(self, node: Element) -> None:
if self.restricted == node:
self.restricted = None
pos = node.parent.index(node)
@ -394,37 +375,29 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
node.parent.insert(pos + i + 1, fntext)
self.pendings = []
def visit_figure(self, node):
# type: (nodes.figure) -> None
def visit_figure(self, node: nodes.figure) -> None:
self.restrict(node)
def depart_figure(self, node):
# type: (nodes.figure) -> None
def depart_figure(self, node: nodes.figure) -> None:
self.unrestrict(node)
def visit_term(self, node):
# type: (nodes.term) -> None
def visit_term(self, node: nodes.term) -> None:
self.restrict(node)
def depart_term(self, node):
# type: (nodes.term) -> None
def depart_term(self, node: nodes.term) -> None:
self.unrestrict(node)
def visit_caption(self, node):
# type: (nodes.caption) -> None
def visit_caption(self, node: nodes.caption) -> None:
self.restrict(node)
def depart_caption(self, node):
# type: (nodes.caption) -> None
def depart_caption(self, node: nodes.caption) -> None:
self.unrestrict(node)
def visit_title(self, node):
# type: (nodes.title) -> None
def visit_title(self, node: nodes.title) -> None:
if isinstance(node.parent, (nodes.section, nodes.table)):
self.restrict(node)
def depart_title(self, node):
# type: (nodes.title) -> None
def depart_title(self, node: nodes.title) -> None:
if isinstance(node.parent, nodes.section):
self.unrestrict(node)
elif isinstance(node.parent, nodes.table):
@ -432,18 +405,15 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
self.pendings = []
self.unrestrict(node)
def visit_thead(self, node):
# type: (nodes.thead) -> None
def visit_thead(self, node: nodes.thead) -> None:
self.restrict(node)
def depart_thead(self, node):
# type: (nodes.thead) -> None
def depart_thead(self, node: nodes.thead) -> None:
self.table_footnotes += self.pendings
self.pendings = []
self.unrestrict(node)
def depart_table(self, node):
# type: (nodes.table) -> None
def depart_table(self, node: nodes.table) -> None:
tbody = list(node.traverse(nodes.tbody))[0]
for footnote in reversed(self.table_footnotes):
fntext = footnotetext('', *footnote.children)
@ -451,16 +421,13 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
self.table_footnotes = []
def visit_footnote(self, node):
# type: (nodes.footnote) -> None
def visit_footnote(self, node: nodes.footnote) -> None:
self.restrict(node)
def depart_footnote(self, node):
# type: (nodes.footnote) -> None
def depart_footnote(self, node: nodes.footnote) -> None:
self.unrestrict(node)
def visit_footnote_reference(self, node):
# type: (nodes.footnote_reference) -> None
def visit_footnote_reference(self, node: nodes.footnote_reference) -> None:
number = node.astext().strip()
docname = node['docname']
if self.restricted:
@ -481,8 +448,7 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
self.appeared.add((docname, number))
raise nodes.SkipNode
def get_footnote_by_reference(self, node):
# type: (nodes.footnote_reference) -> nodes.footnote
def get_footnote_by_reference(self, node: nodes.footnote_reference) -> nodes.footnote:
docname = node['docname']
for footnote in self.footnotes:
if docname == footnote['docname'] and footnote['ids'][0] == node['refid']:
@ -524,8 +490,7 @@ class BibliographyTransform(SphinxPostTransform):
default_priority = 750
builders = ('latex',)
def run(self, **kwargs):
# type: (Any) -> None
def run(self, **kwargs) -> None:
citations = thebibliography()
for node in self.document.traverse(nodes.citation):
node.parent.remove(node)
@ -544,8 +509,7 @@ class CitationReferenceTransform(SphinxPostTransform):
default_priority = 5 # before ReferencesResolver
builders = ('latex',)
def run(self, **kwargs):
# type: (Any) -> None
def run(self, **kwargs) -> None:
domain = cast(CitationDomain, self.env.get_domain('citation'))
matcher = NodeMatcher(addnodes.pending_xref, refdomain='citation', reftype='ref')
for node in self.document.traverse(matcher): # type: addnodes.pending_xref
@ -565,8 +529,7 @@ class MathReferenceTransform(SphinxPostTransform):
default_priority = 5 # before ReferencesResolver
builders = ('latex',)
def run(self, **kwargs):
# type: (Any) -> None
def run(self, **kwargs) -> None:
equations = self.env.get_domain('math').data['objects']
for node in self.document.traverse(addnodes.pending_xref):
if node['refdomain'] == 'math' and node['reftype'] in ('eq', 'numref'):
@ -581,8 +544,7 @@ class LiteralBlockTransform(SphinxPostTransform):
default_priority = 400
builders = ('latex',)
def run(self, **kwargs):
# type: (Any) -> None
def run(self, **kwargs) -> None:
matcher = NodeMatcher(nodes.container, literal_block=True)
for node in self.document.traverse(matcher): # type: nodes.container
newnode = captioned_literal_block('', *node.children, **node.attributes)
@ -594,8 +556,7 @@ class DocumentTargetTransform(SphinxPostTransform):
default_priority = 400
builders = ('latex',)
def run(self, **kwargs):
# type: (Any) -> None
def run(self, **kwargs) -> None:
for node in self.document.traverse(addnodes.start_of_file):
section = node.next_node(nodes.section)
if section:
@ -639,8 +600,7 @@ class IndexInSectionTitleTransform(SphinxTransform):
node.parent.insert(i + 1, index)
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_transform(FootnoteDocnameUpdater)
app.add_post_transform(BibliographyTransform)
app.add_post_transform(CitationReferenceTransform)

View File

@ -18,30 +18,25 @@ from sphinx.deprecation import RemovedInSphinx30Warning
class ExtBabel(Babel):
cyrillic_languages = ('bulgarian', 'kazakh', 'mongolian', 'russian', 'ukrainian')
def __init__(self, language_code, use_polyglossia=False):
# type: (str, bool) -> None
def __init__(self, language_code: str, use_polyglossia: bool = False) -> None:
self.language_code = language_code
self.use_polyglossia = use_polyglossia
self.supported = True
super().__init__(language_code or '')
def get_shorthandoff(self):
# type: () -> str
def get_shorthandoff(self) -> str:
warnings.warn('ExtBabel.get_shorthandoff() is deprecated.',
RemovedInSphinx30Warning, stacklevel=2)
from sphinx.writers.latex import SHORTHANDOFF
return SHORTHANDOFF
def uses_cyrillic(self):
# type: () -> bool
def uses_cyrillic(self) -> bool:
return self.language in self.cyrillic_languages
def is_supported_language(self):
# type: () -> bool
def is_supported_language(self) -> bool:
return self.supported
def language_name(self, language_code):
# type: (str) -> str
def language_name(self, language_code: str) -> str:
language = super().language_name(language_code)
if language == 'ngerman' and self.use_polyglossia:
# polyglossia calls new orthography (Neue Rechtschreibung) as
@ -55,8 +50,7 @@ class ExtBabel(Babel):
self.supported = False
return 'english' # fallback to english
def get_mainlanguage_options(self):
# type: () -> str
def get_mainlanguage_options(self) -> str:
"""Return options for polyglossia's ``\\setmainlanguage``."""
if self.use_polyglossia is False:
return None

View File

@ -14,11 +14,14 @@ import socket
import threading
from html.parser import HTMLParser
from os import path
from typing import Any, Dict, List, Set, Tuple
from urllib.parse import unquote
from docutils import nodes
from docutils.nodes import Node
from requests.exceptions import HTTPError
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.locale import __
from sphinx.util import encode_uri, requests, logging
@ -28,12 +31,6 @@ from sphinx.util.console import ( # type: ignore
from sphinx.util.nodes import get_node_line
from sphinx.util.requests import is_ssl_error
if False:
# For type annotation
from typing import Any, Dict, List, Set, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.util.requests.requests import Response # NOQA
logger = logging.getLogger(__name__)
@ -41,23 +38,20 @@ logger = logging.getLogger(__name__)
class AnchorCheckParser(HTMLParser):
"""Specialized HTML parser that looks for a specific anchor."""
def __init__(self, search_anchor):
# type: (str) -> None
def __init__(self, search_anchor: str) -> None:
super().__init__()
self.search_anchor = search_anchor
self.found = False
def handle_starttag(self, tag, attrs):
# type: (Any, Any) -> None
def handle_starttag(self, tag: Any, attrs: Any) -> None:
for key, value in attrs:
if key in ('id', 'name') and value == self.search_anchor:
self.found = True
break
def check_anchor(response, anchor):
# type: (Response, str) -> bool
def check_anchor(response: requests.requests.Response, anchor: str) -> bool:
"""Reads HTML data from a response object `response` searching for `anchor`.
Returns True if anchor was found, False otherwise.
"""
@ -80,8 +74,7 @@ class CheckExternalLinksBuilder(Builder):
epilog = __('Look for any errors in the above output or in '
'%(outdir)s/output.txt')
def init(self):
# type: () -> None
def init(self) -> None:
self.to_ignore = [re.compile(x) for x in self.app.config.linkcheck_ignore]
self.anchors_ignore = [re.compile(x)
for x in self.app.config.linkcheck_anchors_ignore]
@ -103,8 +96,7 @@ class CheckExternalLinksBuilder(Builder):
thread.start()
self.workers.append(thread)
def check_thread(self):
# type: () -> None
def check_thread(self) -> None:
kwargs = {
'allow_redirects': True,
'headers': {
@ -115,8 +107,7 @@ class CheckExternalLinksBuilder(Builder):
if self.app.config.linkcheck_timeout:
kwargs['timeout'] = self.app.config.linkcheck_timeout
def check_uri():
# type: () -> Tuple[str, str, int]
def check_uri() -> Tuple[str, str, int]:
# split off anchor
if '#' in uri:
req_url, anchor = uri.split('#', 1)
@ -159,6 +150,9 @@ class CheckExternalLinksBuilder(Builder):
if err.response.status_code == 401:
# We'll take "Unauthorized" as working.
return 'working', ' - unauthorized', 0
elif err.response.status_code == 503:
# We'll take "Service Unavailable" as ignored.
return 'ignored', str(err), 0
else:
return 'broken', str(err), 0
except Exception as err:
@ -179,8 +173,7 @@ class CheckExternalLinksBuilder(Builder):
else:
return 'redirected', new_url, 0
def check():
# type: () -> Tuple[str, str, int]
def check() -> Tuple[str, str, int]:
# check for various conditions without bothering the network
if len(uri) == 0 or uri.startswith(('#', 'mailto:', 'ftp:')):
return 'unchecked', '', 0
@ -218,8 +211,7 @@ class CheckExternalLinksBuilder(Builder):
status, info, code = check()
self.rqueue.put((uri, docname, lineno, status, info, code))
def process_result(self, result):
# type: (Tuple[str, str, int, str, str, int]) -> None
def process_result(self, result: Tuple[str, str, int, str, str, int]) -> None:
uri, docname, lineno, status, info, code = result
if status == 'unchecked':
return
@ -256,20 +248,16 @@ class CheckExternalLinksBuilder(Builder):
uri + ' to ' + info)
logger.info(color('redirect ') + uri + color(' - ' + text + ' to ' + info))
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 write_doc(self, docname, doctree):
# type: (str, nodes.Node) -> None
def write_doc(self, docname: str, doctree: Node) -> None:
logger.info('')
n = 0
@ -298,20 +286,17 @@ class CheckExternalLinksBuilder(Builder):
if self.broken:
self.app.statuscode = 1
def write_entry(self, what, docname, line, uri):
# type: (str, str, int, str) -> None
def write_entry(self, what: str, docname: str, line: int, uri: str) -> None:
with open(path.join(self.outdir, 'output.txt'), 'a', encoding='utf-8') as output:
output.write("%s:%s: [%s] %s\n" % (self.env.doc2path(docname, None),
line, what, uri))
def finish(self):
# type: () -> None
def finish(self) -> None:
for worker in self.workers:
self.wqueue.put((None, None, None), False)
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_builder(CheckExternalLinksBuilder)
app.add_config_value('linkcheck_ignore', [], None)

View File

@ -9,12 +9,15 @@
"""
from os import path
from typing import Any, Dict, List, Set, Tuple, Union
from docutils.frontend import OptionParser
from docutils.io import FileOutput
from sphinx import addnodes
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.config import Config
from sphinx.errors import NoUri
from sphinx.locale import __
from sphinx.util import logging
@ -24,12 +27,6 @@ from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.osutil import make_filename_from_project
from sphinx.writers.manpage import ManualPageWriter, ManualPageTranslator
if False:
# For type annotation
from typing import Any, Dict, List, Set, Tuple, Union # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA
logger = logging.getLogger(__name__)
@ -45,25 +42,21 @@ class ManualPageBuilder(Builder):
default_translator_class = ManualPageTranslator
supported_image_types = [] # type: List[str]
def init(self):
# type: () -> None
def init(self) -> None:
if not self.config.man_pages:
logger.warning(__('no "man_pages" config value found; no manual pages '
'will be written'))
def get_outdated_docs(self):
# type: () -> Union[str, List[str]]
def get_outdated_docs(self) -> Union[str, List[str]]:
return 'all manpages' # for now
def get_target_uri(self, docname, typ=None):
# type: (str, str) -> str
def get_target_uri(self, docname: str, typ: str = None) -> str:
if typ == 'token':
return ''
raise NoUri
@progress_message(__('writing'))
def write(self, *ignored):
# type: (Any) -> None
def write(self, *ignored) -> None:
docwriter = ManualPageWriter(self)
docsettings = OptionParser(
defaults=self.env.settings,
@ -106,21 +99,18 @@ class ManualPageBuilder(Builder):
docwriter.write(largetree, destination)
def finish(self):
# type: () -> None
def finish(self) -> None:
pass
def default_man_pages(config):
# type: (Config) -> List[Tuple[str, str, str, List[str], int]]
def default_man_pages(config: Config) -> List[Tuple[str, str, str, List[str], int]]:
""" Better default man_pages settings. """
filename = make_filename_from_project(config.project)
return [(config.master_doc, filename, '%s %s' % (config.project, config.release),
[config.author], 1)]
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_builder(ManualPageBuilder)
app.add_config_value('man_pages', default_man_pages, None)

View File

@ -9,17 +9,14 @@
"""
import warnings
from typing import Any, Dict
from sphinxcontrib.qthelp import QtHelpBuilder, render_file
import sphinx
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.qthelp',
{
@ -29,8 +26,7 @@ deprecated_alias('sphinx.builders.qthelp',
RemovedInSphinx40Warning)
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
warnings.warn('sphinx.builders.qthelp has been moved to sphinxcontrib-qthelp.',
RemovedInSphinx40Warning)

View File

@ -9,9 +9,12 @@
"""
from os import path
from typing import Any, Dict, List, Tuple, Union
from docutils import nodes
from docutils.nodes import Node
from sphinx.application import Sphinx
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
from sphinx.environment.adapters.toctree import TocTree
@ -21,11 +24,6 @@ from sphinx.util import progress_message
from sphinx.util.console import darkgreen # type: ignore
from sphinx.util.nodes import inline_all_toctrees
if False:
# For type annotation
from typing import Any, Dict, List, Tuple, Union # NOQA
from sphinx.application import Sphinx # NOQA
logger = logging.getLogger(__name__)
@ -39,12 +37,10 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
copysource = False
def get_outdated_docs(self): # type: ignore
# type: () -> Union[str, List[str]]
def get_outdated_docs(self) -> Union[str, List[str]]: # type: ignore
return 'all documents'
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 in self.env.all_docs:
# all references are on the same page...
return self.config.master_doc + self.out_suffix + \
@ -53,13 +49,11 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
# chances are this is a html_additional_page
return docname + self.out_suffix
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:
# ignore source
return self.get_target_uri(to, typ)
def fix_refuris(self, tree):
# type: (nodes.Node) -> None
def fix_refuris(self, tree: Node) -> None:
# fix refuris with double anchor
fname = self.config.master_doc + self.out_suffix
for refnode in tree.traverse(nodes.reference):
@ -73,8 +67,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
if hashindex >= 0:
refnode['refuri'] = fname + refuri[hashindex:]
def _get_local_toctree(self, docname, collapse=True, **kwds):
# type: (str, bool, Any) -> str
def _get_local_toctree(self, docname: str, collapse: bool = True, **kwds) -> str:
if 'includehidden' not in kwds:
kwds['includehidden'] = False
toctree = TocTree(self.env).get_toctree_for(docname, self, collapse, **kwds)
@ -82,8 +75,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
self.fix_refuris(toctree)
return self.render_partial(toctree)['fragment']
def assemble_doctree(self):
# type: () -> nodes.document
def assemble_doctree(self) -> nodes.document:
master = self.config.master_doc
tree = self.env.get_doctree(master)
tree = inline_all_toctrees(self, set(), master, tree, darkgreen, [master])
@ -92,8 +84,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
self.fix_refuris(tree)
return tree
def assemble_toc_secnumbers(self):
# type: () -> Dict[str, Dict[str, Tuple[int, ...]]]
def assemble_toc_secnumbers(self) -> Dict[str, Dict[str, Tuple[int, ...]]]:
# Assemble toc_secnumbers to resolve section numbers on SingleHTML.
# Merge all secnumbers to single secnumber.
#
@ -111,8 +102,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
return {self.config.master_doc: new_secnumbers}
def assemble_toc_fignumbers(self):
# type: () -> Dict[str, Dict[str, Dict[str, Tuple[int, ...]]]]
def assemble_toc_fignumbers(self) -> Dict[str, Dict[str, Dict[str, Tuple[int, ...]]]]:
# Assemble toc_fignumbers to resolve figure numbers on SingleHTML.
# Merge all fignumbers to single fignumber.
#
@ -133,8 +123,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
return {self.config.master_doc: new_fignumbers}
def get_doc_context(self, docname, body, metatags):
# type: (str, str, str) -> Dict
def get_doc_context(self, docname: str, body: str, metatags: str) -> Dict:
# no relation links...
toctree = TocTree(self.env).get_toctree_for(self.config.master_doc, self, False)
# if there is no toctree, toc is None
@ -160,8 +149,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
'display_toc': display_toc,
}
def write(self, *ignored):
# type: (Any) -> None
def write(self, *ignored) -> None:
docnames = self.env.all_docs
with progress_message(__('preparing documents')):
@ -176,8 +164,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
self.write_doc_serialized(self.config.master_doc, doctree)
self.write_doc(self.config.master_doc, doctree)
def finish(self):
# type: () -> None
def finish(self) -> None:
self.write_additional_files()
self.copy_image_files()
self.copy_download_files()
@ -187,8 +174,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
self.dump_inventory()
@progress_message(__('writing additional files'))
def write_additional_files(self):
# type: () -> None
def write_additional_files(self) -> None:
# no indices or search pages are supported
# additional pages from conf.py
@ -210,8 +196,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(SingleFileHTMLBuilder)

View File

@ -10,6 +10,7 @@
import os
from os import path
from typing import Any, Dict, Iterable, List, Tuple, Union
from docutils import nodes
from docutils.frontend import OptionParser
@ -17,7 +18,9 @@ from docutils.io import FileOutput
from sphinx import addnodes
from sphinx import package_dir
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.config import Config
from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.errors import NoUri
from sphinx.locale import _, __
@ -30,12 +33,6 @@ from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.osutil import SEP, ensuredir, make_filename_from_project
from sphinx.writers.texinfo import TexinfoWriter, TexinfoTranslator
if False:
# For type annotation
from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA
from typing import Any, Dict, Iterable, List, Tuple, Union # NOQA
logger = logging.getLogger(__name__)
template_dir = os.path.join(package_dir, 'templates', 'texinfo')
@ -57,29 +54,24 @@ class TexinfoBuilder(Builder):
'image/gif']
default_translator_class = TexinfoTranslator
def init(self):
# type: () -> None
def init(self) -> None:
self.docnames = [] # type: Iterable[str]
self.document_data = [] # type: List[Tuple[str, str, str, str, str, str, str, bool]]
def get_outdated_docs(self):
# type: () -> Union[str, List[str]]
def get_outdated_docs(self) -> Union[str, List[str]]:
return 'all documents' # for now
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 not in self.docnames:
raise NoUri
else:
return '%' + docname
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:
# ignore source path
return self.get_target_uri(to, typ)
def init_document_data(self):
# type: () -> None
def init_document_data(self) -> None:
preliminary_document_data = [list(x) for x in self.config.texinfo_documents]
if not preliminary_document_data:
logger.warning(__('no "texinfo_documents" config value found; no documents '
@ -98,8 +90,7 @@ class TexinfoBuilder(Builder):
docname = docname[:-5]
self.titles.append((docname, entry[2]))
def write(self, *ignored):
# type: (Any) -> None
def write(self, *ignored) -> None:
self.init_document_data()
for entry in self.document_data:
docname, targetname, title, author = entry[:4]
@ -136,8 +127,7 @@ class TexinfoBuilder(Builder):
docwriter.write(doctree, destination)
self.copy_image_files(targetname[:-5])
def assemble_doctree(self, indexfile, toctree_only, appendices):
# type: (str, bool, List[str]) -> nodes.document
def assemble_doctree(self, indexfile: str, toctree_only: bool, appendices: List[str]) -> nodes.document: # NOQA
self.docnames = set([indexfile] + appendices)
logger.info(darkgreen(indexfile) + " ", nonl=True)
tree = self.env.get_doctree(indexfile)
@ -179,12 +169,10 @@ class TexinfoBuilder(Builder):
pendingnode.replace_self(newnodes)
return largetree
def finish(self):
# type: () -> None
def finish(self) -> None:
self.copy_support_files()
def copy_image_files(self, targetname):
# type: (str) -> None
def copy_image_files(self, targetname: str) -> None:
if self.images:
stringify_func = ImageAdapter(self.app.env).get_original_image_uri
for src in status_iterator(self.images, __('copying images... '), "brown",
@ -199,8 +187,7 @@ class TexinfoBuilder(Builder):
logger.warning(__('cannot copy image file %r: %s'),
path.join(self.srcdir, src), err)
def copy_support_files(self):
# type: () -> None
def copy_support_files(self) -> None:
try:
with progress_message(__('copying Texinfo support files')):
logger.info('Makefile ', nonl=True)
@ -209,16 +196,14 @@ class TexinfoBuilder(Builder):
logger.warning(__("error writing file Makefile: %s"), err)
def default_texinfo_documents(config):
# type: (Config) -> List[Tuple[str, str, str, str, str, str, str]]
def default_texinfo_documents(config: Config) -> List[Tuple[str, str, str, str, str, str, str]]: # NOQA
""" Better default texinfo_documents settings. """
filename = make_filename_from_project(config.project)
return [(config.master_doc, filename, config.project, config.author, filename,
'One line description of project', 'Miscellaneous')]
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_builder(TexinfoBuilder)
app.add_config_value('texinfo_documents', default_texinfo_documents, None)

View File

@ -9,21 +9,18 @@
"""
from os import path
from typing import Any, Dict, Iterator, Set, Tuple
from docutils.io import StringOutput
from docutils.nodes import Node
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util.osutil import ensuredir, os_path
from sphinx.writers.text import TextWriter, TextTranslator
if False:
# For type annotation
from typing import Any, Dict, Iterator, Set, Tuple # NOQA
from docutils import nodes # NOQA
from sphinx.application import Sphinx # NOQA
logger = logging.getLogger(__name__)
@ -38,13 +35,11 @@ class TextBuilder(Builder):
current_docname = None # type: str
def init(self):
# type: () -> None
def init(self) -> None:
# section numbers for headings in the currently visited document
self.secnumbers = {} # type: Dict[str, Tuple[int, ...]]
def get_outdated_docs(self):
# type: () -> Iterator[str]
def get_outdated_docs(self) -> Iterator[str]:
for docname in self.env.found_docs:
if docname not in self.env.all_docs:
yield docname
@ -62,16 +57,13 @@ class TextBuilder(Builder):
# source doesn't exist anymore
pass
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:
self.writer = TextWriter(self)
def write_doc(self, docname, doctree):
# type: (str, nodes.Node) -> None
def write_doc(self, docname: str, doctree: Node) -> None:
self.current_docname = docname
self.secnumbers = self.env.toc_secnumbers.get(docname, {})
destination = StringOutput(encoding='utf-8')
@ -84,13 +76,11 @@ class TextBuilder(Builder):
except OSError as err:
logger.warning(__("error writing file %s: %s"), outfilename, err)
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(TextBuilder)
app.add_config_value('text_sectionchars', '*=-~"+`', 'env')

View File

@ -9,23 +9,20 @@
"""
from os import path
from typing import Any, Dict, Iterator, Set, Type, Union
from docutils import nodes
from docutils.io import StringOutput
from docutils.nodes import Node
from docutils.writers.docutils_xml import XMLTranslator
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util.osutil import ensuredir, os_path
from sphinx.writers.xml import XMLWriter, PseudoXMLWriter
if False:
# For type annotation
from typing import Any, Dict, Iterator, Set, Type # NOQA
from docutils.writers.xml import BaseXMLWriter # NOQA
from sphinx.application import Sphinx # NOQA
logger = logging.getLogger(__name__)
@ -40,15 +37,13 @@ class XMLBuilder(Builder):
out_suffix = '.xml'
allow_parallel = True
_writer_class = XMLWriter # type: Type[BaseXMLWriter]
_writer_class = XMLWriter # type: Union[Type[XMLWriter], Type[PseudoXMLWriter]]
default_translator_class = XMLTranslator
def init(self):
# type: () -> None
def init(self) -> None:
pass
def get_outdated_docs(self):
# type: () -> Iterator[str]
def get_outdated_docs(self) -> Iterator[str]:
for docname in self.env.found_docs:
if docname not in self.env.all_docs:
yield docname
@ -66,16 +61,13 @@ class XMLBuilder(Builder):
# source doesn't exist anymore
pass
def get_target_uri(self, docname, typ=None):
# type: (str, str) -> str
def get_target_uri(self, docname: str, typ: str = None) -> str:
return docname
def prepare_writing(self, docnames):
# type: (Set[str]) -> None
def prepare_writing(self, docnames: Set[str]) -> None:
self.writer = self._writer_class(self)
def write_doc(self, docname, doctree):
# type: (str, nodes.Node) -> None
def write_doc(self, docname: str, doctree: Node) -> None:
# work around multiple string % tuple issues in docutils;
# replace tuples in attribute values with lists
doctree = doctree.deepcopy()
@ -98,8 +90,7 @@ class XMLBuilder(Builder):
except OSError as err:
logger.warning(__("error writing file %s: %s"), outfilename, err)
def finish(self):
# type: () -> None
def finish(self) -> None:
pass
@ -116,8 +107,7 @@ class PseudoXMLBuilder(XMLBuilder):
_writer_class = PseudoXMLWriter
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_builder(XMLBuilder)
app.add_builder(PseudoXMLBuilder)

View File

@ -310,7 +310,7 @@ you can select a language here by its language code. Sphinx will then
translate text that it generates into that language.
For a list of supported codes, see
http://sphinx-doc.org/config.html#confval-language.'''))
https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language.'''))
d['language'] = do_prompt(__('Project language'), 'en')
if d['language'] == 'en':
d['language'] = None

View File

@ -9,23 +9,24 @@
"""
import re
from typing import List, cast
from typing import Any, Dict, List, Tuple
from typing import cast
from docutils import nodes
from docutils.nodes import Node
from docutils.parsers.rst import directives, roles
from sphinx import addnodes
from sphinx.addnodes import desc_signature
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
from sphinx.util import docutils
from sphinx.util.docfields import DocFieldTransformer, TypedField
from sphinx.util.docfields import DocFieldTransformer, Field, TypedField
from sphinx.util.docutils import SphinxDirective
from sphinx.util.typing import DirectiveOption
if False:
# For type annotation
from typing import Any, Dict, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.util.docfields import Field # NOQA
from sphinx.util.typing import DirectiveOption # NOQA
from sphinx.application import Sphinx
# RE to strip backslash escapes
@ -70,8 +71,7 @@ class ObjectDescription(SphinxDirective):
# Warning: this might be removed in future version. Don't touch this from extensions.
_doc_field_type_map = {} # type: Dict[str, Tuple[Field, bool]]
def get_field_type_map(self):
# type: () -> Dict[str, Tuple[Field, bool]]
def get_field_type_map(self) -> Dict[str, Tuple[Field, bool]]:
if self._doc_field_type_map == {}:
for field in self.doc_field_types:
for name in field.names:
@ -84,8 +84,7 @@ class ObjectDescription(SphinxDirective):
return self._doc_field_type_map
def get_signatures(self):
# type: () -> List[str]
def get_signatures(self) -> List[str]:
"""
Retrieve the signatures to document from the directive arguments. By
default, signatures are given as arguments, one per line.
@ -96,8 +95,7 @@ class ObjectDescription(SphinxDirective):
# remove backslashes to support (dummy) escapes; helps Vim highlighting
return [strip_backslash_re.sub(r'\1', line.strip()) for line in lines]
def handle_signature(self, sig, signode):
# type: (str, addnodes.desc_signature) -> Any
def handle_signature(self, sig: str, signode: desc_signature) -> Any:
"""
Parse the signature *sig* into individual nodes and append them to
*signode*. If ValueError is raised, parsing is aborted and the whole
@ -109,8 +107,7 @@ class ObjectDescription(SphinxDirective):
"""
raise ValueError
def add_target_and_index(self, name, sig, signode):
# type: (Any, str, addnodes.desc_signature) -> None
def add_target_and_index(self, name: Any, sig: str, signode: desc_signature) -> None:
"""
Add cross-reference IDs and entries to self.indexnode, if applicable.
@ -118,24 +115,21 @@ class ObjectDescription(SphinxDirective):
"""
return # do nothing by default
def before_content(self):
# type: () -> None
def before_content(self) -> None:
"""
Called before parsing content. Used to set information about the current
directive context on the build environment.
"""
pass
def after_content(self):
# type: () -> None
def after_content(self) -> None:
"""
Called after parsing content. Used to reset information about the
current directive context on the build environment.
"""
pass
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
"""
Main directive entry function, called by docutils upon encountering the
directive.
@ -212,8 +206,7 @@ class DefaultRole(SphinxDirective):
optional_arguments = 1
final_argument_whitespace = False
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
if not self.arguments:
docutils.unregister_role('')
return []
@ -244,8 +237,7 @@ class DefaultDomain(SphinxDirective):
final_argument_whitespace = False
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
domain_name = self.arguments[0].lower()
# if domain_name not in env.domains:
# # try searching by label
@ -294,8 +286,7 @@ deprecated_alias('sphinx.directives',
DescDirective = ObjectDescription
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: "Sphinx") -> Dict[str, Any]:
directives.register_directive('default-role', DefaultRole)
directives.register_directive('default-domain', DefaultDomain)
directives.register_directive('describe', ObjectDescription)

View File

@ -9,12 +9,15 @@
import sys
import warnings
from difflib import unified_diff
from typing import Any, Dict, List, Tuple
from docutils import nodes
from docutils.nodes import Element, Node
from docutils.parsers.rst import directives
from docutils.statemachine import StringList
from sphinx import addnodes
from sphinx.config import Config
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.locale import __
from sphinx.util import logging
@ -23,9 +26,7 @@ from sphinx.util.docutils import SphinxDirective
if False:
# For type annotation
from typing import Any, Dict, List, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA
from sphinx.application import Sphinx
logger = logging.getLogger(__name__)
@ -45,8 +46,7 @@ class Highlight(SphinxDirective):
'linenothreshold': directives.positive_int,
}
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
language = self.arguments[0].strip()
linenothreshold = self.options.get('linenothreshold', sys.maxsize)
force = 'force' in self.options
@ -60,16 +60,14 @@ class Highlight(SphinxDirective):
class HighlightLang(Highlight):
"""highlightlang directive (deprecated)"""
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
warnings.warn('highlightlang directive is deprecated. '
'Please use highlight directive instead.',
RemovedInSphinx40Warning, stacklevel=2)
return super().run()
def dedent_lines(lines, dedent, location=None):
# type: (List[str], int, Tuple[str, int]) -> List[str]
def dedent_lines(lines: List[str], dedent: int, location: Tuple[str, int] = None) -> List[str]:
if not dedent:
return lines
@ -86,8 +84,7 @@ def dedent_lines(lines, dedent, location=None):
return new_lines
def container_wrapper(directive, literal_node, caption):
# type: (SphinxDirective, nodes.Node, str) -> nodes.container
def container_wrapper(directive: SphinxDirective, literal_node: Node, caption: str) -> nodes.container: # NOQA
container_node = nodes.container('', literal_block=True,
classes=['literal-block-wrapper'])
parsed = nodes.Element()
@ -129,8 +126,7 @@ class CodeBlock(SphinxDirective):
'name': directives.unchanged,
}
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
document = self.state.document
code = '\n'.join(self.content)
location = self.state_machine.get_source_and_line(self.lineno)
@ -157,7 +153,7 @@ class CodeBlock(SphinxDirective):
lines = dedent_lines(lines, self.options['dedent'], location=location)
code = '\n'.join(lines)
literal = nodes.literal_block(code, code) # type: nodes.Element
literal = nodes.literal_block(code, code) # type: Element
if 'linenos' in self.options or 'lineno-start' in self.options:
literal['linenos'] = True
literal['classes'] += self.options.get('class', [])
@ -209,8 +205,7 @@ class LiteralIncludeReader:
('diff', 'end-at'),
]
def __init__(self, filename, options, config):
# type: (str, Dict, Config) -> None
def __init__(self, filename: str, options: Dict, config: Config) -> None:
self.filename = filename
self.options = options
self.encoding = options.get('encoding', config.source_encoding)
@ -218,15 +213,13 @@ class LiteralIncludeReader:
self.parse_options()
def parse_options(self):
# type: () -> None
def parse_options(self) -> None:
for option1, option2 in self.INVALID_OPTIONS_PAIR:
if option1 in self.options and option2 in self.options:
raise ValueError(__('Cannot use both "%s" and "%s" options') %
(option1, option2))
def read_file(self, filename, location=None):
# type: (str, Tuple[str, int]) -> List[str]
def read_file(self, filename: str, location: Tuple[str, int] = None) -> List[str]:
try:
with open(filename, encoding=self.encoding, errors='strict') as f:
text = f.read()
@ -241,8 +234,7 @@ class LiteralIncludeReader:
'be wrong, try giving an :encoding: option') %
(self.encoding, filename))
def read(self, location=None):
# type: (Tuple[str, int]) -> Tuple[str, int]
def read(self, location: Tuple[str, int] = None) -> Tuple[str, int]:
if 'diff' in self.options:
lines = self.show_diff()
else:
@ -259,16 +251,14 @@ class LiteralIncludeReader:
return ''.join(lines), len(lines)
def show_diff(self, location=None):
# type: (Tuple[str, int]) -> List[str]
def show_diff(self, location: Tuple[str, int] = None) -> List[str]:
new_lines = self.read_file(self.filename)
old_filename = self.options.get('diff')
old_lines = self.read_file(old_filename)
diff = unified_diff(old_lines, new_lines, old_filename, self.filename)
return list(diff)
def pyobject_filter(self, lines, location=None):
# type: (List[str], Tuple[str, int]) -> List[str]
def pyobject_filter(self, lines: List[str], location: Tuple[str, int] = None) -> List[str]:
pyobject = self.options.get('pyobject')
if pyobject:
from sphinx.pycode import ModuleAnalyzer
@ -286,8 +276,7 @@ class LiteralIncludeReader:
return lines
def lines_filter(self, lines, location=None):
# type: (List[str], Tuple[str, int]) -> List[str]
def lines_filter(self, lines: List[str], location: Tuple[str, int] = None) -> List[str]:
linespec = self.options.get('lines')
if linespec:
linelist = parselinenos(linespec, len(lines))
@ -311,8 +300,7 @@ class LiteralIncludeReader:
return lines
def start_filter(self, lines, location=None):
# type: (List[str], Tuple[str, int]) -> List[str]
def start_filter(self, lines: List[str], location: Tuple[str, int] = None) -> List[str]:
if 'start-at' in self.options:
start = self.options.get('start-at')
inclusive = False
@ -343,8 +331,7 @@ class LiteralIncludeReader:
return lines
def end_filter(self, lines, location=None):
# type: (List[str], Tuple[str, int]) -> List[str]
def end_filter(self, lines: List[str], location: Tuple[str, int] = None) -> List[str]:
if 'end-at' in self.options:
end = self.options.get('end-at')
inclusive = True
@ -371,24 +358,21 @@ class LiteralIncludeReader:
return lines
def prepend_filter(self, lines, location=None):
# type: (List[str], Tuple[str, int]) -> List[str]
def prepend_filter(self, lines: List[str], location: Tuple[str, int] = None) -> List[str]:
prepend = self.options.get('prepend')
if prepend:
lines.insert(0, prepend + '\n')
return lines
def append_filter(self, lines, location=None):
# type: (List[str], Tuple[str, int]) -> List[str]
def append_filter(self, lines: List[str], location: Tuple[str, int] = None) -> List[str]:
append = self.options.get('append')
if append:
lines.append(append + '\n')
return lines
def dedent_filter(self, lines, location=None):
# type: (List[str], Tuple[str, int]) -> List[str]
def dedent_filter(self, lines: List[str], location: Tuple[str, int] = None) -> List[str]:
if 'dedent' in self.options:
return dedent_lines(lines, self.options.get('dedent'), location=location)
else:
@ -430,8 +414,7 @@ class LiteralInclude(SphinxDirective):
'diff': directives.unchanged_required,
}
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
document = self.state.document
if not document.settings.file_insertion_enabled:
return [document.reporter.warning('File insertion disabled',
@ -449,7 +432,7 @@ class LiteralInclude(SphinxDirective):
reader = LiteralIncludeReader(filename, self.options, self.config)
text, lines = reader.read(location=location)
retnode = nodes.literal_block(text, text, source=filename) # type: nodes.Element
retnode = nodes.literal_block(text, text, source=filename) # type: Element
retnode['force'] = 'force' in self.options
self.set_source_info(retnode)
if self.options.get('diff'): # if diff is set, set udiff
@ -483,8 +466,7 @@ class LiteralInclude(SphinxDirective):
return [document.reporter.warning(exc, line=self.lineno)]
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: "Sphinx") -> Dict[str, Any]:
directives.register_directive('highlight', Highlight)
directives.register_directive('highlightlang', HighlightLang)
directives.register_directive('code-block', CodeBlock)

View File

@ -7,9 +7,11 @@
"""
import re
from typing import Any, Dict, List
from typing import cast
from docutils import nodes
from docutils.nodes import Element, Node
from docutils.parsers.rst import directives
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
from docutils.parsers.rst.directives.misc import Class
@ -25,15 +27,13 @@ from sphinx.util.nodes import explicit_title_re, process_index_entry
if False:
# For type annotation
from typing import Any, Dict, List # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.application import Sphinx
glob_re = re.compile(r'.*[*?\[].*')
def int_or_nothing(argument):
# type: (str) -> int
def int_or_nothing(argument: str) -> int:
if not argument:
return 999
return int(argument)
@ -60,8 +60,7 @@ class TocTree(SphinxDirective):
'reversed': directives.flag,
}
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
subnode = addnodes.toctree()
subnode['parent'] = self.env.docname
@ -160,11 +159,10 @@ class Author(SphinxDirective):
final_argument_whitespace = True
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
if not self.config.show_authors:
return []
para = nodes.paragraph(translatable=False) # type: nodes.Element
para = nodes.paragraph(translatable=False) # type: Element
emph = nodes.emphasis()
para += emph
if self.name == 'sectionauthor':
@ -179,7 +177,7 @@ class Author(SphinxDirective):
inodes, messages = self.state.inline_text(self.arguments[0], self.lineno)
emph.extend(inodes)
ret = [para] # type: List[nodes.Node]
ret = [para] # type: List[Node]
ret += messages
return ret
@ -194,8 +192,7 @@ class Index(SphinxDirective):
final_argument_whitespace = True
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
arguments = self.arguments[0].split('\n')
targetid = 'index-%s' % self.env.new_serialno('index')
targetnode = nodes.target('', '', ids=[targetid])
@ -226,8 +223,7 @@ class TabularColumns(SphinxDirective):
final_argument_whitespace = True
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
node = addnodes.tabular_col_spec()
node['spec'] = self.arguments[0]
self.set_source_info(node)
@ -244,15 +240,14 @@ class Centered(SphinxDirective):
final_argument_whitespace = True
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
if not self.arguments:
return []
subnode = addnodes.centered() # type: nodes.Element
subnode = addnodes.centered() # type: Element
inodes, messages = self.state.inline_text(self.arguments[0], self.lineno)
subnode.extend(inodes)
ret = [subnode] # type: List[nodes.Node]
ret = [subnode] # type: List[Node]
ret += messages
return ret
@ -267,8 +262,7 @@ class Acks(SphinxDirective):
final_argument_whitespace = False
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
node = addnodes.acks()
node.document = self.state.document
self.state.nested_parse(self.content, self.content_offset, node)
@ -291,8 +285,7 @@ class HList(SphinxDirective):
'columns': int,
}
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
ncolumns = self.options.get('columns', 2)
node = nodes.paragraph()
node.document = self.state.document
@ -325,8 +318,7 @@ class Only(SphinxDirective):
final_argument_whitespace = True
option_spec = {} # type: Dict
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
node = addnodes.only()
node.document = self.state.document
self.set_source_info(node)
@ -380,8 +372,7 @@ class Include(BaseInclude, SphinxDirective):
"correctly", i.e. relative to source directory.
"""
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
if self.arguments[0].startswith('<') and \
self.arguments[0].endswith('>'):
# docutils "standard" includes, do not do path processing
@ -392,8 +383,7 @@ class Include(BaseInclude, SphinxDirective):
return super().run()
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: "Sphinx") -> Dict[str, Any]:
directives.register_directive('toctree', TocTree)
directives.register_directive('sectionauthor', Author)
directives.register_directive('moduleauthor', Author)

View File

@ -6,10 +6,11 @@
:license: BSD, see LICENSE for details.
"""
from typing import Any, Dict, List, Tuple
from typing import cast
from docutils import nodes
from docutils.nodes import make_id
from docutils.nodes import Node, make_id, system_message
from docutils.parsers.rst import directives
from docutils.parsers.rst.directives import images, html, tables
@ -20,8 +21,7 @@ from sphinx.util.nodes import set_source_info
if False:
# For type annotation
from typing import Dict, List, Tuple # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.application import Sphinx
class Figure(images.Figure):
@ -29,8 +29,7 @@ class Figure(images.Figure):
instead of the image node.
"""
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
name = self.options.pop('name', None)
result = super().run()
if len(result) == 2 or isinstance(result[0], nodes.system_message):
@ -52,8 +51,7 @@ class Figure(images.Figure):
class Meta(html.Meta, SphinxDirective):
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
result = super().run()
for node in result:
if (isinstance(node, nodes.pending) and
@ -74,8 +72,7 @@ class RSTTable(tables.RSTTable):
Only for docutils-0.13 or older version."""
def make_title(self):
# type: () -> Tuple[nodes.title, List[nodes.system_message]]
def make_title(self) -> Tuple[nodes.title, List[system_message]]:
title, message = super().make_title()
if title:
set_source_info(self, title)
@ -88,8 +85,7 @@ class CSVTable(tables.CSVTable):
Only for docutils-0.13 or older version."""
def make_title(self):
# type: () -> Tuple[nodes.title, List[nodes.system_message]]
def make_title(self) -> Tuple[nodes.title, List[system_message]]:
title, message = super().make_title()
if title:
set_source_info(self, title)
@ -102,8 +98,7 @@ class ListTable(tables.ListTable):
Only for docutils-0.13 or older version."""
def make_title(self):
# type: () -> Tuple[nodes.title, List[nodes.system_message]]
def make_title(self) -> Tuple[nodes.title, List[system_message]]:
title, message = super().make_title()
if title:
set_source_info(self, title)
@ -125,8 +120,7 @@ class Code(SphinxDirective):
}
has_content = True
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
self.assert_has_content()
code = '\n'.join(self.content)
@ -169,8 +163,7 @@ class MathDirective(SphinxDirective):
'nowrap': directives.flag,
}
def run(self):
# type: () -> List[nodes.Node]
def run(self) -> List[Node]:
latex = '\n'.join(self.content)
if self.arguments and self.arguments[0]:
latex = self.arguments[0] + '\n\n' + latex
@ -184,12 +177,11 @@ class MathDirective(SphinxDirective):
self.add_name(node)
self.set_source_info(node)
ret = [node] # type: List[nodes.Node]
ret = [node] # type: List[Node]
self.add_target(ret)
return ret
def add_target(self, ret):
# type: (List[nodes.Node]) -> None
def add_target(self, ret: List[Node]) -> None:
node = cast(nodes.math_block, ret[0])
# assign label automatically if math_number_all enabled
@ -216,8 +208,7 @@ class MathDirective(SphinxDirective):
self.state_machine.reporter.warning(exc, line=self.lineno)
def setup(app):
# type: (Sphinx) -> Dict
def setup(app: "Sphinx") -> Dict[str, Any]:
directives.register_directive('figure', Figure)
directives.register_directive('meta', Meta)
directives.register_directive('table', RSTTable)

View File

@ -337,7 +337,8 @@ class PyObject(ObjectDescription):
self.state.document.note_explicit_target(signode)
domain = cast(PythonDomain, self.env.get_domain('py'))
domain.note_object(fullname, self.objtype)
domain.note_object(fullname, self.objtype,
location=(self.env.docname, self.lineno))
indextext = self.get_index_text(modname, name_cls)
if indextext:
@ -752,7 +753,7 @@ class PyModule(SphinxDirective):
self.options.get('synopsis', ''),
self.options.get('platform', ''),
'deprecated' in self.options)
domain.note_object(modname, 'module')
domain.note_object(modname, 'module', location=(self.env.docname, self.lineno))
targetnode = nodes.target('', '', ids=['module-' + modname],
ismod=True)

View File

@ -137,7 +137,7 @@ class DownloadFileCollector(EnvironmentCollector):
logger.warning(__('download file not readable: %s') % filename,
location=node, type='download', subtype='not_readable')
continue
node['filename'] = app.env.dlfiles.add_file(app.env.docname, filename)
node['filename'] = app.env.dlfiles.add_file(app.env.docname, rel_filename)
def setup(app):

View File

@ -549,10 +549,8 @@ class Documenter:
if self.analyzer:
attr_docs = self.analyzer.find_attr_docs()
tagorder = self.analyzer.tagorder
else:
attr_docs = {}
tagorder = {}
# process members and determine which to skip
for (membername, member) in members:
@ -582,13 +580,12 @@ class Documenter:
membername in self.options.special_members:
keep = has_doc or self.options.undoc_members
elif (namespace, membername) in attr_docs:
has_doc = bool(attr_docs[namespace, membername])
if want_all and membername.startswith('_'):
# ignore members whose name starts with _ by default
keep = has_doc and self.options.private_members
keep = self.options.private_members
else:
# keep documented attributes
keep = has_doc
keep = True
isattr = True
elif want_all and membername.startswith('_'):
# ignore members whose name starts with _ by default
@ -597,8 +594,6 @@ class Documenter:
else:
# ignore undocumented members if :undoc-members: is not given
keep = has_doc or self.options.undoc_members
# module top level item or not
isattr = membername in tagorder
# give the user a chance to decide whether this member
# should be skipped
@ -1296,10 +1291,6 @@ class DataDocumenter(ModuleLevelDocumenter):
return self.get_attr(self.parent or self.object, '__module__', None) \
or self.modname
def get_doc(self, encoding=None, ignore=1):
# type: (str, int) -> List[List[str]]
return []
class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type: ignore
"""

View File

@ -128,7 +128,7 @@ def get_object_members(subject, objpath, attrgetter, analyzer=None):
members[name] = Attribute(name, True, value)
# members in __slots__
if isclass(subject) and hasattr(subject, '__slots__'):
if isclass(subject) and getattr(subject, '__slots__', None) is not None:
from sphinx.ext.autodoc import SLOTSATTR
for name in subject.__slots__:

View File

@ -754,7 +754,6 @@ def process_generate_options(app):
imported_members = app.config.autosummary_imported_members
with mock(app.config.autosummary_mock_imports):
generate_autosummary_docs(genfiles, builder=app.builder,
warn=logger.warning, info=logger.info,
suffix=suffix, base_path=app.srcdir,
app=app, imported_members=imported_members)

View File

@ -23,6 +23,7 @@ import os
import pydoc
import re
import sys
import warnings
from jinja2 import BaseLoader, FileSystemLoader, TemplateNotFound
from jinja2.sandbox import SandboxedEnvironment
@ -30,10 +31,12 @@ from jinja2.sandbox import SandboxedEnvironment
import sphinx.locale
from sphinx import __display_version__
from sphinx import package_dir
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.ext.autosummary import import_by_name, get_documenter
from sphinx.jinja2glue import BuiltinTemplateLoader
from sphinx.locale import __
from sphinx.registry import SphinxComponentRegistry
from sphinx.util import logging
from sphinx.util import rst
from sphinx.util.inspect import safe_getattr
from sphinx.util.osutil import ensuredir
@ -45,12 +48,17 @@ if False:
from sphinx.ext.autodoc import Documenter # NOQA
logger = logging.getLogger(__name__)
class DummyApplication:
"""Dummy Application class for sphinx-autogen command."""
def __init__(self):
# type: () -> None
self.registry = SphinxComponentRegistry()
self.messagelog = [] # type: List[str]
self.verbosity = 0
def setup_documenters(app):
@ -127,10 +135,20 @@ class AutosummaryRenderer:
# -- Generating output ---------------------------------------------------------
def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
warn=_simple_warn, info=_simple_info,
base_path=None, builder=None, template_dir=None,
imported_members=False, app=None):
warn=None, info=None, base_path=None, builder=None,
template_dir=None, imported_members=False, app=None):
# type: (List[str], str, str, Callable, Callable, str, Builder, str, bool, Any) -> None
if info:
warnings.warn('info argument for generate_autosummary_docs() is deprecated.',
RemovedInSphinx40Warning)
else:
info = logger.info
if warn:
warnings.warn('warn argument for generate_autosummary_docs() is deprecated.',
RemovedInSphinx40Warning)
else:
warn = logger.warning
showed_sources = list(sorted(sources))
if len(showed_sources) > 20:
@ -221,7 +239,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
get_members(obj, {'attribute', 'property'})
parts = name.split('.')
if doc.objtype in ('method', 'attribute'):
if doc.objtype in ('method', 'attribute', 'property'):
mod_name = '.'.join(parts[:-2])
cls_name = parts[-2]
obj_name = '.'.join(parts[-2:])
@ -420,6 +438,7 @@ def main(argv=sys.argv[1:]):
sphinx.locale.init_console(os.path.join(package_dir, 'locale'), 'sphinx')
app = DummyApplication()
logging.setup(app, sys.stdout, sys.stderr) # type: ignore
setup_documenters(app)
args = get_parser().parse_args(argv)
generate_autosummary_docs(args.source_file, args.output_dir,

View File

@ -328,6 +328,9 @@ class GoogleDocstring:
def _escape_args_and_kwargs(self, name):
# type: (str) -> str
if name.endswith('_'):
name = name[:-1] + r'\_'
if name[:2] == '**':
return r'\*\*' + name[2:]
elif name[:1] == '*':
@ -555,7 +558,7 @@ class GoogleDocstring:
# type: () -> None
self._parsed_lines = self._consume_empty()
if self._name and (self._what == 'attribute' or self._what == 'data'):
if self._name and self._what in ('attribute', 'data', 'property'):
# Implicit stop using StopIteration no longer allowed in
# Python 3.7; see PEP 479
res = [] # type: List[str]

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1448,8 +1448,8 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
msgstr "\nWe xetz'ib'an ri wuj pa jun ch'abäl man Q'anch' ta,\nyatikïr nacha' jun chïk runuk'unem ch'ab'äl wawe' chi Sphinx tiq'ax\nruch'abäl ri wuj xtik'iyij pa ri ch'ab'äl re.\n\nChi natz'u rucholajem runuk'unem ch'ab'äl k'o chïk pa Sphinx, tab'e pa\nhttp://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr "\nWe xetz'ib'an ri wuj pa jun ch'abäl man Q'anch' ta,\nyatikïr nacha' jun chïk runuk'unem ch'ab'äl wawe' chi Sphinx tiq'ax\nruch'abäl ri wuj xtik'iyij pa ri ch'ab'äl re.\n\nChi natz'u rucholajem runuk'unem ch'ab'äl k'o chïk pa Sphinx, tab'e pa\nhttps://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
#: sphinx/cmd/quickstart.py:314
msgid "Project language"

View File

@ -1449,7 +1449,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1449,7 +1449,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1450,7 +1450,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1451,7 +1451,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1454,8 +1454,8 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
msgstr "\nSi los documentos están escritos en un idioma distinto al Inglés,\npuedes seleccionar un idioma aqui a través de su código. Sphinx traducirá\nlos textos que genere en dicho idioma.\n\nPara una lista de los códigos soportados visita: \nhttp://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr "\nSi los documentos están escritos en un idioma distinto al Inglés,\npuedes seleccionar un idioma aqui a través de su código. Sphinx traducirá\nlos textos que genere en dicho idioma.\n\nPara una lista de los códigos soportados visita: \nhttps://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
#: sphinx/cmd/quickstart.py:314
msgid "Project language"

View File

@ -1451,8 +1451,8 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
msgstr "\nKui su dokumendid pole kirjutatud inglise keeles, siis võid siin määrata\nkeele vastava keelekoodi abil. Sel juhul tõlgib Sphinx enda genereeritud\nteksti vastavasse keelde.\n\nToetatud keelekoodide kohta vaata\nhttp://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr "\nKui su dokumendid pole kirjutatud inglise keeles, siis võid siin määrata\nkeele vastava keelekoodi abil. Sel juhul tõlgib Sphinx enda genereeritud\nteksti vastavasse keelde.\n\nToetatud keelekoodide kohta vaata\nhttps://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
#: sphinx/cmd/quickstart.py:314
msgid "Project language"

View File

@ -1449,7 +1449,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1447,7 +1447,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1465,8 +1465,8 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
msgstr "\nSi le documents doit être écrit dans une autre langue que l'anglais, vous pouvez choisir une langue ici en saisissant son code. Sphinx traduira le texte qu'il génère dans cette langue. Pour une liste des codes supportés : http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr "\nSi le documents doit être écrit dans une autre langue que l'anglais, vous pouvez choisir une langue ici en saisissant son code. Sphinx traduira le texte qu'il génère dans cette langue. Pour une liste des codes supportés : https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
#: sphinx/cmd/quickstart.py:314
msgid "Project language"

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1449,8 +1449,8 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
msgstr "\nयदि प्रलेखों को अंग्रेजी के अलावा अन्य किसी भाषा में लिखा जाना है,\nतो यहाँ पर आप भाषा का कूटशब्द दे सकते हैं. स्फिंक्स तदपुरांत,\nजो वाक्यांश बनाता है उसे उस भाषा में अनुवादित करेगा.\n\nमान्य भाषा कूटशब्द सूची यहाँ पर देखें\nhttp://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr "\nयदि प्रलेखों को अंग्रेजी के अलावा अन्य किसी भाषा में लिखा जाना है,\nतो यहाँ पर आप भाषा का कूटशब्द दे सकते हैं. स्फिंक्स तदपुरांत,\nजो वाक्यांश बनाता है उसे उस भाषा में अनुवादित करेगा.\n\nमान्य भाषा कूटशब्द सूची यहाँ पर देखें\nhttps://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
#: sphinx/cmd/quickstart.py:314
msgid "Project language"

View File

@ -1447,7 +1447,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1452,7 +1452,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1451,7 +1451,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1452,7 +1452,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1460,8 +1460,8 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
msgstr "\nドキュメントを英語以外の言語で書く場合は、\n 言語コードで言語を選択できます。Sphinx は生成したテキストをその言語に翻訳します。\n\nサポートされているコードのリストについては、\nhttp://sphinx-doc.org/config.html#confval-language を参照してください。"
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr "\nドキュメントを英語以外の言語で書く場合は、\n 言語コードで言語を選択できます。Sphinx は生成したテキストをその言語に翻訳します。\n\nサポートされているコードのリストについては、\nhttps://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language を参照してください。"
#: sphinx/cmd/quickstart.py:314
msgid "Project language"

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1447,7 +1447,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1447,7 +1447,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1449,7 +1449,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1453,7 +1453,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1451,8 +1451,8 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
msgstr "\nJeśli dokumenty mają być pisane w języku innym niż angielski,\nmożesz tutaj wybrać język przez jego kod. Sphinx następnie\nprzetłumaczy tekst, który generuje, na ten język.\n\nListę wspieranych kodów znajdziesz na\nhttp://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr "\nJeśli dokumenty mają być pisane w języku innym niż angielski,\nmożesz tutaj wybrać język przez jego kod. Sphinx następnie\nprzetłumaczy tekst, który generuje, na ten język.\n\nListę wspieranych kodów znajdziesz na\nhttps://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
#: sphinx/cmd/quickstart.py:314
msgid "Project language"

View File

@ -1447,7 +1447,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1451,7 +1451,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1449,7 +1449,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1449,7 +1449,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1453,7 +1453,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1450,7 +1450,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1447,7 +1447,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1461,7 +1461,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1447,7 +1447,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1447,7 +1447,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1447,7 +1447,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1449,7 +1449,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1447,7 +1447,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1448,7 +1448,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -1456,8 +1456,8 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
msgstr "\n如果用英语以外的语言编写文档你可以在此按语言代码选择语种。\nSphinx 会把内置文本翻译成相应语言的版本。\n\n支持的语言代码列表见\nhttp://sphinx-doc.org/config.html#confval-language。"
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr "\n如果用英语以外的语言编写文档你可以在此按语言代码选择语种。\nSphinx 会把内置文本翻译成相应语言的版本。\n\n支持的语言代码列表见\nhttps://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language。"
#: sphinx/cmd/quickstart.py:314
msgid "Project language"

View File

@ -1453,7 +1453,7 @@ msgid ""
"translate text that it generates into that language.\n"
"\n"
"For a list of supported codes, see\n"
"http://sphinx-doc.org/config.html#confval-language."
"https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-language."
msgstr ""
#: sphinx/cmd/quickstart.py:314

View File

@ -357,6 +357,17 @@ class VariableCommentPicker(ast.NodeVisitor):
except TypeError:
pass # this assignment is not new definition!
def visit_Try(self, node):
# type: (ast.Try) -> None
"""Handles Try node and processes body and else-clause.
.. note:: pycode parser ignores objects definition in except-clause.
"""
for subnode in node.body:
self.visit(subnode)
for subnode in node.orelse:
self.visit(subnode)
def visit_ClassDef(self, node):
# type: (ast.ClassDef) -> None
"""Handles ClassDef node and set context."""

View File

@ -40,8 +40,8 @@ Submodules
{{- [submodule, "module"] | join(" ") | e | heading(2) }}
{% endif %}
{{ automodule(submodule, automodule_options) }}
{%- endfor %}
{% endif %}
{% endfor %}
{%- endif %}
{% endif %}
{%- if not modulefirst and not is_namespace %}

View File

@ -6,7 +6,7 @@
%
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\ProvidesPackage{sphinx}[2019/01/12 v1.8.4 LaTeX package (Sphinx markup)]
\ProvidesPackage{sphinx}[2019/06/04 v2.1.1 LaTeX package (Sphinx markup)]
% provides \ltx@ifundefined
% (many packages load ltxcmds: graphicx does for pdftex and lualatex but
@ -1444,7 +1444,7 @@
% Some are quite plain
% the spx@notice@bordercolor etc are set in the sphinxadmonition environment
\newenvironment{sphinxlightbox}{%
\par\allowbreak
\par
\noindent{\color{spx@notice@bordercolor}%
\rule{\linewidth}{\spx@notice@border}}\par\nobreak
{\parskip\z@skip\noindent}%

View File

@ -13,6 +13,11 @@
/* -- page layout ----------------------------------------------------------- */
html {
/* CSS hack for macOS's scrollbar (see #1125) */
background-color: #FFFFFF;
}
body {
font-family: {{ theme_bodyfont }};
font-size: 100%;

View File

@ -337,15 +337,13 @@ _coding_re = re.compile(r'coding[:=]\s*([-\w.]+)')
def detect_encoding(readline: Callable[[], bytes]) -> str:
"""Like tokenize.detect_encoding() from Py3k, but a bit simplified."""
def read_or_stop():
# type: () -> bytes
def read_or_stop() -> bytes:
try:
return readline()
except StopIteration:
return None
def get_normal_name(orig_enc):
# type: (str) -> str
def get_normal_name(orig_enc: str) -> str:
"""Imitates get_normal_name in tokenizer.c."""
# Only care about the first 12 characters.
enc = orig_enc[:12].lower().replace('_', '-')
@ -356,8 +354,7 @@ def detect_encoding(readline: Callable[[], bytes]) -> str:
return 'iso-8859-1'
return orig_enc
def find_cookie(line):
# type: (bytes) -> str
def find_cookie(line: bytes) -> str:
try:
line_string = line.decode('ascii')
except UnicodeDecodeError:

View File

@ -10,23 +10,22 @@
import sys
import warnings
from typing import Any, Dict
from docutils.utils import get_source_line
from sphinx import addnodes
from sphinx.config import Config
from sphinx.deprecation import RemovedInSphinx30Warning, RemovedInSphinx40Warning
from sphinx.transforms import SphinxTransform
from sphinx.util import import_object
if False:
# For type annotation
from typing import Any, Dict # NOQA
from sphinx.application import Sphinx # NOQA
from sphinx.config import Config # NOQA
from sphinx.application import Sphinx
def deprecate_source_parsers(app, config):
# type: (Sphinx, Config) -> None
def deprecate_source_parsers(app: "Sphinx", config: Config) -> None:
if config.source_parsers:
warnings.warn('The config variable "source_parsers" is deprecated. '
'Please update your extension for the parser and remove the setting.',
@ -37,8 +36,7 @@ def deprecate_source_parsers(app, config):
app.add_source_parser(suffix, parser)
def register_application_for_autosummary(app):
# type: (Sphinx) -> None
def register_application_for_autosummary(app: "Sphinx") -> None:
"""Register application object to autosummary module.
Since Sphinx-1.7, documenters and attrgetters are registered into
@ -55,8 +53,7 @@ class IndexEntriesMigrator(SphinxTransform):
"""Migrating indexentries from old style (4columns) to new style (5columns)."""
default_priority = 700
def apply(self, **kwargs):
# type: (Any) -> None
def apply(self, **kwargs) -> None:
for node in self.document.traverse(addnodes.index):
for i, entries in enumerate(node['entries']):
if len(entries) == 4:
@ -66,8 +63,7 @@ class IndexEntriesMigrator(SphinxTransform):
node['entries'][i] = entries + (None,)
def setup(app):
# type: (Sphinx) -> Dict[str, Any]
def setup(app: "Sphinx") -> Dict[str, Any]:
app.add_transform(IndexEntriesMigrator)
app.connect('config-inited', deprecate_source_parsers)
app.connect('builder-inited', register_application_for_autosummary)

View File

@ -11,6 +11,7 @@
import os
import re
import sys
from typing import Dict
try:
# check if colorama is installed to support color on Windows
@ -18,23 +19,17 @@ try:
except ImportError:
colorama = None
if False:
# For type annotation
from typing import Dict # NOQA
_ansi_re = re.compile('\x1b\\[(\\d\\d;){0,2}\\d\\dm')
codes = {} # type: Dict[str, str]
def terminal_safe(s):
# type: (str) -> str
def terminal_safe(s: str) -> str:
"""safely encode a string for printing to the terminal."""
return s.encode('ascii', 'backslashreplace').decode('ascii')
def get_terminal_width():
# type: () -> int
def get_terminal_width() -> int:
"""Borrowed from the py lib."""
try:
import termios
@ -53,8 +48,7 @@ def get_terminal_width():
_tw = get_terminal_width()
def term_width_line(text):
# type: (str) -> str
def term_width_line(text: str) -> str:
if not codes:
# if no coloring, don't output fancy backspaces
return text + '\n'
@ -63,8 +57,7 @@ def term_width_line(text):
return text.ljust(_tw + len(text) - len(_ansi_re.sub('', text))) + '\r'
def color_terminal():
# type: () -> bool
def color_terminal() -> bool:
if sys.platform == 'win32' and colorama is not None:
colorama.init()
return True
@ -80,21 +73,18 @@ def color_terminal():
return False
def nocolor():
# type: () -> None
def nocolor() -> None:
if sys.platform == 'win32' and colorama is not None:
colorama.deinit()
codes.clear()
def coloron():
# type: () -> None
def coloron() -> None:
codes.update(_orig_codes)
def colorize(name, text, input_mode=False):
# type: (str, str, bool) -> str
def escseq(name):
def colorize(name: str, text: str, input_mode: bool = False) -> str:
def escseq(name: str) -> str:
# Wrap escape sequence with ``\1`` and ``\2`` to let readline know
# it is non-printable characters
# ref: https://tiswww.case.edu/php/chet/readline/readline.html
@ -109,15 +99,12 @@ def colorize(name, text, input_mode=False):
return escseq(name) + text + escseq('reset')
def strip_colors(s):
# type: (str) -> str
def strip_colors(s: str) -> str:
return re.compile('\x1b.*?m').sub('', s)
def create_color_func(name):
# type: (str) -> None
def inner(text):
# type: (str) -> str
def create_color_func(name: str) -> None:
def inner(text: str) -> str:
return colorize(name, text)
globals()[name] = inner

View File

@ -10,23 +10,23 @@
"""
import warnings
from typing import List, Tuple, cast
from typing import Any, Dict, List, Tuple, Type, Union
from typing import cast
from docutils import nodes
from docutils.nodes import Node
from sphinx import addnodes
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.util.typing import TextlikeNode
if False:
# For type annotation
from typing import Any, Dict, Type, Union # NOQA
from sphinx.directive import ObjectDescription # NOQA
from sphinx.environment import BuildEnvironment # NOQA
from sphinx.util.typing import TextlikeNode # NOQA
from sphinx.environment import BuildEnvironment
from sphinx.directive import ObjectDescription
def _is_single_paragraph(node):
# type: (nodes.field_body) -> bool
def _is_single_paragraph(node: nodes.field_body) -> bool:
"""True if the node only contains one paragraph (and system messages)."""
if len(node) == 0:
return False
@ -55,9 +55,8 @@ class Field:
is_grouped = False
is_typed = False
def __init__(self, name, names=(), label=None, has_arg=True, rolename=None,
bodyrolename=None):
# type: (str, Tuple[str, ...], str, bool, str, str) -> None
def __init__(self, name: str, names: Tuple[str, ...] = (), label: str = None,
has_arg: bool = True, rolename: str = None, bodyrolename: str = None) -> None:
self.name = name
self.names = names
self.label = label
@ -65,15 +64,9 @@ class Field:
self.rolename = rolename
self.bodyrolename = bodyrolename
def make_xref(self,
rolename, # type: str
domain, # type: str
target, # type: str
innernode=addnodes.literal_emphasis, # type: Type[TextlikeNode]
contnode=None, # type: nodes.Node
env=None, # type: BuildEnvironment
):
# type: (...) -> nodes.Node
def make_xref(self, rolename: str, domain: str, target: str,
innernode: Type[TextlikeNode] = addnodes.literal_emphasis,
contnode: Node = None, env: "BuildEnvironment" = None) -> Node:
if not rolename:
return contnode or innernode(target, target)
refnode = addnodes.pending_xref('', refdomain=domain, refexplicit=False,
@ -83,28 +76,16 @@ class Field:
env.get_domain(domain).process_field_xref(refnode)
return refnode
def make_xrefs(self,
rolename, # type: str
domain, # type: str
target, # type: str
innernode=addnodes.literal_emphasis, # type: Type[TextlikeNode]
contnode=None, # type: nodes.Node
env=None, # type: BuildEnvironment
):
# type: (...) -> List[nodes.Node]
def make_xrefs(self, rolename: str, domain: str, target: str,
innernode: Type[TextlikeNode] = addnodes.literal_emphasis,
contnode: Node = None, env: "BuildEnvironment" = None) -> List[Node]:
return [self.make_xref(rolename, domain, target, innernode, contnode, env)]
def make_entry(self, fieldarg, content):
# type: (str, List[nodes.Node]) -> Tuple[str, List[nodes.Node]]
def make_entry(self, fieldarg: str, content: List[Node]) -> Tuple[str, List[Node]]:
return (fieldarg, content)
def make_field(self,
types, # type: Dict[str, List[nodes.Node]]
domain, # type: str
item, # type: Tuple
env=None, # type: BuildEnvironment
):
# type: (...) -> nodes.field
def make_field(self, types: Dict[str, List[Node]], domain: str,
item: Tuple, env: "BuildEnvironment" = None) -> nodes.field:
fieldarg, content = item
fieldname = nodes.field_name('', self.label)
if fieldarg:
@ -138,19 +119,13 @@ class GroupedField(Field):
is_grouped = True
list_type = nodes.bullet_list
def __init__(self, name, names=(), label=None, rolename=None,
can_collapse=False):
# type: (str, Tuple[str, ...], str, str, bool) -> None
def __init__(self, name: str, names: Tuple[str, ...] = (), label: str = None,
rolename: str = None, can_collapse: bool = False) -> None:
super().__init__(name, names, label, True, rolename)
self.can_collapse = can_collapse
def make_field(self,
types, # type: Dict[str, List[nodes.Node]]
domain, # type: str
items, # type: Tuple
env=None, # type: BuildEnvironment
):
# type: (...) -> nodes.field
def make_field(self, types: Dict[str, List[Node]], domain: str,
items: Tuple, env: "BuildEnvironment" = None) -> nodes.field:
fieldname = nodes.field_name('', self.label)
listnode = self.list_type()
for fieldarg, content in items:
@ -191,22 +166,16 @@ class TypedField(GroupedField):
"""
is_typed = True
def __init__(self, name, names=(), typenames=(), label=None,
rolename=None, typerolename=None, can_collapse=False):
# type: (str, Tuple[str, ...], Tuple[str, ...], str, str, str, bool) -> None
def __init__(self, name: str, names: Tuple[str, ...] = (), typenames: Tuple[str, ...] = (),
label: str = None, rolename: str = None, typerolename: str = None,
can_collapse: bool = False) -> None:
super().__init__(name, names, label, rolename, can_collapse)
self.typenames = typenames
self.typerolename = typerolename
def make_field(self,
types, # type: Dict[str, List[nodes.Node]]
domain, # type: str
items, # type: Tuple
env=None, # type: BuildEnvironment
):
# type: (...) -> nodes.field
def handle_item(fieldarg, content):
# type: (str, str) -> nodes.paragraph
def make_field(self, types: Dict[str, List[Node]], domain: str,
items: Tuple, env: "BuildEnvironment" = None) -> nodes.field:
def handle_item(fieldarg: str, content: str) -> nodes.paragraph:
par = nodes.paragraph()
par.extend(self.make_xrefs(self.rolename, domain, fieldarg,
addnodes.literal_strong, env=env))
@ -246,13 +215,11 @@ class DocFieldTransformer:
"""
typemap = None # type: Dict[str, Tuple[Field, bool]]
def __init__(self, directive):
# type: (ObjectDescription) -> None
def __init__(self, directive: "ObjectDescription") -> None:
self.directive = directive
self.typemap = directive.get_field_type_map()
def preprocess_fieldtypes(self, types):
# type: (List[Field]) -> Dict[str, Tuple[Field, bool]]
def preprocess_fieldtypes(self, types: List[Field]) -> Dict[str, Tuple[Field, bool]]:
warnings.warn('DocFieldTransformer.preprocess_fieldtypes() is deprecated.',
RemovedInSphinx40Warning)
typemap = {}
@ -265,16 +232,14 @@ class DocFieldTransformer:
typemap[name] = typed_field, True
return typemap
def transform_all(self, node):
# type: (addnodes.desc_content) -> None
def transform_all(self, node: addnodes.desc_content) -> None:
"""Transform all field list children of a node."""
# don't traverse, only handle field lists that are immediate children
for child in node:
if isinstance(child, nodes.field_list):
self.transform(child)
def transform(self, node):
# type: (nodes.field_list) -> None
def transform(self, node: nodes.field_list) -> None:
"""Transform a single field list *node*."""
typemap = self.typemap

View File

@ -16,33 +16,33 @@ from contextlib import contextmanager
from copy import copy
from distutils.version import LooseVersion
from os import path
from typing import IO, cast
from types import ModuleType
from typing import Any, Callable, Dict, Generator, IO, List, Optional, Set, Tuple, Type
from typing import cast
import docutils
from docutils import nodes
from docutils.io import FileOutput
from docutils.nodes import Element, Node, system_message
from docutils.parsers.rst import Directive, directives, roles, convert_directive_function
from docutils.statemachine import StateMachine
from docutils.parsers.rst.states import Inliner
from docutils.statemachine import StateMachine, State, StringList
from docutils.utils import Reporter, unescape
from sphinx.deprecation import RemovedInSphinx30Warning
from sphinx.errors import ExtensionError, SphinxError
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util.typing import RoleFunction
logger = logging.getLogger(__name__)
report_re = re.compile('^(.+?:(?:\\d+)?): \\((DEBUG|INFO|WARNING|ERROR|SEVERE)/(\\d+)?\\) ')
if False:
# For type annotation
from types import ModuleType # NOQA
from typing import Any, Callable, Dict, Generator, List, Set, Tuple, Type # NOQA
from docutils.parsers.rst.states import Inliner # NOQA
from docutils.statemachine import State, StringList # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.config import Config # NOQA
from sphinx.environment import BuildEnvironment # NOQA
from sphinx.util.typing import RoleFunction # NOQA
from sphinx.builders import Builder
from sphinx.config import Config
from sphinx.environment import BuildEnvironment
__version_info__ = tuple(LooseVersion(docutils.__version__).version)
@ -50,8 +50,7 @@ additional_nodes = set() # type: Set[Type[nodes.Element]]
@contextmanager
def docutils_namespace():
# type: () -> Generator[None, None, None]
def docutils_namespace() -> Generator[None, None, None]:
"""Create namespace for reST parsers."""
try:
_directives = copy(directives._directives) # type: ignore
@ -67,14 +66,12 @@ def docutils_namespace():
additional_nodes.discard(node)
def is_directive_registered(name):
# type: (str) -> bool
def is_directive_registered(name: str) -> bool:
"""Check the *name* directive is already registered."""
return name in directives._directives # type: ignore
def register_directive(name, directive):
# type: (str, Type[Directive]) -> None
def register_directive(name: str, directive: Type[Directive]) -> None:
"""Register a directive to docutils.
This modifies global state of docutils. So it is better to use this
@ -83,14 +80,12 @@ def register_directive(name, directive):
directives.register_directive(name, directive)
def is_role_registered(name):
# type: (str) -> bool
def is_role_registered(name: str) -> bool:
"""Check the *name* role is already registered."""
return name in roles._roles # type: ignore
def register_role(name, role):
# type: (str, RoleFunction) -> None
def register_role(name: str, role: RoleFunction) -> None:
"""Register a role to docutils.
This modifies global state of docutils. So it is better to use this
@ -99,20 +94,17 @@ def register_role(name, role):
roles.register_local_role(name, role)
def unregister_role(name):
# type: (str) -> None
def unregister_role(name: str) -> None:
"""Unregister a role from docutils."""
roles._roles.pop(name, None) # type: ignore
def is_node_registered(node):
# type: (Type[nodes.Element]) -> bool
def is_node_registered(node: Type[Element]) -> bool:
"""Check the *node* is already registered."""
return hasattr(nodes.GenericNodeVisitor, 'visit_' + node.__name__)
def register_node(node):
# type: (Type[nodes.Element]) -> None
def register_node(node: Type[Element]) -> None:
"""Register a node to docutils.
This modifies global state of some visitors. So it is better to use this
@ -123,8 +115,7 @@ def register_node(node):
additional_nodes.add(node)
def unregister_node(node):
# type: (Type[nodes.Element]) -> None
def unregister_node(node: Type[Element]) -> None:
"""Unregister a node from docutils.
This is inverse of ``nodes._add_nodes_class_names()``.
@ -137,8 +128,7 @@ def unregister_node(node):
@contextmanager
def patched_get_language():
# type: () -> Generator[None, None, None]
def patched_get_language() -> Generator[None, None, None]:
"""Patch docutils.languages.get_language() temporarily.
This ignores the second argument ``reporter`` to suppress warnings.
@ -146,8 +136,7 @@ def patched_get_language():
"""
from docutils.languages import get_language
def patched_get_language(language_code, reporter=None):
# type: (str, Reporter) -> Any
def patched_get_language(language_code: str, reporter: Reporter = None) -> Any:
return get_language(language_code)
try:
@ -159,8 +148,7 @@ def patched_get_language():
@contextmanager
def using_user_docutils_conf(confdir):
# type: (str) -> Generator[None, None, None]
def using_user_docutils_conf(confdir: str) -> Generator[None, None, None]:
"""Let docutils know the location of ``docutils.conf`` for Sphinx."""
try:
docutilsconfig = os.environ.get('DOCUTILSCONFIG', None)
@ -176,8 +164,7 @@ def using_user_docutils_conf(confdir):
@contextmanager
def patch_docutils(confdir=None):
# type: (str) -> Generator[None, None, None]
def patch_docutils(confdir: str = None) -> Generator[None, None, None]:
"""Patch to docutils temporarily."""
with patched_get_language(), using_user_docutils_conf(confdir):
yield
@ -191,35 +178,30 @@ class sphinx_domains:
"""Monkey-patch directive and role dispatch, so that domain-specific
markup takes precedence.
"""
def __init__(self, env):
# type: (BuildEnvironment) -> None
def __init__(self, env: "BuildEnvironment") -> None:
self.env = env
self.directive_func = None # type: Callable
self.roles_func = None # type: Callable
def __enter__(self):
# type: () -> None
def __enter__(self) -> None:
self.enable()
def __exit__(self, type, value, traceback):
# type: (str, str, str) -> None
def __exit__(self, exc_type: Type[Exception], exc_value: Exception, traceback: Any) -> bool: # NOQA
self.disable()
return True
def enable(self):
# type: () -> None
def enable(self) -> None:
self.directive_func = directives.directive
self.role_func = roles.role
directives.directive = self.lookup_directive # type: ignore
roles.role = self.lookup_role # type: ignore
directives.directive = self.lookup_directive
roles.role = self.lookup_role
def disable(self):
# type: () -> None
def disable(self) -> None:
directives.directive = self.directive_func
roles.role = self.role_func
def lookup_domain_element(self, type, name):
# type: (str, str) -> Any
def lookup_domain_element(self, type: str, name: str) -> Any:
"""Lookup a markup element (directive or role), given its name which can
be a full name (with domain).
"""
@ -247,24 +229,21 @@ class sphinx_domains:
raise ElementLookupError
def lookup_directive(self, name, lang_module, document):
# type: (str, ModuleType, nodes.document) -> Tuple[Type[Directive], List[nodes.system_message]] # NOQA
def lookup_directive(self, directive_name: str, language_module: ModuleType, document: nodes.document) -> Tuple[Optional[Type[Directive]], List[system_message]]: # NOQA
try:
return self.lookup_domain_element('directive', name)
return self.lookup_domain_element('directive', directive_name)
except ElementLookupError:
return self.directive_func(name, lang_module, document)
return self.directive_func(directive_name, language_module, document)
def lookup_role(self, name, lang_module, lineno, reporter):
# type: (str, ModuleType, int, Reporter) -> Tuple[RoleFunction, List[nodes.system_message]] # NOQA
def lookup_role(self, role_name: str, language_module: ModuleType, lineno: int, reporter: Reporter) -> Tuple[RoleFunction, List[system_message]]: # NOQA
try:
return self.lookup_domain_element('role', name)
return self.lookup_domain_element('role', role_name)
except ElementLookupError:
return self.role_func(name, lang_module, lineno, reporter)
return self.role_func(role_name, language_module, lineno, reporter)
class WarningStream:
def write(self, text):
# type: (str) -> None
def write(self, text: str) -> None:
matched = report_re.search(text)
if not matched:
logger.warning(text.rstrip("\r\n"))
@ -276,16 +255,14 @@ class WarningStream:
class LoggingReporter(Reporter):
@classmethod
def from_reporter(cls, reporter):
# type: (Reporter) -> LoggingReporter
def from_reporter(cls, reporter: Reporter) -> "LoggingReporter":
"""Create an instance of LoggingReporter from other reporter object."""
return cls(reporter.source, reporter.report_level, reporter.halt_level,
reporter.debug_flag, reporter.error_handler)
def __init__(self, source, report_level=Reporter.WARNING_LEVEL,
halt_level=Reporter.SEVERE_LEVEL, debug=False,
error_handler='backslashreplace'):
# type: (str, int, int, bool, str) -> None
def __init__(self, source: str, report_level: int = Reporter.WARNING_LEVEL,
halt_level: int = Reporter.SEVERE_LEVEL, debug: bool = False,
error_handler: str = 'backslashreplace') -> None:
stream = cast(IO, WarningStream())
super().__init__(source, report_level, halt_level,
stream, debug, error_handler=error_handler)
@ -294,18 +271,15 @@ class LoggingReporter(Reporter):
class NullReporter(Reporter):
"""A dummy reporter; write nothing."""
def __init__(self):
# type: () -> None
def __init__(self) -> None:
super().__init__('', 999, 4)
def is_html5_writer_available():
# type: () -> bool
def is_html5_writer_available() -> bool:
return __version_info__ > (0, 13, 0)
def directive_helper(obj, has_content=None, argument_spec=None, **option_spec):
# type: (Any, bool, Tuple[int, int, bool], Any) -> Any
def directive_helper(obj: Any, has_content: bool = None, argument_spec: Tuple[int, int, bool] = None, **option_spec) -> Any: # NOQA
warnings.warn('function based directive support is now deprecated. '
'Use class based directive instead.',
RemovedInSphinx30Warning)
@ -323,8 +297,7 @@ def directive_helper(obj, has_content=None, argument_spec=None, **option_spec):
@contextmanager
def switch_source_input(state, content):
# type: (State, StringList) -> Generator[None, None, None]
def switch_source_input(state: State, content: StringList) -> Generator[None, None, None]:
"""Switch current source input of state temporarily."""
try:
# remember the original ``get_source_and_line()`` method
@ -344,13 +317,11 @@ def switch_source_input(state, content):
class SphinxFileOutput(FileOutput):
"""Better FileOutput class for Sphinx."""
def __init__(self, **kwargs):
# type: (Any) -> None
def __init__(self, **kwargs) -> None:
self.overwrite_if_changed = kwargs.pop('overwrite_if_changed', False)
super().__init__(**kwargs)
def write(self, data):
# type: (str) -> str
def write(self, data: str) -> str:
if (self.destination_path and self.autoclose and 'b' not in self.mode and
self.overwrite_if_changed and os.path.exists(self.destination_path)):
with open(self.destination_path, encoding=self.encoding) as f:
@ -371,19 +342,16 @@ class SphinxDirective(Directive):
"""
@property
def env(self):
# type: () -> BuildEnvironment
def env(self) -> "BuildEnvironment":
"""Reference to the :class:`.BuildEnvironment` object."""
return self.state.document.settings.env
@property
def config(self):
# type: () -> Config
def config(self) -> "Config":
"""Reference to the :class:`.Config` object."""
return self.env.config
def set_source_info(self, node):
# type: (nodes.Node) -> None
def set_source_info(self, node: Node) -> None:
"""Set source and line number to the node."""
node.source, node.line = self.state_machine.get_source_and_line(self.lineno)
@ -406,8 +374,9 @@ class SphinxRole:
content = None #: A list of strings, the directive content for customization
#: (from the "role" directive).
def __call__(self, name, rawtext, text, lineno, inliner, options={}, content=[]):
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
def __call__(self, name: str, rawtext: str, text: str, lineno: int,
inliner: Inliner, options: Dict = {}, content: List[str] = []
) -> Tuple[List[Node], List[system_message]]:
self.rawtext = rawtext
self.text = unescape(text)
self.lineno = lineno
@ -427,24 +396,20 @@ class SphinxRole:
return self.run()
def run(self):
# type: () -> Tuple[List[nodes.Node], List[nodes.system_message]]
def run(self) -> Tuple[List[Node], List[system_message]]:
raise NotImplementedError
@property
def env(self):
# type: () -> BuildEnvironment
def env(self) -> "BuildEnvironment":
"""Reference to the :class:`.BuildEnvironment` object."""
return self.inliner.document.settings.env
@property
def config(self):
# type: () -> Config
def config(self) -> "Config":
"""Reference to the :class:`.Config` object."""
return self.env.config
def set_source_info(self, node, lineno=None):
# type: (nodes.Node, int) -> None
def set_source_info(self, node: Node, lineno: int = None) -> None:
if lineno is None:
lineno = self.lineno
@ -466,8 +431,9 @@ class ReferenceRole(SphinxRole):
# \x00 means the "<" was backslash-escaped
explicit_title_re = re.compile(r'^(.+?)\s*(?<!\x00)<(.*?)>$', re.DOTALL)
def __call__(self, name, rawtext, text, lineno, inliner, options={}, content=[]):
# type: (str, str, str, int, Inliner, Dict, List[str]) -> Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA
def __call__(self, name: str, rawtext: str, text: str, lineno: int,
inliner: Inliner, options: Dict = {}, content: List[str] = []
) -> Tuple[List[Node], List[system_message]]:
matched = self.explicit_title_re.match(text)
if matched:
self.has_explicit_title = True
@ -490,8 +456,7 @@ class SphinxTranslator(nodes.NodeVisitor):
This class is strongly coupled with Sphinx.
"""
def __init__(self, document, builder):
# type: (nodes.document, Builder) -> None
def __init__(self, document: nodes.document, builder: "Builder") -> None:
super().__init__(document)
self.builder = builder
self.config = builder.config
@ -503,8 +468,7 @@ class SphinxTranslator(nodes.NodeVisitor):
__document_cache__ = None # type: nodes.document
def new_document(source_path, settings=None):
# type: (str, Any) -> nodes.document
def new_document(source_path: str, settings: Any = None) -> nodes.document:
"""Return a new empty document object. This is an alternative of docutils'.
This is a simple wrapper for ``docutils.utils.new_document()``. It

View File

@ -10,20 +10,20 @@
import os
import re
import zlib
from typing import Callable, IO, Iterator
from sphinx.util import logging
if False:
# For type annotation
from typing import Callable, IO, Iterator # NOQA
from sphinx.builders import Builder # NOQA
from sphinx.environment import BuildEnvironment # NOQA
from sphinx.util.typing import Inventory # NOQA
from sphinx.util.typing import Inventory
BUFSIZE = 16 * 1024
logger = logging.getLogger(__name__)
if False:
# For type annotation
from sphinx.builders import Builder
from sphinx.environment import BuildEnvironment
class InventoryFileReader:
"""A file reader for inventory file.
@ -31,21 +31,18 @@ class InventoryFileReader:
This reader supports mixture of texts and compressed texts.
"""
def __init__(self, stream):
# type: (IO) -> None
def __init__(self, stream: IO) -> None:
self.stream = stream
self.buffer = b''
self.eof = False
def read_buffer(self):
# type: () -> None
def read_buffer(self) -> None:
chunk = self.stream.read(BUFSIZE)
if chunk == b'':
self.eof = True
self.buffer += chunk
def readline(self):
# type: () -> str
def readline(self) -> str:
pos = self.buffer.find(b'\n')
if pos != -1:
line = self.buffer[:pos].decode()
@ -59,15 +56,13 @@ class InventoryFileReader:
return line
def readlines(self):
# type: () -> Iterator[str]
def readlines(self) -> Iterator[str]:
while not self.eof:
line = self.readline()
if line:
yield line
def read_compressed_chunks(self):
# type: () -> Iterator[bytes]
def read_compressed_chunks(self) -> Iterator[bytes]:
decompressor = zlib.decompressobj()
while not self.eof:
self.read_buffer()
@ -75,8 +70,7 @@ class InventoryFileReader:
self.buffer = b''
yield decompressor.flush()
def read_compressed_lines(self):
# type: () -> Iterator[str]
def read_compressed_lines(self) -> Iterator[str]:
buf = b''
for chunk in self.read_compressed_chunks():
buf += chunk
@ -89,8 +83,7 @@ class InventoryFileReader:
class InventoryFile:
@classmethod
def load(cls, stream, uri, joinfunc):
# type: (IO, str, Callable) -> Inventory
def load(cls, stream: IO, uri: str, joinfunc: Callable) -> Inventory:
reader = InventoryFileReader(stream)
line = reader.readline().rstrip()
if line == '# Sphinx inventory version 1':
@ -101,8 +94,7 @@ class InventoryFile:
raise ValueError('invalid inventory header: %s' % line)
@classmethod
def load_v1(cls, stream, uri, join):
# type: (InventoryFileReader, str, Callable) -> Inventory
def load_v1(cls, stream: InventoryFileReader, uri: str, join: Callable) -> Inventory:
invdata = {} # type: Inventory
projname = stream.readline().rstrip()[11:]
version = stream.readline().rstrip()[11:]
@ -120,8 +112,7 @@ class InventoryFile:
return invdata
@classmethod
def load_v2(cls, stream, uri, join):
# type: (InventoryFileReader, str, Callable) -> Inventory
def load_v2(cls, stream: InventoryFileReader, uri: str, join: Callable) -> Inventory:
invdata = {} # type: Inventory
projname = stream.readline().rstrip()[11:]
version = stream.readline().rstrip()[11:]
@ -150,10 +141,8 @@ class InventoryFile:
return invdata
@classmethod
def dump(cls, filename, env, builder):
# type: (str, BuildEnvironment, Builder) -> None
def escape(string):
# type: (str) -> str
def dump(cls, filename: str, env: "BuildEnvironment", builder: "Builder") -> None:
def escape(string: str) -> str:
return re.sub("\\s+", " ", string)
with open(os.path.join(filename), 'wb') as f:

View File

@ -10,10 +10,7 @@
"""
import re
if False:
# For type annotation
from typing import Any, Dict, IO, List, Match, Union # NOQA
from typing import Any, Dict, IO, List, Match, Union
_str_re = re.compile(r'"(\\\\|\\"|[^"])*"')
_int_re = re.compile(r'\d+')
@ -35,10 +32,8 @@ ESCAPE_DICT = {
ESCAPED = re.compile(r'\\u.{4}|\\.')
def encode_string(s):
# type: (str) -> str
def replace(match):
# type: (Match) -> str
def encode_string(s: str) -> str:
def replace(match: Match) -> str:
s = match.group(0)
try:
return ESCAPE_DICT[s]
@ -55,8 +50,7 @@ def encode_string(s):
return '"' + str(ESCAPE_ASCII.sub(replace, s)) + '"'
def decode_string(s):
# type: (str) -> str
def decode_string(s: str) -> str:
return ESCAPED.sub(lambda m: eval('"' + m.group() + '"'), s)
@ -78,8 +72,7 @@ do import static with
double in super""".split())
def dumps(obj, key=False):
# type: (Any, bool) -> str
def dumps(obj: Any, key: bool = False) -> str:
if key:
if not isinstance(obj, str):
obj = str(obj)
@ -107,13 +100,11 @@ def dumps(obj, key=False):
raise TypeError(type(obj))
def dump(obj, f):
# type: (Any, IO) -> None
def dump(obj: Any, f: IO) -> None:
f.write(dumps(obj))
def loads(x):
# type: (str) -> Any
def loads(x: str) -> Any:
"""Loader that can read the JS subset the indexer produces."""
nothing = object()
i = 0
@ -205,6 +196,5 @@ def loads(x):
return obj
def load(f):
# type: (IO) -> Any
def load(f: IO) -> Any:
return loads(f.read())

Some files were not shown because too many files have changed in this diff Show More