summaryrefslogtreecommitdiff
path: root/sphinx/application.py
diff options
context:
space:
mode:
authorTakeshi KOMIYA <i.tkomiya@gmail.com>2021-01-24 16:34:47 +0900
committerTakeshi KOMIYA <i.tkomiya@gmail.com>2021-01-24 16:34:47 +0900
commit51d500833e391c182f536e83a5d62d5e90ce8ca9 (patch)
treefb854309b759773feb83e7e4bbc91e3ed3cb2b00 /sphinx/application.py
parent375fb52fe402d46d633e321ce8f20c1aa61c49b9 (diff)
parent41ee2d6e6595d0eefb4a2b752fd79a3451382d5a (diff)
downloadsphinx-git-51d500833e391c182f536e83a5d62d5e90ce8ca9.tar.gz
Merge branch '3.x' into 7774_remove_develop.rst
Diffstat (limited to 'sphinx/application.py')
-rw-r--r--sphinx/application.py213
1 files changed, 160 insertions, 53 deletions
diff --git a/sphinx/application.py b/sphinx/application.py
index bd23c86e7..69887682f 100644
--- a/sphinx/application.py
+++ b/sphinx/application.py
@@ -6,7 +6,7 @@
Gracefully adapted from the TextPress system by Armin.
- :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
+ :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
@@ -18,16 +18,17 @@ import warnings
from collections import deque
from io import StringIO
from os import path
-from typing import Any, Callable, Dict, IO, List, Tuple, Union
+from typing import IO, Any, Callable, Dict, List, Optional, Tuple, Union
from docutils import nodes
from docutils.nodes import Element, TextElement
+from docutils.parsers import Parser
from docutils.parsers.rst import Directive, roles
from docutils.transforms import Transform
from pygments.lexer import Lexer
import sphinx
-from sphinx import package_dir, locale
+from sphinx import locale, package_dir
from sphinx.config import Config
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.domains import Domain, Index
@@ -42,9 +43,7 @@ from sphinx.project import Project
from sphinx.registry import SphinxComponentRegistry
from sphinx.roles import XRefRole
from sphinx.theming import Theme
-from sphinx.util import docutils
-from sphinx.util import logging
-from sphinx.util import progress_message
+from sphinx.util import docutils, logging, progress_message
from sphinx.util.build_phase import BuildPhase
from sphinx.util.console import bold # type: ignore
from sphinx.util.i18n import CatalogRepository
@@ -55,8 +54,10 @@ from sphinx.util.typing import RoleFunction, TitleGetter
if False:
# For type annotation
- from docutils.nodes import Node # NOQA
from typing import Type # for python3.5.1
+
+ from docutils.nodes import Node # NOQA
+
from sphinx.builders import Builder
@@ -134,7 +135,7 @@ class Sphinx:
:ivar outdir: Directory for storing build documents.
"""
- def __init__(self, srcdir: str, confdir: str, outdir: str, doctreedir: str,
+ def __init__(self, srcdir: str, confdir: Optional[str], outdir: str, doctreedir: str,
buildername: str, confoverrides: Dict = None,
status: IO = sys.stdout, warning: IO = sys.stderr,
freshenv: bool = False, warningiserror: bool = False, tags: List[str] = None,
@@ -165,7 +166,7 @@ class Sphinx:
if path.exists(self.outdir) and not path.isdir(self.outdir):
raise ApplicationError(__('Output directory (%s) is not a directory') %
- self.srcdir)
+ self.outdir)
if self.srcdir == self.outdir:
raise ApplicationError(__('Source directory and destination '
@@ -293,7 +294,10 @@ class Sphinx:
if catalog.domain == 'sphinx' and catalog.is_outdated():
catalog.write_mo(self.config.language)
- locale_dirs = [None, path.join(package_dir, 'locale')] + list(repo.locale_dirs)
+ locale_dirs = list(repo.locale_dirs) # type: List[Optional[str]]
+ locale_dirs += [None]
+ locale_dirs += [path.join(package_dir, 'locale')]
+
self.translator, has_translation = locale.init(locale_dirs, self.config.language)
if has_translation or self.config.language == 'en':
# "en" never needs to be translated
@@ -400,9 +404,10 @@ class Sphinx:
def require_sphinx(self, version: str) -> None:
"""Check the Sphinx version if requested.
- Compare *version* (which must be a ``major.minor`` version string, e.g.
- ``'1.1'``) with the version of the running Sphinx, and abort the build
- when it is too old.
+ Compare *version* with the version of the running Sphinx, and abort the
+ build when it is too old.
+
+ :param version: The required version in the form of ``major.minor``.
.. versionadded:: 1.0
"""
@@ -416,11 +421,11 @@ class Sphinx:
For details on available core events and the arguments of callback
functions, please see :ref:`events`.
- Registered callbacks will be invoked on event in the order of *priority* and
- registration. The priority is ascending order.
-
- The method returns a "listener ID" that can be used as an argument to
- :meth:`disconnect`.
+ :param event: The name of target event
+ :param callback: Callback function for the event
+ :param priority: The priority of the callback. The callbacks will be invoked
+ in the order of *priority* in asending.
+ :return: A listener ID. It can be used for :meth:`disconnect`.
.. versionchanged:: 3.0
@@ -432,7 +437,10 @@ class Sphinx:
return listener_id
def disconnect(self, listener_id: int) -> None:
- """Unregister callback by *listener_id*."""
+ """Unregister callback by *listener_id*.
+
+ :param listener_id: A listener_id that :meth:`connect` returns
+ """
logger.debug('[app] disconnecting event: [id=%s]', listener_id)
self.events.disconnect(listener_id)
@@ -443,6 +451,10 @@ class Sphinx:
Return the return values of all callbacks as a list. Do not emit core
Sphinx events in extensions!
+ :param event: The name of event that will be emitted
+ :param args: The arguments for the event
+ :param allowed_exceptions: The list of exceptions that are allowed in the callbacks
+
.. versionchanged:: 3.1
Added *allowed_exceptions* to specify path-through exceptions
@@ -455,6 +467,10 @@ class Sphinx:
Return the result of the first callback that doesn't return ``None``.
+ :param event: The name of event that will be emitted
+ :param args: The arguments for the event
+ :param allowed_exceptions: The list of exceptions that are allowed in the callbacks
+
.. versionadded:: 0.5
.. versionchanged:: 3.1
@@ -468,8 +484,9 @@ class Sphinx:
def add_builder(self, builder: "Type[Builder]", override: bool = False) -> None:
"""Register a new builder.
- *builder* must be a class that inherits from
- :class:`~sphinx.builders.Builder`.
+ :param builder: A builder class
+ :param override: If true, install the builder forcedly even if another builder
+ is already installed as the same name
.. versionchanged:: 1.8
Add *override* keyword.
@@ -493,6 +510,10 @@ class Sphinx:
documents.
* ``''`` if a change in the setting will not need any special rebuild.
+ The *types* value takes a list of types that describes the type of
+ configuration value. For example, ``[str]`` is used to describe a
+ configuration that takes string value.
+
.. versionchanged:: 0.6
Changed *rebuild* from a simple boolean (equivalent to ``''`` or
``'env'``) to a string. However, booleans are still accepted and
@@ -526,6 +547,11 @@ class Sphinx:
builtin translator. This allows extensions to use custom translator
and define custom nodes for the translator (see :meth:`add_node`).
+ :param name: The name of builder for the translator
+ :param translator_class: A translator class
+ :param override: If true, install the translator forcedly even if another translator
+ is already installed as the same name
+
.. versionadded:: 1.3
.. versionchanged:: 1.8
Add *override* keyword.
@@ -560,6 +586,9 @@ class Sphinx:
Obviously, translators for which you don't specify visitor methods will
choke on the node when encountered in a document to translate.
+ If *override* is True, the given *node* is forcedly installed even if
+ a node having the same name is already installed.
+
.. versionchanged:: 0.5
Added the support for keyword arguments giving visit functions.
"""
@@ -595,6 +624,9 @@ class Sphinx:
Other keyword arguments are used for node visitor functions. See the
:meth:`.Sphinx.add_node` for details.
+ If *override* is True, the given *node* is forcedly installed even if
+ a node having the same name is already installed.
+
.. versionadded:: 1.4
"""
self.registry.add_enumerable_node(node, figtype, title_getter, override=override)
@@ -603,19 +635,19 @@ class Sphinx:
def add_directive(self, name: str, cls: "Type[Directive]", override: bool = False) -> None:
"""Register a Docutils directive.
- *name* must be the prospective directive name. *cls* is a directive
- class which inherits ``docutils.parsers.rst.Directive``. For more
- details, see `the Docutils docs
- <http://docutils.sourceforge.net/docs/howto/rst-directives.html>`_ .
+ :param name: The name of directive
+ :param cls: A directive class
+ :param override: If true, install the directive forcedly even if another directive
+ is already installed as the same name
- For example, the (already existing) :rst:dir:`literalinclude` directive
- would be added like this:
+ For example, a custom directive named ``my-directive`` would be added
+ like this:
.. code-block:: python
from docutils.parsers.rst import Directive, directives
- class LiteralIncludeDirective(Directive):
+ class MyDirective(Directive):
has_content = True
required_arguments = 1
optional_arguments = 0
@@ -628,7 +660,11 @@ class Sphinx:
def run(self):
...
- add_directive('literalinclude', LiteralIncludeDirective)
+ def setup(app):
+ add_directive('my-directive', MyDirective)
+
+ For more details, see `the Docutils docs
+ <http://docutils.sourceforge.net/docs/howto/rst-directives.html>`__ .
.. versionchanged:: 0.6
Docutils 0.5-style directive classes are now supported.
@@ -647,10 +683,13 @@ class Sphinx:
def add_role(self, name: str, role: Any, override: bool = False) -> None:
"""Register a Docutils role.
- *name* must be the role name that occurs in the source, *role* the role
- function. Refer to the `Docutils documentation
- <http://docutils.sourceforge.net/docs/howto/rst-roles.html>`_ for
- more information.
+ :param name: The name of role
+ :param cls: A role function
+ :param override: If true, install the role forcedly even if another role is already
+ installed as the same name
+
+ For more details about role functions, see `the Docutils docs
+ <http://docutils.sourceforge.net/docs/howto/rst-roles.html>`__ .
.. versionchanged:: 1.8
Add *override* keyword.
@@ -667,6 +706,9 @@ class Sphinx:
Register a Docutils role that does nothing but wrap its contents in the
node given by *nodeclass*.
+ If *override* is True, the given *nodeclass* is forcedly installed even if
+ a role named as *name* is already installed.
+
.. versionadded:: 0.6
.. versionchanged:: 1.8
Add *override* keyword.
@@ -686,6 +728,9 @@ class Sphinx:
Make the given *domain* (which must be a class; more precisely, a
subclass of :class:`~sphinx.domains.Domain`) known to Sphinx.
+ If *override* is True, the given *domain* is forcedly installed even if
+ a domain having the same name is already installed.
+
.. versionadded:: 1.0
.. versionchanged:: 1.8
Add *override* keyword.
@@ -699,6 +744,9 @@ class Sphinx:
Like :meth:`add_directive`, but the directive is added to the domain
named *domain*.
+ If *override* is True, the given *directive* is forcedly installed even if
+ a directive named as *name* is already installed.
+
.. versionadded:: 1.0
.. versionchanged:: 1.8
Add *override* keyword.
@@ -712,6 +760,9 @@ class Sphinx:
Like :meth:`add_role`, but the role is added to the domain named
*domain*.
+ If *override* is True, the given *role* is forcedly installed even if
+ a role named as *name* is already installed.
+
.. versionadded:: 1.0
.. versionchanged:: 1.8
Add *override* keyword.
@@ -725,6 +776,9 @@ class Sphinx:
Add a custom *index* class to the domain named *domain*. *index* must
be a subclass of :class:`~sphinx.domains.Index`.
+ If *override* is True, the given *index* is forcedly installed even if
+ an index having the same name is already installed.
+
.. versionadded:: 1.0
.. versionchanged:: 1.8
Add *override* keyword.
@@ -788,6 +842,9 @@ class Sphinx:
For the role content, you have the same syntactical possibilities as
for standard Sphinx roles (see :ref:`xref-syntax`).
+ If *override* is True, the given object_type is forcedly installed even if
+ an object_type having the same name is already installed.
+
.. versionchanged:: 1.8
Add *override* keyword.
"""
@@ -824,6 +881,9 @@ class Sphinx:
(Of course, the element following the ``topic`` directive needn't be a
section.)
+ If *override* is True, the given crossref_type is forcedly installed even if
+ a crossref_type having the same name is already installed.
+
.. versionchanged:: 1.8
Add *override* keyword.
"""
@@ -873,22 +933,24 @@ class Sphinx:
"""
self.registry.add_post_transform(transform)
- def add_javascript(self, filename: str, **kwargs: str) -> None:
+ def add_javascript(self, filename: str, **kwargs: Any) -> None:
"""An alias of :meth:`add_js_file`."""
warnings.warn('The app.add_javascript() is deprecated. '
'Please use app.add_js_file() instead.',
RemovedInSphinx40Warning, stacklevel=2)
self.add_js_file(filename, **kwargs)
- def add_js_file(self, filename: str, **kwargs: str) -> None:
+ def add_js_file(self, filename: str, priority: int = 500, **kwargs: Any) -> None:
"""Register a JavaScript file to include in the HTML output.
Add *filename* to the list of JavaScript files that the default HTML
- template will include. The filename must be relative to the HTML
- static path , or a full URI with scheme. If the keyword argument
- ``body`` is given, its value will be added between the
- ``<script>`` tags. Extra keyword arguments are included as
- attributes of the ``<script>`` tag.
+ template will include in order of *priority* (ascending). The filename
+ must be relative to the HTML static path , or a full URI with scheme.
+ If the priority of JavaScript file is the same as others, the JavaScript
+ files will be included in order of the registration. If the keyword
+ argument ``body`` is given, its value will be added between the
+ ``<script>`` tags. Extra keyword arguments are included as attributes of
+ the ``<script>`` tag.
Example::
@@ -901,23 +963,43 @@ class Sphinx:
app.add_js_file(None, body="var myVariable = 'foo';")
# => <script>var myVariable = 'foo';</script>
+ .. list-table:: priority range for JavaScript files
+ :widths: 20,80
+
+ * - Priority
+ - Main purpose in Sphinx
+ * - 200
+ - default priority for built-in JavaScript files
+ * - 500
+ - default priority for extensions
+ * - 800
+ - default priority for :confval:`html_js_files`
+
+ A JavaScript file can be added to the specific HTML page when on extension
+ calls this method on :event:`html-page-context` event.
+
.. versionadded:: 0.5
.. versionchanged:: 1.8
Renamed from ``app.add_javascript()``.
And it allows keyword arguments as attributes of script tag.
+
+ .. versionchanged:: 3.5
+ Take priority argument. Allow to add a JavaScript file to the specific page.
"""
- self.registry.add_js_file(filename, **kwargs)
+ self.registry.add_js_file(filename, priority=priority, **kwargs)
if hasattr(self.builder, 'add_js_file'):
- self.builder.add_js_file(filename, **kwargs) # type: ignore
+ self.builder.add_js_file(filename, priority=priority, **kwargs) # type: ignore
- def add_css_file(self, filename: str, **kwargs: str) -> None:
+ def add_css_file(self, filename: str, priority: int = 500, **kwargs: Any) -> None:
"""Register a stylesheet to include in the HTML output.
Add *filename* to the list of CSS files that the default HTML template
- will include. The filename must be relative to the HTML static path,
- or a full URI with scheme. The keyword arguments are also accepted for
- attributes of ``<link>`` tag.
+ will include in order of *priority* (ascending). The filename must be
+ relative to the HTML static path, or a full URI with scheme. If the
+ priority of CSS file is the same as others, the CSS files will be
+ included in order of the registration. The keyword arguments are also
+ accepted for attributes of ``<link>`` tag.
Example::
@@ -932,6 +1014,19 @@ class Sphinx:
# => <link rel="alternate stylesheet" href="_static/fancy.css"
# type="text/css" title="fancy" />
+ .. list-table:: priority range for CSS files
+ :widths: 20,80
+
+ * - Priority
+ - Main purpose in Sphinx
+ * - 500
+ - default priority for extensions
+ * - 800
+ - default priority for :confval:`html_css_files`
+
+ A CSS file can be added to the specific HTML page when on extension calls
+ this method on :event:`html-page-context` event.
+
.. versionadded:: 1.0
.. versionchanged:: 1.6
@@ -944,11 +1039,14 @@ class Sphinx:
.. versionchanged:: 1.8
Renamed from ``app.add_stylesheet()``.
And it allows keyword arguments as attributes of link tag.
+
+ .. versionchanged:: 3.5
+ Take priority argument. Allow to add a CSS file to the specific page.
"""
logger.debug('[app] adding stylesheet: %r', filename)
- self.registry.add_css_files(filename, **kwargs)
+ self.registry.add_css_files(filename, priority=priority, **kwargs)
if hasattr(self.builder, 'add_css_file'):
- self.builder.add_css_file(filename, **kwargs) # type: ignore
+ self.builder.add_css_file(filename, priority=priority, **kwargs) # type: ignore
def add_stylesheet(self, filename: str, alternate: bool = False, title: str = None
) -> None:
@@ -957,7 +1055,7 @@ class Sphinx:
'Please use app.add_css_file() instead.',
RemovedInSphinx40Warning, stacklevel=2)
- attributes = {} # type: Dict[str, str]
+ attributes = {} # type: Dict[str, Any]
if alternate:
attributes['rel'] = 'alternate stylesheet'
else:
@@ -1004,7 +1102,7 @@ class Sphinx:
logger.debug('[app] adding lexer: %r', (alias, lexer))
if isinstance(lexer, Lexer):
warnings.warn('app.add_lexer() API changed; '
- 'Please give lexer class instead instance',
+ 'Please give lexer class instead of instance',
RemovedInSphinx40Warning, stacklevel=2)
lexers[alias] = lexer
else:
@@ -1019,6 +1117,9 @@ class Sphinx:
new types of objects. See the source of the autodoc module for
examples on how to subclass :class:`Documenter`.
+ If *override* is True, the given *cls* is forcedly installed even if
+ a documenter having the same name is already installed.
+
.. todo:: Add real docs for Documenter and subclassing
.. versionadded:: 0.6
@@ -1057,7 +1158,7 @@ class Sphinx:
.. versionadded:: 1.1
"""
logger.debug('[app] adding search language: %r', cls)
- from sphinx.search import languages, SearchLanguage
+ from sphinx.search import SearchLanguage, languages
assert issubclass(cls, SearchLanguage)
languages[cls.lang] = cls
@@ -1067,13 +1168,19 @@ class Sphinx:
Same as :confval:`source_suffix`. The users can override this
using the setting.
+ If *override* is True, the given *suffix* is forcedly installed even if
+ a same suffix is already installed.
+
.. versionadded:: 1.8
"""
self.registry.add_source_suffix(suffix, filetype, override=override)
- def add_source_parser(self, *args: Any, **kwargs: Any) -> None:
+ def add_source_parser(self, parser: "Type[Parser]", override: bool = False) -> None:
"""Register a parser class.
+ If *override* is True, the given *parser* is forcedly installed even if
+ a parser for the same suffix is already installed.
+
.. versionadded:: 1.4
.. versionchanged:: 1.8
*suffix* argument is deprecated. It only accepts *parser* argument.
@@ -1081,7 +1188,7 @@ class Sphinx:
.. versionchanged:: 1.8
Add *override* keyword.
"""
- self.registry.add_source_parser(*args, **kwargs)
+ self.registry.add_source_parser(parser, override=override)
def add_env_collector(self, collector: "Type[EnvironmentCollector]") -> None:
"""Register an environment collector class.