Merge branch '3.x' into 7774_remove_develop.rst

This commit is contained in:
Takeshi KOMIYA 2021-01-24 16:34:47 +09:00
commit 51d500833e
610 changed files with 17988 additions and 4879 deletions

View File

@ -3,12 +3,14 @@ jobs:
build:
docker:
- image: sphinxdoc/docker-ci
environment:
DO_EPUBCHECK: 1
working_directory: /sphinx
steps:
- checkout
- run: /python3.6/bin/pip install -U pip setuptools
- run: /python3.6/bin/pip install -U .[test]
- run: mkdir -p test-reports/pytest
- run: make test PYTHON=/python3.6/bin/python TEST=--junitxml=test-reports/pytest/results.xml
- run: make test PYTHON=/python3.6/bin/python TEST="--junitxml=test-reports/pytest/results.xml -vv"
- store_test_results:
path: test-reports

View File

@ -2,5 +2,8 @@
blank_issues_enabled: false # default: true
contact_links:
- name: Question
url: https://stackoverflow.com/questions/tagged/python-sphinx
about: For Q&A purpose, please use Stackoverflow with the tag python-sphinx
- name: Discussion
url: https://groups.google.com/forum/#!forum/sphinx-users
about: For Q&A purpose, please use sphinx-users mailing list.
about: For general discussion, please use sphinx-users mailing list.

View File

@ -7,7 +7,7 @@ Subject: <short purpose of this pull request>
- Critical or severe bugs: X.Y.Z
- Others: X.Y
For more details, see https://www.sphinx-doc.org/en/master/devguide.html#branch-model
For more details, see https://www.sphinx-doc.org/en/master/internals/release-process.html#branch-model
-->
### Feature or Bugfix

21
.github/workflows/builddoc.yml vendored Normal file
View File

@ -0,0 +1,21 @@
name: Build document
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: 3.6
- name: Install dependencies
run: |
sudo apt update
sudo apt install -y graphviz
pip install -U tox
- name: Run Tox
run: tox -e docs

22
.github/workflows/lint.yml vendored Normal file
View File

@ -0,0 +1,22 @@
name: Lint source code
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
tool: [docslint, flake8, isort, mypy, twine]
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v1
with:
python-version: 3.6
- name: Install dependencies
run: pip install -U tox
- name: Run Tox
run: tox -e ${{ matrix.tool }}

View File

@ -1,9 +1,64 @@
name: CI on Windows
name: CI
on: [push, pull_request]
jobs:
build:
ubuntu:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
name: [py35, py36, py37, py38, py39]
os: [ubuntu-16.04]
include:
- name: py35
python: 3.5
docutils: du12
- name: py36
python: 3.6
docutils: du13
- name: py37
python: 3.7
docutils: du14
- name: py38
python: 3.8
docutils: du15
- name: py39
python: 3.9
docutils: du16
coverage: "--cov ./ --cov-append --cov-config setup.cfg"
- name: py310-dev
python: 3.10-dev
docutils: du16
os: ubuntu-latest # required
env:
PYTEST_ADDOPTS: ${{ matrix.coverage }}
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v2
if: "!endsWith(matrix.python, '-dev')"
with:
python-version: ${{ matrix.python }}
- name: Set up Python ${{ matrix.python }} (deadsnakes)
uses: deadsnakes/action@v2.0.1
if: endsWith(matrix.python, '-dev')
with:
python-version: ${{ matrix.python }}
- name: Check Python version
run: python --version
- name: Install graphviz
run: sudo apt-get install graphviz
- name: Install dependencies
run: pip install -U tox codecov
- name: Run Tox
run: tox -e ${{ matrix.docutils }} -- -vv
- name: codecov
uses: codecov/codecov-action@v1
if: matrix.coverage
windows:
runs-on: windows-latest
strategy:
matrix:
@ -18,4 +73,4 @@ jobs:
- name: Install dependencies
run: pip install -U tox
- name: Run Tox
run: tox -e py
run: tox -e py -- -vv

21
.github/workflows/nodejs.yml vendored Normal file
View File

@ -0,0 +1,21 @@
name: CI (node.js)
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
env:
node-version: 10.7
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ env.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ env.node-version }}
- run: npm install
- name: Run headless test
uses: GabrielBB/xvfb-action@v1
with:
run: npm test

8
.readthedocs.yml Normal file
View File

@ -0,0 +1,8 @@
version: 2
python:
version: 3
install:
- method: pip
path: .
extra_requirements:
- docs

View File

@ -1,54 +0,0 @@
os: linux
dist: xenial
language: python
cache: pip
env:
global:
- PYTHONFAULTHANDLER=x
- SKIP_LATEX_BUILD=1
- IS_PYTHON=true
jobs:
include:
- python: '3.5'
env:
- TOXENV=du12
- python: '3.6'
env:
- TOXENV=du13
- python: '3.7'
env:
- TOXENV=du14
- python: '3.8'
env:
- TOXENV=du15
- PYTEST_ADDOPTS="--cov ./ --cov-append --cov-config setup.cfg"
- python: 'nightly'
env:
- TOXENV=du16
- python: '3.6'
env: TOXENV=docs
- python: '3.6'
env: TOXENV=docslint
- python: '3.6'
env: TOXENV=mypy
- python: '3.6'
env: TOXENV=flake8
- language: node_js
node_js: '10.7'
env: IS_PYTHON=false
services: xvfb
install:
- "sudo apt-get install graphviz"
- if [ $IS_PYTHON = true ]; then pip install -U tox codecov; fi
- if [ $IS_PYTHON = false ]; then npm install; fi
script:
- if [ $IS_PYTHON = true ]; then tox -- -v; fi
- if [ $IS_PYTHON = false ]; then npm test; fi
after_success:
- if [[ -e .coverage ]]; then codecov -e $TOXENV; fi

596
CHANGES
View File

@ -1,9 +1,555 @@
Release 3.1.0 (in development)
Release 3.5.0 (in development)
==============================
Dependencies
------------
Incompatible changes
--------------------
* Update Underscore.js to 1.12.0
* #6550: html: The config variable ``html_add_permalinks`` is replaced by
:confval:`html_permalinks` and :confval:`html_permalinks_icon`
Deprecated
----------
* pending_xref node for viewcode extension
* ``sphinx.builders.linkcheck.CheckExternalLinksBuilder.broken``
* ``sphinx.builders.linkcheck.CheckExternalLinksBuilder.good``
* ``sphinx.builders.linkcheck.CheckExternalLinksBuilder.redirected``
* ``sphinx.builders.linkcheck.node_line_or_0()``
* ``sphinx.ext.autodoc.AttributeDocumenter.isinstanceattribute()``
* ``sphinx.ext.autodoc.directive.DocumenterBridge.reporter``
* ``sphinx.ext.autodoc.importer.get_module_members()``
* ``sphinx.ext.autosummary.generate._simple_info()``
* ``sphinx.ext.autosummary.generate._simple_warn()``
* ``sphinx.writers.html.HTMLTranslator.permalink_text``
* ``sphinx.writers.html5.HTML5Translator.permalink_text``
Features added
--------------
* #8022: autodoc: autodata and autoattribute directives does not show right-hand
value of the variable if docstring contains ``:meta hide-value:`` in
info-field-list
* #8514: autodoc: Default values of overloaded functions are taken from actual
implementation if they're ellipsis
* #8619: html: kbd role generates customizable HTML tags for compound keys
* #8634: html: Allow to change the order of JS/CSS via ``priority`` parameter
for :meth:`Sphinx.add_js_file()` and :meth:`Sphinx.add_css_file()`
* #6241: html: Allow to add JS/CSS files to the specific page when an extension
calls ``app.add_js_file()`` or ``app.add_css_file()`` on
:event:`html-page-context` event
* #6550: html: Allow to use HTML permalink texts via
:confval:`html_permalinks_icon`
* #8649: imgconverter: Skip availability check if builder supports the image
type
* #8573: napoleon: Allow to change the style of custom sections using
:confval:`napoleon_custom_styles`
* #8004: napoleon: Type definitions in Google style docstrings are rendered as
references when :confval:`napoleon_preprocess_types` enabled
* #6241: mathjax: Include mathjax.js only on the document using equations
* #8651: std domain: cross-reference for a rubric having inline item is broken
* #8681: viewcode: Support incremental build
* #8132: Add :confval:`project_copyright` as an alias of :confval:`copyright`
* #207: Now :confval:`highlight_language` supports multiple languages
* #2030: :rst:dir:`code-block` and :rst:dir:`literalinclude` supports automatic
dedent via no-argument ``:dedent:`` option
* C++, also hyperlink operator overloads in expressions and alias declarations.
* #8247: Allow production lists to refer to tokens from other production groups
Bugs fixed
----------
* #8727: apidoc: namespace module file is not generated if no submodules there
* #741: autodoc: inherited-members doesn't work for instance attributes on super
class
* #8592: autodoc: ``:meta public:`` does not effect to variables
* #8594: autodoc: empty __all__ attribute is ignored
* #8315: autodoc: Failed to resolve struct.Struct type annotation
* #8652: autodoc: All variable comments in the module are ignored if the module
contains invalid type comments
* #8693: autodoc: Default values for overloaded functions are rendered as string
* #8306: autosummary: mocked modules are documented as empty page when using
:recursive: option
* #8618: html: kbd role produces incorrect HTML when compound-key separators (-,
+ or ^) are used as keystrokes
* #8629: html: A type warning for html_use_opensearch is shown twice
* #8714: html: kbd role with "Caps Lock" rendered incorrectly
* #8665: html theme: Could not override globaltoc_maxdepth in theme.conf
* #4304: linkcheck: Fix race condition that could lead to checking the
availability of the same URL twice
* #8094: texinfo: image files on the different directory with document are not
copied
* #8720: viewcode: module pages are generated for epub on incremental build
* #8704: viewcode: anchors are generated in incremental build after singlehtml
* #8671: :confval:`highlight_options` is not working
* #8341: C, fix intersphinx lookup types for names in declarations.
* C, C++: in general fix intersphinx and role lookup types.
* #8683: :confval:`html_last_updated_fmt` does not support UTC offset (%z)
* #8683: :confval:`html_last_updated_fmt` generates wrong time zone for %Z
* #1112: ``download`` role creates duplicated copies when relative path is
specified
* #8735: LaTeX: wrong internal links in pdf to captioned code-blocks when
:confval:`numfig` is not True
Testing
--------
Release 3.4.4 (in development)
==============================
Dependencies
------------
Incompatible changes
--------------------
Deprecated
----------
Features added
--------------
Bugs fixed
----------
* #8655: autodoc: Failed to generate document if target module contains an
object that raises an exception on ``hasattr()``
* C, ``expr`` role should start symbol lookup in the current scope.
Testing
--------
Release 3.4.3 (released Jan 08, 2021)
=====================================
Bugs fixed
----------
* #8655: autodoc: Failed to generate document if target module contains an
object that raises an exception on ``hasattr()``
Release 3.4.2 (released Jan 04, 2021)
=====================================
Bugs fixed
----------
* #8164: autodoc: Classes that inherit mocked class are not documented
* #8602: autodoc: The ``autodoc-process-docstring`` event is emitted to the
non-datadescriptors unexpectedly
* #8616: autodoc: AttributeError is raised on non-class object is passed to
autoclass directive
Release 3.4.1 (released Dec 25, 2020)
=====================================
Bugs fixed
----------
* #8559: autodoc: AttributeError is raised when using forward-reference type
annotations
* #8568: autodoc: TypeError is raised on checking slots attribute
* #8567: autodoc: Instance attributes are incorrectly added to Parent class
* #8566: autodoc: The ``autodoc-process-docstring`` event is emitted to the
alias classes unexpectedly
* #8583: autodoc: Unnecessary object comparision via ``__eq__`` method
* #8565: linkcheck: Fix PriorityQueue crash when link tuples are not
comparable
Release 3.4.0 (released Dec 20, 2020)
=====================================
Incompatible changes
--------------------
* #8105: autodoc: the signature of class constructor will be shown for decorated
classes, not a signature of decorator
Deprecated
----------
* The ``follow_wrapped`` argument of ``sphinx.util.inspect.signature()``
* The ``no_docstring`` argument of
``sphinx.ext.autodoc.Documenter.add_content()``
* ``sphinx.ext.autodoc.Documenter.get_object_members()``
* ``sphinx.ext.autodoc.DataDeclarationDocumenter``
* ``sphinx.ext.autodoc.GenericAliasDocumenter``
* ``sphinx.ext.autodoc.InstanceAttributeDocumenter``
* ``sphinx.ext.autodoc.SlotsAttributeDocumenter``
* ``sphinx.ext.autodoc.TypeVarDocumenter``
* ``sphinx.ext.autodoc.importer._getannotations()``
* ``sphinx.ext.autodoc.importer._getmro()``
* ``sphinx.pycode.ModuleAnalyzer.parse()``
* ``sphinx.util.osutil.movefile()``
* ``sphinx.util.requests.is_ssl_error()``
Features added
--------------
* #8119: autodoc: Allow to determine whether a member not included in
``__all__`` attribute of the module should be documented or not via
:event:`autodoc-skip-member` event
* #8219: autodoc: Parameters for generic class are not shown when super class is
a generic class and show-inheritance option is given (in Python 3.7 or above)
* autodoc: Add ``Documenter.config`` as a shortcut to access the config object
* autodoc: Add Optional[t] to annotation of function and method if a default
value equal to None is set.
* #8209: autodoc: Add ``:no-value:`` option to :rst:dir:`autoattribute` and
:rst:dir:`autodata` directive to suppress the default value of the variable
* #8460: autodoc: Support custom types defined by typing.NewType
* #8285: napoleon: Add :confval:`napoleon_attr_annotations` to merge type hints
on source code automatically if any type is specified in docstring
* #8236: napoleon: Support numpydoc's "Receives" section
* #6914: Add a new event :event:`warn-missing-reference` to custom warning
messages when failed to resolve a cross-reference
* #6914: Emit a detailed warning when failed to resolve a ``:ref:`` reference
* #6629: linkcheck: The builder now handles rate limits. See
:confval:`linkcheck_retry_on_rate_limit` for details.
Bugs fixed
----------
* #7613: autodoc: autodoc does not respect __signature__ of the class
* #4606: autodoc: the location of the warning is incorrect for inherited method
* #8105: autodoc: the signature of class constructor is incorrect if the class
is decorated
* #8434: autodoc: :confval:`autodoc_type_aliases` does not effect to variables
and attributes
* #8443: autodoc: autodata directive can't create document for PEP-526 based
type annotated variables
* #8443: autodoc: autoattribute directive can't create document for PEP-526
based uninitalized variables
* #8480: autodoc: autoattribute could not create document for __slots__
attributes
* #8503: autodoc: autoattribute could not create document for a GenericAlias as
class attributes correctly
* #8534: autodoc: autoattribute could not create document for a commented
attribute in alias class
* #8452: autodoc: autodoc_type_aliases doesn't work when autodoc_typehints is
set to "description"
* #8541: autodoc: autodoc_type_aliases doesn't work for the type annotation to
instance attributes
* #8460: autodoc: autodata and autoattribute directives do not display type
information of TypeVars
* #8493: autodoc: references to builtins not working in class aliases
* #8522: autodoc: ``__bool__`` method could be called
* #8067: autodoc: A typehint for the instance variable having type_comment on
super class is not displayed
* #8545: autodoc: a __slots__ attribute is not documented even having docstring
* #741: autodoc: inherited-members doesn't work for instance attributes on super
class
* #8477: autosummary: non utf-8 reST files are generated when template contains
multibyte characters
* #8501: autosummary: summary extraction splits text after "el at." unexpectedly
* #8524: html: Wrong url_root has been generated on a document named "index"
* #8419: html search: Do not load ``language_data.js`` in non-search pages
* #8549: i18n: ``-D gettext_compact=0`` is no longer working
* #8454: graphviz: The layout option for graph and digraph directives don't work
* #8131: linkcheck: Use GET when HEAD requests cause Too Many Redirects, to
accommodate infinite redirect loops on HEAD
* #8437: Makefile: ``make clean`` with empty BUILDDIR is dangerous
* #8365: py domain: ``:type:`` and ``:rtype:`` gives false ambiguous class
lookup warnings
* #8352: std domain: Failed to parse an option that starts with bracket
* #8519: LaTeX: Prevent page brake in the middle of a seealso
* #8520: C, fix copying of AliasNode.
Release 3.3.1 (released Nov 12, 2020)
=====================================
Bugs fixed
----------
* #8372: autodoc: autoclass directive became slower than Sphinx-3.2
* #7727: autosummary: raise PycodeError when documenting python package
without __init__.py
* #8350: autosummary: autosummary_mock_imports causes slow down builds
* #8364: C, properly initialize attributes in empty symbols.
* #8399: i18n: Put system locale path after the paths specified by configuration
Release 3.3.0 (released Nov 02, 2020)
=====================================
Deprecated
----------
* ``sphinx.builders.latex.LaTeXBuilder.usepackages``
* ``sphinx.builders.latex.LaTeXBuilder.usepackages_afger_hyperref``
* ``sphinx.ext.autodoc.SingledispatchFunctionDocumenter``
* ``sphinx.ext.autodoc.SingledispatchMethodDocumenter``
Features added
--------------
* #8100: html: Show a better error message for failures on copying
html_static_files
* #8141: C: added a ``maxdepth`` option to :rst:dir:`c:alias` to insert
nested declarations.
* #8081: LaTeX: Allow to add LaTeX package via ``app.add_latex_package()`` until
just before writing .tex file
* #7996: manpage: Add :confval:`man_make_section_directory` to make a section
directory on build man page
* #8289: epub: Allow to suppress "duplicated ToC entry found" warnings from epub
builder using :confval:`suppress_warnings`.
* #8298: sphinx-quickstart: Add :option:`sphinx-quickstart --no-sep` option
* #8304: sphinx.testing: Register public markers in sphinx.testing.fixtures
* #8051: napoleon: use the obj role for all See Also items
* #8050: napoleon: Apply :confval:`napoleon_preprocess_types` to every field
* C and C++, show line numbers for previous declarations when duplicates are
detected.
* #8183: Remove substitution_reference nodes from doctree only on LaTeX builds
Bugs fixed
----------
* #8085: i18n: Add support for having single text domain
* #6640: i18n: Failed to override system message translation
* #8143: autodoc: AttributeError is raised when False value is passed to
autodoc_default_options
* #8103: autodoc: functools.cached_property is not considered as a property
* #8190: autodoc: parsing error is raised if some extension replaces docstring
by string not ending with blank lines
* #8142: autodoc: Wrong constructor signature for the class derived from
typing.Generic
* #8157: autodoc: TypeError is raised when annotation has invalid __args__
* #7964: autodoc: Tuple in default value is wrongly rendered
* #8200: autodoc: type aliases break type formatting of autoattribute
* #7786: autodoc: can't detect overloaded methods defined in other file
* #8294: autodoc: single-string __slots__ is not handled correctly
* #7785: autodoc: autodoc_typehints='none' does not effect to overloaded functions
* #8192: napoleon: description is disappeared when it contains inline literals
* #8142: napoleon: Potential of regex denial of service in google style docs
* #8169: LaTeX: pxjahyper loaded even when latex_engine is not platex
* #8215: LaTeX: 'oneside' classoption causes build warning
* #8175: intersphinx: Potential of regex denial of service by broken inventory
* #8277: sphinx-build: missing and redundant spacing (and etc) for console
output on building
* #7973: imgconverter: Check availability of imagemagick many times
* #8255: py domain: number in default argument value is changed from hexadecimal
to decimal
* #8316: html: Prevent arrow keys changing page when button elements are focused
* #8343: html search: Fix unnecessary load of images when parsing the document
* #8254: html theme: Line numbers misalign with code lines
* #8093: The highlight warning has wrong location in some builders (LaTeX,
singlehtml and so on)
* #8215: Eliminate Fancyhdr build warnings for oneside documents
* #8239: Failed to refer a token in productionlist if it is indented
* #8268: linkcheck: Report HTTP errors when ``linkcheck_anchors`` is ``True``
* #8245: linkcheck: take source directory into account for local files
* #8321: linkcheck: ``tel:`` schema hyperlinks are detected as errors
* #8323: linkcheck: An exit status is incorrect when links having unsupported
schema found
* #8188: C, add missing items to internal object types dictionary,
e.g., preventing intersphinx from resolving them.
* C, fix anon objects in intersphinx.
* #8270, C++, properly reject functions as duplicate declarations if a
non-function declaration of the same name already exists.
* C, fix references to function parameters.
Link to the function instead of a non-existing anchor.
* #6914: figure numbers are unexpectedly assigned to uncaptioned items
* #8320: make "inline" line numbers un-selectable
Testing
--------
* #8257: Support parallel build in sphinx.testing
Release 3.2.1 (released Aug 14, 2020)
=====================================
Features added
--------------
* #8095: napoleon: Add :confval:`napoleon_preprocess_types` to enable the type
preprocessor for numpy style docstrings
* #8114: C and C++, parse function attributes after parameters and qualifiers.
Bugs fixed
----------
* #8074: napoleon: Crashes during processing C-ext module
* #8088: napoleon: "Inline literal start-string without end-string" warning in
Numpy style Parameters section
* #8084: autodoc: KeyError is raised on documenting an attribute of the broken
class
* #8091: autodoc: AttributeError is raised on documenting an attribute on Python
3.5.2
* #8099: autodoc: NameError is raised when target code uses ``TYPE_CHECKING``
* C++, fix parsing of template template paramters, broken by the fix of #7944
Release 3.2.0 (released Aug 08, 2020)
=====================================
Deprecated
----------
* ``sphinx.ext.autodoc.members_set_option()``
* ``sphinx.ext.autodoc.merge_special_members_option()``
* ``sphinx.writers.texinfo.TexinfoWriter.desc``
* C, parsing of pre-v3 style type directives and roles, along with the options
:confval:`c_allow_pre_v3` and :confval:`c_warn_on_allowed_pre_v3`.
Features added
--------------
* #2076: autodoc: Allow overriding of exclude-members in skip-member function
* #8034: autodoc: ``:private-member:`` can take an explicit list of member names
to be documented
* #2024: autosummary: Add :confval:`autosummary_filename_map` to avoid conflict
of filenames between two object with different case
* #8011: autosummary: Support instance attributes as a target of autosummary
directive
* #7849: html: Add :confval:`html_codeblock_linenos_style` to change the style
of line numbers for code-blocks
* #7853: C and C++, support parameterized GNU style attributes.
* #7888: napoleon: Add aliases Warn and Raise.
* #7690: napoleon: parse type strings and make them hyperlinks as possible. The
conversion rule can be updated via :confval:`napoleon_type_aliases`
* #8049: napoleon: Create a hyperlink for each the type of parameter when
:confval:`napoleon_use_params` is False
* C, added :rst:dir:`c:alias` directive for inserting copies
of existing declarations.
* #7745: html: inventory is broken if the docname contains a space
* #7991: html search: Allow searching for numbers
* #7902: html theme: Add a new option :confval:`globaltoc_maxdepth` to control
the behavior of globaltoc in sidebar
* #7840: i18n: Optimize the dependencies check on bootstrap
* #7768: i18n: :confval:`figure_language_filename` supports ``docpath`` token
* #5208: linkcheck: Support checks for local links
* #5090: setuptools: Link verbosity to distutils' -v and -q option
* #6698: doctest: Add ``:trim-doctest-flags:`` and ``:no-trim-doctest-flags:``
options to doctest, testcode and testoutput directives
* #7052: add ``:noindexentry:`` to the Python, C, C++, and Javascript domains.
Update the documentation to better reflect the relationship between this option
and the ``:noindex:`` option.
* #7899: C, add possibility of parsing of some pre-v3 style type directives and
roles and try to convert them to equivalent v3 directives/roles.
Set the new option :confval:`c_allow_pre_v3` to ``True`` to enable this.
The warnings printed from this functionality can be suppressed by setting
:confval:`c_warn_on_allowed_pre_v3`` to ``True``.
The functionality is immediately deprecated.
* #7999: C, add support for named variadic macro arguments.
* #8071: Allow to suppress "self referenced toctrees" warning
Bugs fixed
----------
* #7886: autodoc: TypeError is raised on mocking generic-typed classes
* #7935: autodoc: function signature is not shown when the function has a
parameter having ``inspect._empty`` as its default value
* #7901: autodoc: type annotations for overloaded functions are not resolved
* #904: autodoc: An instance attribute cause a crash of autofunction directive
* #1362: autodoc: ``private-members`` option does not work for class attributes
* #7983: autodoc: Generator type annotation is wrongly rendered in py36
* #8030: autodoc: An uninitialized annotated instance variable is not documented
when ``:inherited-members:`` option given
* #8032: autodoc: A type hint for the instance variable defined at parent class
is not shown in the document of the derived class
* #8041: autodoc: An annotated instance variable on super class is not
documented when derived class has other annotated instance variables
* #7839: autosummary: cannot handle umlauts in function names
* #7865: autosummary: Failed to extract summary line when abbreviations found
* #7866: autosummary: Failed to extract correct summary line when docstring
contains a hyperlink target
* #7469: autosummary: "Module attributes" header is not translatable
* #7940: apidoc: An extra newline is generated at the end of the rst file if a
module has submodules
* #4258: napoleon: decorated special methods are not shown
* #7799: napoleon: parameters are not escaped for combined params in numpydoc
* #7780: napoleon: multiple paramaters declaration in numpydoc was wrongly
recognized when napoleon_use_params=True
* #7715: LaTeX: ``numfig_secnum_depth > 1`` leads to wrong figure links
* #7846: html theme: XML-invalid files were generated
* #7894: gettext: Wrong source info is shown when using rst_epilog
* #7691: linkcheck: HEAD requests are not used for checking
* #4888: i18n: Failed to add an explicit title to ``:ref:`` role on translation
* #7928: py domain: failed to resolve a type annotation for the attribute
* #8008: py domain: failed to parse a type annotation containing ellipsis
* #7994: std domain: option directive does not generate old node_id compatible
with 2.x or older
* #7968: i18n: The content of ``math`` directive is interpreted as reST on
translation
* #7768: i18n: The ``root`` element for :confval:`figure_language_filename` is
not a path that user specifies in the document
* #7993: texinfo: TypeError is raised for nested object descriptions
* #7993: texinfo: a warning not supporting desc_signature_line node is shown
* #7869: :rst:role:`abbr` role without an explanation will show the explanation
from the previous abbr role
* #8048: graphviz: graphviz.css was copied on building non-HTML document
* C and C++, removed ``noindex`` directive option as it did
nothing.
* #7619: Duplicated node IDs are generated if node has multiple IDs
* #2050: Symbols sections are appeared twice in the index page
* #8017: Fix circular import in sphinx.addnodes
* #7986: CSS: make "highlight" selector more robust
* #7944: C++, parse non-type template parameters starting with
a dependent qualified name.
* C, don't deepcopy the entire symbol table and make a mess every time an
enumerator is handled.
Release 3.1.2 (released Jul 05, 2020)
=====================================
Incompatible changes
--------------------
* #7650: autodoc: the signature of base function will be shown for decorated
functions, not a signature of decorator
Bugs fixed
----------
* #7844: autodoc: Failed to detect module when relative module name given
* #7856: autodoc: AttributeError is raised when non-class object is given to
the autoclass directive
* #7850: autodoc: KeyError is raised for invalid mark up when autodoc_typehints
is 'description'
* #7812: autodoc: crashed if the target name matches to both an attribute and
module that are same name
* #7650: autodoc: function signature becomes ``(*args, **kwargs)`` if the
function is decorated by generic decorator
* #7812: autosummary: generates broken stub files if the target code contains
an attribute and module that are same name
* #7806: viewcode: Failed to resolve viewcode references on 3rd party builders
* #7838: html theme: List items have extra vertical space
* #7878: html theme: Undesired interaction between "overflow" and "float"
Release 3.1.1 (released Jun 14, 2020)
=====================================
Incompatible changes
--------------------
* #7808: napoleon: a type for attribute are represented as typed field
Features added
--------------
* #7807: autodoc: Show detailed warning when type_comment is mismatched with its
signature
Bugs fixed
----------
* #7808: autodoc: Warnings raised on variable and attribute type annotations
* #7802: autodoc: EOFError is raised on parallel build
* #7821: autodoc: TypeError is raised for overloaded C-ext function
* #7805: autodoc: an object which descriptors returns is unexpectedly documented
* #7807: autodoc: wrong signature is shown for the function using contextmanager
* #7812: autosummary: generates broken stub files if the target code contains
an attribute and module that are same name
* #7808: napoleon: Warnings raised on variable and attribute type annotations
* #7811: sphinx.util.inspect causes circular import problem
Release 3.1.0 (released Jun 08, 2020)
=====================================
Dependencies
------------
* #7746: mathjax: Update to 2.7.5
Incompatible changes
@ -51,6 +597,8 @@ Features added
builtin base classes
* #2106: autodoc: Support multiple signatures on docstring
* #4422: autodoc: Support GenericAlias in Python 3.7 or above
* #3610: autodoc: Support overloaded functions
* #7722: autodoc: Support TypeVar
* #7466: autosummary: headings in generated documents are not translated
* #7490: autosummary: Add ``:caption:`` option to autosummary directive to set a
caption to the toctree
@ -61,7 +609,8 @@ Features added
variables for custom templates
* #7530: html: Support nested <kbd> elements
* #7481: html theme: Add right margin to footnote/citation labels
* #7482: html theme: CSS spacing for code blocks with captions and line numbers
* #7482, #7717: html theme: CSS spacing for code blocks with captions and line
numbers
* #7443: html theme: Add new options :confval:`globaltoc_collapse` and
:confval:`globaltoc_includehidden` to control the behavior of globaltoc in
sidebar
@ -73,6 +622,8 @@ Features added
* #7542: html theme: Make admonition/topic/sidebar scrollable
* #7543: html theme: Add top and bottom margins to tables
* #7695: html theme: Add viewport meta tag for basic theme
* #7721: html theme: classic: default codetextcolor/codebgcolor doesn't override
Pygments
* C and C++: allow semicolon in the end of declarations.
* C++, parse parameterized noexcept specifiers.
* #7294: C++, parse expressions with user-defined literals.
@ -80,8 +631,13 @@ Features added
* #7143: py domain: Add ``:final:`` option to :rst:dir:`py:class:`,
:rst:dir:`py:exception:` and :rst:dir:`py:method:` directives
* #7596: py domain: Change a type annotation for variables to a hyperlink
* #7770: std domain: :rst:dir:`option` directive support arguments in the form
of ``foo[=bar]``
* #7582: napoleon: a type for attribute are represented like type annotation
* #7734: napoleon: overescaped trailing underscore on attribute
* #7247: linkcheck: Add :confval:`linkcheck_request_headers` to send custom HTTP
headers for specific host
* #7792: setuptools: Support ``--verbosity`` option
* #7683: Add ``allowed_exceptions`` parameter to ``Sphinx.emit()`` to allow
handlers to raise specified exceptions
* #7295: C++, parse (trailing) requires clauses.
@ -113,6 +669,7 @@ Bugs fixed
* #7668: autodoc: wrong retann value is passed to a handler of
autodoc-proccess-signature
* #7711: autodoc: fails with ValueError when processing numpy objects
* #7791: autodoc: TypeError is raised on documenting singledispatch function
* #7551: autosummary: a nested class is indexed as non-nested class
* #7661: autosummary: autosummary directive emits warnings twices if failed to
import the target module
@ -121,8 +678,12 @@ Bugs fixed
* #7671: autosummary: The location of import failure warning is missing
* #7535: sphinx-autogen: crashes when custom template uses inheritance
* #7536: sphinx-autogen: crashes when template uses i18n feature
* #7781: sphinx-build: Wrong error message when outdir is not directory
* #7653: sphinx-quickstart: Fix multiple directory creation for nested relpath
* #2785: html: Bad alignment of equation links
* #7718: html theme: some themes does not respect background color of Pygments
style (agogo, haiku, nature, pyramid, scrolls, sphinxdoc and traditional)
* #7544: html theme: inconsistent padding in admonitions
* #7581: napoleon: bad parsing of inline code in attribute docstrings
* #7628: imgconverter: runs imagemagick once unnecessary for builders not
supporting images
@ -130,7 +691,10 @@ Bugs fixed
* #7646: handle errors on event handlers
* #4187: LaTeX: EN DASH disappears from PDF bookmarks in Japanese documents
* #7701: LaTeX: Anonymous indirect hyperlink target causes duplicated labels
* #7723: LaTeX: pdflatex crashed when URL contains a single quote
* #7756: py domain: The default value for positional only argument is not shown
* #7760: coverage: Add :confval:`coverage_show_missing_items` to show coverage
result to console
* C++, fix rendering and xrefs in nested names explicitly starting
in global scope, e.g., ``::A::B``.
* C, fix rendering and xrefs in nested names explicitly starting
@ -138,30 +702,6 @@ Bugs fixed
* #7763: C and C++, don't crash during display stringification of unary
expressions and fold expressions.
Testing
--------
Release 3.0.5 (in development)
==============================
Dependencies
------------
Incompatible changes
--------------------
Deprecated
----------
Features added
--------------
Bugs fixed
----------
Testing
--------
Release 3.0.4 (released May 27, 2020)
=====================================
@ -470,7 +1010,7 @@ Release 2.4.1 (released Feb 11, 2020)
Bugs fixed
----------
* #7120: html: crashed when on scaling SVG images which have float dimentions
* #7120: html: crashed when on scaling SVG images which have float dimensions
* #7126: autodoc: TypeError: 'getset_descriptor' object is not iterable
Release 2.4.0 (released Feb 09, 2020)
@ -616,7 +1156,7 @@ Features added
* #6548: html: Use favicon for OpenSearch if available
* #6729: html theme: agogo theme now supports ``rightsidebar`` option
* #6780: Add PEP-561 Support
* #6762: latex: Allow to load additonal LaTeX packages via ``extrapackages`` key
* #6762: latex: Allow to load additional LaTeX packages via ``extrapackages`` key
of :confval:`latex_elements`
* #1331: Add new config variable: :confval:`user_agent`
* #6000: LaTeX: have backslash also be an inline literal word wrap break

View File

@ -8,10 +8,11 @@ reports/feature requests.
Our contributing guide can be found online at:
https://www.sphinx-doc.org/en/master/internals/contributing/
https://www.sphinx-doc.org/en/master/internals/contributing.html
You can also browse it from this repository from
``doc/internals/contributing/``
``doc/internals/contributing.rst``
Sphinx uses GitHub to host source code, track patches and bugs, and more.
Please make an effort to provide as much possible when filing bugs.
Please make an effort to provide as much detail as possible when filing
bugs.

View File

@ -230,6 +230,7 @@ Documentation using sphinx_rtd_theme
* `MyHDL <http://docs.myhdl.org/>`__
* `Nextflow <https://www.nextflow.io/docs/latest/index.html>`__
* `NICOS <https://forge.frm2.tum.de/nicos/doc/nicos-master/>`__ (customized)
* `OpenFAST <https://openfast.readthedocs.io/>`__
* `Pelican <http://docs.getpelican.com/>`__
* `picamera <https://picamera.readthedocs.io/>`__
* `Pillow <https://pillow.readthedocs.io/>`__
@ -317,6 +318,7 @@ Documentation using a custom theme or integrated in a website
* `Django <https://docs.djangoproject.com/>`__
* `Doctrine <https://www.doctrine-project.org/>`__
* `Enterprise Toolkit for Acrobat products <https://www.adobe.com/devnet-docs/acrobatetk/>`__
* `FreeFEM <https://doc.freefem.org/introduction/>`__
* `Gameduino <http://excamera.com/sphinx/gameduino/>`__
* `gensim <https://radimrehurek.com/gensim/>`__
* `GeoServer <http://docs.geoserver.org/>`__
@ -330,6 +332,7 @@ Documentation using a custom theme or integrated in a website
* `Lasso <http://lassoguide.com/>`__
* `Mako <http://docs.makotemplates.org/>`__
* `MirrorBrain <http://mirrorbrain.org/docs/>`__
* `Mitiq <https://mitiq.readthedocs.io/>`__
* `MongoDB <https://docs.mongodb.com/>`__
* `Music21 <https://web.mit.edu/music21/doc/>`__
* `MyHDL <http://docs.myhdl.org/>`__
@ -355,7 +358,7 @@ Documentation using a custom theme or integrated in a website
* `Roundup <http://www.roundup-tracker.org/>`__
* `SaltStack <https://docs.saltstack.com/>`__
* `scikit-learn <http://scikit-learn.org/stable/>`__
* `SciPy <https://docs.scipy.org/doc/scipy/refrence/>`__
* `SciPy <https://docs.scipy.org/doc/scipy/reference/>`__
* `Scrapy <https://doc.scrapy.org/>`__
* `Seaborn <https://seaborn.pydata.org/>`__
* `Selenium <https://docs.seleniumhq.org/docs/>`__
@ -382,6 +385,7 @@ Homepages and other non-documentation sites
* `Pylearn2 <http://www.deeplearning.net/software/pylearn2/>`__ (sphinxdoc, customized)
* `PyXLL <https://www.pyxll.com/>`__ (sphinx_bootstrap_theme, customized)
* `SciPy Cookbook <https://scipy-cookbook.readthedocs.io/>`__ (sphinx_rtd_theme)
* `Tech writer at work blog <https://blog.documatt.com/>`__ (custom theme)
* `The Wine Cellar Book <https://www.thewinecellarbook.com/doc/en/>`__ (sphinxdoc)
* `Thomas Cokelaer's Python, Sphinx and reStructuredText tutorials <https://thomas-cokelaer.info/tutorials/>`__ (standard)
* `UC Berkeley ME233 Advanced Control Systems II course <https://berkeley-me233.github.io/>`__ (sphinxdoc)

View File

@ -1,7 +1,7 @@
License for Sphinx
==================
Copyright (c) 2007-2019 by the Sphinx team (see AUTHORS file).
Copyright (c) 2007-2021 by the Sphinx team (see AUTHORS file).
All rights reserved.
Redistribution and use in source and binary forms, with or without

View File

@ -64,17 +64,13 @@ type-check:
doclinter:
python utils/doclinter.py CHANGES *.rst doc/
.PHONY: pylint
pylint:
@pylint --rcfile utils/pylintrc sphinx
.PHONY: test
test:
@$(PYTHON) -m pytest -v $(TEST)
@$(PYTHON) -X dev -m pytest -v $(TEST)
.PHONY: covertest
covertest:
@$(PYTHON) -m pytest -v --cov=sphinx --junitxml=.junit.xml $(TEST)
@$(PYTHON) -X dev -m pytest -v --cov=sphinx --junitxml=.junit.xml $(TEST)
.PHONY: build
build:
@ -83,6 +79,6 @@ build:
.PHONY: docs
docs:
ifndef target
$(info You need to give a provide a target variable, e.g. `make docs target=html`.)
$(info You need to provide a target variable, e.g. `make docs target=html`.)
endif
$(MAKE) -C doc $(target)

View File

@ -30,6 +30,10 @@
:target: https://opensource.org/licenses/BSD-3-Clause
:alt: BSD 3 Clause
.. image:: https://codetriage.com/sphinx-doc/sphinx/badges/users.svg
:target: https://codetriage.com/sphinx-doc/sphinx
:alt: Open Source Helpers badge
Sphinx is a tool that makes it easy to create intelligent and beautiful
documentation for Python projects (or other documents consisting of multiple
reStructuredText sources), written by Georg Brandl. It was originally created

View File

@ -13,3 +13,9 @@ texlive-anyfontsize [platform:rpm]
texlive-ctablestack [platform:rpm]
texlive-gnu-freefont [platform:rpm]
latexmk [platform:rpm]
texlive-latex-recommended [platform:dpkg]
texlive-fonts-recommended [platform:dpkg]
texlive-latex-extra [platform:dpkg]
texlive-luatex [platform:dpkg]
latexmk [platform:dpkg]

View File

@ -1,4 +1,6 @@
translation.png: translation.puml
plantuml -tpng $<
translation.svg: translation.puml
plantuml -tsvg $<
clean:
rm translation.svg
rm -f translation.png translation.svg

8
doc/_static/favicon.svg vendored Normal file
View File

@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<style>
@media (prefers-color-scheme: dark) {
svg { fill: white; }
}
</style>
<path d="m 67.780707,71.526216 c 0,-2.720856 0.735772,-7.633735 1.635035,-10.917507 2.076574,-7.582764 3.222746,-16.97568 2.071477,-16.97568 -0.485619,0 -3.994408,3.173002 -7.797313,7.051115 -14.448869,14.734603 -29.952812,23.068339 -42.915946,23.068339 -7.400211,0 -12.4298817,-1.871115 -17.2867007,-6.430912 -2.94436186,-2.764297 -3.47532146,-4.129685 -3.47532146,-8.936928 0,-4.94488 0.4862322,-6.108589 3.78321146,-9.054437 2.987989,-2.669773 4.875111,-3.380296 8.9779137,-3.380296 3.163221,0.711278 5.032659,0.664017 6.063532,1.917191 1.045041,1.231842 1.406892,5.262673 0.143323,7.623675 -0.674746,1.260763 -2.435471,2.043539 -4.5966,2.043539 -2.040303,0 -3.203991,-0.483702 -2.786976,-1.15844 1.31395,-2.126021 -0.560952,-3.566616 -2.9664067,-2.279256 -2.907025,1.555792 -2.957418,7.069066 -0.08839,9.665535 4.0345357,3.651203 15.1912207,5.023925 21.9019857,2.694828 7.250749,-2.516503 16.739014,-8.578986 24.30831,-15.531674 l 6.657407,-6.115083 -8.688303,-0.05007 C 43.622519,44.707714 37.702703,43.621524 18.54695,38.489741 12.175528,36.782852 6.0502733,35.306342 4.9352743,35.208608 3.6710803,35.097791 2.841723,34.067882 2.9080043,32.476074 3.0199286,29.788108 4.4800823,27.78768 6.2067673,27.033038 7.2437505,26.579828 14.43583,25.894406 22.0605,23.866486 c 29.699148,-7.899023 31.502043,-6.781254 51.28707,-1.772167 6.461504,1.635896 13.942408,3.414988 17.256961,3.474566 5.106245,0.09178 6.211825,0.514653 7.240255,2.76932 0.66758,1.46355 1.21378,2.858905 1.21378,3.10079 0,0.241884 -2.89333,1.764397 -6.429613,3.383363 -12.984983,5.944723 -17.083271,9.093943 -12.855172,15.130399 1.753219,2.503069 1.718037,2.768923 -0.57922,4.37799 -1.345193,0.942203 -2.457238,2.856456 -2.471232,4.253898 -0.03777,3.776976 -2.424786,11.884847 -5.893734,15.080164 l -3.048923,2.808424 z m 6.632814,-34.658372 c 5.169656,-1.440693 8.302047,-3.07045 14.72913,-6.500861 -5.292267,-1.548658 -18.570782,-3.724097 -18.570782,-3.724097 -9.796513,-1.964547 -8.76916,-1.865132 -9.21348,0.29669 -0.176673,0.859598 -0.702644,2.763948 -1.872329,4.596663 -2.251474,3.527711 -10.489307,4.271075 -15.214327,2.009703 -1.482367,-0.709454 -2.971272,-3.416276 -2.950606,-5.336922 0.02911,-2.705486 -1.505386,-3.336055 -2.486689,-2.975309 -0.796428,0.292781 -3.384665,0.330004 -9.071284,1.864262 -18.784765,5.068157 -21.3552119,4.487473 -9.110967,6.223299 1.472409,0.208739 9.252992,2.381926 13.052028,3.39412 9.318588,2.482796 11.064717,2.665087 23.125496,2.414247 8.385835,-0.174409 11.891174,-0.675356 17.58381,-2.261795 z M 3.0589449,14.916483 C 3.2921927,12.514245 3.424378,11.992797 10.100599,10.647894 13.924923,9.8774962 23.355266,7.3808108 31.056903,5.0997052 c 17.703937,-5.2436279 22.73392,-5.2565016 41.092202,-0.105175 7.923233,2.2232606 16.798382,4.047803 19.72254,4.054541 4.567242,0.01054 6.941892,2.0284768 6.941892,2.0284768 2.101843,4.825342 1.718463,5.158474 -6.484103,5.158474 -5.714193,0 -10.641875,-0.963081 -18.245438,-3.565943 C 68.300078,10.69012 60.060462,8.8316882 55.557963,8.4915615 47.342337,7.8709375 47.353713,7.8687835 21.963188,14.855617 17.503192,16.082896 11.34213,17.454164 8.2719268,17.902883 l -5.5821654,0.81585 z" />
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
doc/_static/translation.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -12,5 +12,5 @@ SphinxProject -r-> .rst
.pot -r-> .po : Pootle
.po -d-> .mo : msgfmt
.mo -l-> TranslatedBuild
.rst -d-> TranslatedBuild : "sphinx-buid -Dlanguage="
.rst -d-> TranslatedBuild : "sphinx-build -Dlanguage="
@enduml

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -239,7 +239,7 @@ div.footer a {
/* -- body styles ----------------------------------------------------------- */
p {
p {
margin: 0.8em 0 0.5em 0;
}

View File

@ -4,7 +4,6 @@ import re
import sphinx
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo',
'sphinx.ext.autosummary', 'sphinx.ext.extlinks',
'sphinx.ext.intersphinx',
@ -15,7 +14,7 @@ templates_path = ['_templates']
exclude_patterns = ['_build']
project = 'Sphinx'
copyright = '2007-2020, Georg Brandl and the Sphinx team'
copyright = '2007-2021, Georg Brandl and the Sphinx team'
version = sphinx.__display_version__
release = version
show_authors = True
@ -28,6 +27,7 @@ html_sidebars = {'index': ['indexsidebar.html', 'searchbox.html']}
html_additional_pages = {'index': 'index.html'}
html_use_opensearch = 'https://www.sphinx-doc.org/en/master'
html_baseurl = 'https://www.sphinx-doc.org/en/master/'
html_favicon = '_static/favicon.svg'
htmlhelp_basename = 'Sphinxdoc'
@ -110,9 +110,10 @@ texinfo_documents = [
1),
]
# We're not using intersphinx right now, but if we did, this would be part of
# the mapping:
intersphinx_mapping = {'python': ('https://docs.python.org/3/', None)}
intersphinx_mapping = {
'python': ('https://docs.python.org/3/', None),
'requests': ('https://requests.readthedocs.io/en/master', None),
}
# Sphinx document translation with sphinx gettext feature uses these settings:
locale_dirs = ['locale/']

View File

@ -10,7 +10,6 @@ Sphinx documentation contents
development/index
man/index
theming
templating
latex
extdev/index

View File

@ -0,0 +1,34 @@
Configuring builders
====================
Discover builders by entry point
--------------------------------
.. versionadded:: 1.6
:term:`builder` extensions can be discovered by means of `entry points`_ so
that they do not have to be listed in the :confval:`extensions` configuration
value.
Builder extensions should define an entry point in the ``sphinx.builders``
group. The name of the entry point needs to match your builder's
:attr:`~.Builder.name` attribute, which is the name passed to the
:option:`sphinx-build -b` option. The entry point value should equal the
dotted name of the extension module. Here is an example of how an entry point
for 'mybuilder' can be defined in the extension's ``setup.py``
.. code-block:: python
setup(
# ...
entry_points={
'sphinx.builders': [
'mybuilder = my.extension.module',
],
}
)
Note that it is still necessary to register the builder using
:meth:`~.Sphinx.add_builder` in the extension's :func:`setup` function.
.. _entry points: https://setuptools.readthedocs.io/en/latest/setuptools.html#dynamic-discovery-of-services-and-plugins

View File

@ -2,12 +2,22 @@
Extending Sphinx
================
This guide is aimed at those wishing to develop their own extensions for
Sphinx. Sphinx possesses significant extensibility capabilities including the
ability to hook into almost every point of the build process. If you simply
wish to use Sphinx with existing extensions, refer to :doc:`/usage/index`.
This guide is aimed at giving a quick introduction for those wishing to
develop their own extensions for Sphinx. Sphinx possesses significant
extensibility capabilities including the ability to hook into almost every
point of the build process. If you simply wish to use Sphinx with existing
extensions, refer to :doc:`/usage/index`. For a more detailed discussion of
the extension interface see :doc:`/extdev/index`.
.. toctree::
:maxdepth: 2
overview
tutorials/index
builders
.. toctree::
:caption: Theming
:maxdepth: 2
theming

View File

@ -0,0 +1,32 @@
Developing extensions overview
==============================
This page contains general information about developing Sphinx extensions.
Make an extension depend on another extension
---------------------------------------------
Sometimes your extension depends on the functionality of another
Sphinx extension. Most Sphinx extensions are activated in a
project's :file:`conf.py` file, but this is not available to you as an
extension developer.
.. module:: sphinx.application
:noindex:
To ensure that another extension is activated as a part of your own extension,
use the :meth:`Sphinx.setup_extension` method. This will
activate another extension at run-time, ensuring that you have access to its
functionality.
For example, the following code activates the ``recommonmark`` extension:
.. code-block:: python
def setup(app):
app.setup_extension("recommonmark")
.. note::
Since your extension will depend on another, make sure to include
it as a part of your extension's installation requirements.

336
doc/development/theming.rst Normal file
View File

@ -0,0 +1,336 @@
HTML theme development
======================
.. versionadded:: 0.6
.. note::
This document provides information about creating your own theme. If you
simply wish to use a pre-existing HTML themes, refer to
:doc:`/usage/theming`.
Sphinx supports changing the appearance of its HTML output via *themes*. A
theme is a collection of HTML templates, stylesheet(s) and other static files.
Additionally, it has a configuration file which specifies from which theme to
inherit, which highlighting style to use, and what options exist for customizing
the theme's look and feel.
Themes are meant to be project-unaware, so they can be used for different
projects without change.
.. note::
See :ref:`dev-extensions` for more information that may
be helpful in developing themes.
Creating themes
---------------
Themes take the form of either a directory or a zipfile (whose name is the
theme name), containing the following:
* A :file:`theme.conf` file.
* HTML templates, if needed.
* A ``static/`` directory containing any static files that will be copied to the
output static directory on build. These can be images, styles, script files.
The :file:`theme.conf` file is in INI format [1]_ (readable by the standard
Python :mod:`ConfigParser` module) and has the following structure:
.. sourcecode:: ini
[theme]
inherit = base theme
stylesheet = main CSS name
pygments_style = stylename
sidebars = localtoc.html, relations.html, sourcelink.html, searchbox.html
[options]
variable = default value
* The **inherit** setting gives the name of a "base theme", or ``none``. The
base theme will be used to locate missing templates (most themes will not have
to supply most templates if they use ``basic`` as the base theme), its options
will be inherited, and all of its static files will be used as well. If you
want to also inherit the stylesheet, include it via CSS' ``@import`` in your
own.
* The **stylesheet** setting gives the name of a CSS file which will be
referenced in the HTML header. If you need more than one CSS file, either
include one from the other via CSS' ``@import``, or use a custom HTML template
that adds ``<link rel="stylesheet">`` tags as necessary. Setting the
:confval:`html_style` config value will override this setting.
* The **pygments_style** setting gives the name of a Pygments style to use for
highlighting. This can be overridden by the user in the
:confval:`pygments_style` config value.
* The **pygments_dark_style** setting gives the name of a Pygments style to use
for highlighting when the CSS media query ``(prefers-color-scheme: dark)``
evaluates to true. It is injected into the page using
:meth:`~Sphinx.add_css_file()`.
* The **sidebars** setting gives the comma separated list of sidebar templates
for constructing sidebars. This can be overridden by the user in the
:confval:`html_sidebars` config value.
* The **options** section contains pairs of variable names and default values.
These options can be overridden by the user in :confval:`html_theme_options`
and are accessible from all templates as ``theme_<name>``.
.. versionadded:: 1.7
sidebar settings
.. _distribute-your-theme:
Distribute your theme as a Python package
-----------------------------------------
As a way to distribute your theme, you can use Python package. Python package
brings to users easy setting up ways.
To distribute your theme as a Python package, please define an entry point
called ``sphinx.html_themes`` in your ``setup.py`` file, and write a ``setup()``
function to register your themes using ``add_html_theme()`` API in it::
# 'setup.py'
setup(
...
entry_points = {
'sphinx.html_themes': [
'name_of_theme = your_package',
]
},
...
)
# 'your_package.py'
from os import path
def setup(app):
app.add_html_theme('name_of_theme', path.abspath(path.dirname(__file__)))
If your theme package contains two or more themes, please call
``add_html_theme()`` twice or more.
.. versionadded:: 1.2
'sphinx_themes' entry_points feature.
.. deprecated:: 1.6
``sphinx_themes`` entry_points has been deprecated.
.. versionadded:: 1.6
``sphinx.html_themes`` entry_points feature.
Templating
----------
The :doc:`guide to templating </templating>` is helpful if you want to write your
own templates. What is important to keep in mind is the order in which Sphinx
searches for templates:
* First, in the user's ``templates_path`` directories.
* Then, in the selected theme.
* Then, in its base theme, its base's base theme, etc.
When extending a template in the base theme with the same name, use the theme
name as an explicit directory: ``{% extends "basic/layout.html" %}``. From a
user ``templates_path`` template, you can still use the "exclamation mark"
syntax as described in the templating document.
.. _theming-static-templates:
Static templates
~~~~~~~~~~~~~~~~
Since theme options are meant for the user to configure a theme more easily,
without having to write a custom stylesheet, it is necessary to be able to
template static files as well as HTML files. Therefore, Sphinx supports
so-called "static templates", like this:
If the name of a file in the ``static/`` directory of a theme (or in the user's
static path, for that matter) ends with ``_t``, it will be processed by the
template engine. The ``_t`` will be left from the final file name. For
example, the *classic* theme has a file ``static/classic.css_t`` which uses
templating to put the color options into the stylesheet. When a documentation
is built with the classic theme, the output directory will contain a
``_static/classic.css`` file where all template tags have been processed.
Use custom page metadata in HTML templates
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Any key / value pairs in :doc:`field lists </usage/restructuredtext/field-lists>`
that are placed *before* the page's title will be available to the Jinja
template when building the page within the :data:`meta` attribute. For example,
if a page had the following text before its first title:
.. code-block:: rst
:mykey: My value
My first title
--------------
Then it could be accessed within a Jinja template like so:
.. code-block:: jinja
{%- if meta is mapping %}
{{ meta.get("mykey") }}
{%- endif %}
Note the check that ``meta`` is a dictionary ("mapping" in Jinja
terminology) to ensure that using it in this way is valid.
Defining custom template functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sometimes it is useful to define your own function in Python that you wish to
then use in a template. For example, if you'd like to insert a template value
with logic that depends on the user's configuration in the project, or if you'd
like to include non-trivial checks and provide friendly error messages for
incorrect configuration in the template.
To define your own template function, you'll need to define two functions
inside your module:
* A **page context event handler** (or **registration**) function. This is
connected to the :class:`.Sphinx` application via an event callback.
* A **template function** that you will use in your Jinja template.
First, define the registration function, which accepts the arguments for
:event:`html-page-context`.
Within the registration function, define the template function that you'd like to use
within Jinja. The template function should return a string or Python objects (lists,
dictionaries) with strings inside that Jinja uses in the templating process
.. note::
The template function will have access to all of the variables that
are passed to the registration function.
At the end of the registration function, add the template function to the
Sphinx application's context with ``context['template_func'] = template_func``.
Finally, in your extension's ``setup()`` function, add your registration
function as a callback for :event:`html-page-context`.
.. code-block:: python
# The registration function
def setup_my_func(app, pagename, templatename, context, doctree):
# The template function
def my_func(mystring):
return "Your string is %s" % mystring
# Add it to the page's context
context['my_func'] = my_func
# Your extension's setup function
def setup(app):
app.connect("html-page-context", setup_my_func)
Now, you will have access to this function in jinja like so:
.. code-block:: jinja
<div>
{{ my_func("some string") }}
</div>
Add your own static files to the build assets
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you are packaging your own build assets with an extension
(e.g., a CSS or JavaScript file), you need to ensure that they are placed
in the ``_static/`` folder of HTML outputs. To do so, you may copy them directly
into a build's ``_static/`` folder at build time, generally via an event hook.
Here is some sample code to accomplish this:
.. code-block:: python
def copy_custom_files(app, exc):
if app.builder.format == 'html' and not exc:
staticdir = path.join(app.builder.outdir, '_static')
copy_asset_file('path/to/myextension/_static/myjsfile.js', staticdir)
def setup(app):
app.connect('builder-inited', copy_custom_files)
Inject JavaScript based on user configuration
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If your extension makes use of JavaScript, it can be useful to allow users
to control its behavior using their Sphinx configuration. However, this can
be difficult to do if your JavaScript comes in the form of a static library
(which will not be built with Jinja).
There are two ways to inject variables into the JavaScript space based on user
configuration.
First, you may append ``_t`` to the end of any static files included with your
extension. This will cause Sphinx to process these files with the templating
engine, allowing you to embed variables and control behavior.
For example, the following JavaScript structure:
.. code-block:: bash
mymodule/
├── _static
│   └── myjsfile.js_t
└── mymodule.py
Will result in the following static file placed in your HTML's build output:
.. code-block:: bash
_build/
└── html
└── _static
   └── myjsfile.js
See :ref:`theming-static-templates` for more information.
Second, you may use the :meth:`Sphinx.add_js_file` method without pointing it
to a file. Normally, this method is used to insert a new JavaScript file
into your site. However, if you do *not* pass a file path, but instead pass
a string to the "body" argument, then this text will be inserted as JavaScript
into your site's head. This allows you to insert variables into your project's
JavaScript from Python.
For example, the following code will read in a user-configured value and then
insert this value as a JavaScript variable, which your extension's JavaScript
code may use:
.. code-block:: python
# This function reads in a variable and inserts it into JavaScript
def add_js_variable(app):
# This is a configuration that you've specified for users in `conf.py`
js_variable = app.config['my_javascript_variable']
js_text = "var my_variable = '%s';" % js_variable
app.add_js_file(None, body=js_text)
# We connect this function to the step after the builder is initialized
def setup(app):
# Tell Sphinx about this configuration variable
app.add_config_value('my_javascript_variable')
# Run the function after the builder is initialized
app.connect('builder-inited', add_js_variable)
As a result, in your theme you can use code that depends on the presence of
this variable. Users can control the variable's value by defining it in their
:file:`conf.py` file.
.. [1] It is not an executable Python file, as opposed to :file:`conf.py`,
because that would pose an unnecessary security risk if themes are
shared.

View File

@ -4,8 +4,7 @@ from docutils.parsers.rst import directives
from sphinx import addnodes
from sphinx.directives import ObjectDescription
from sphinx.domains import Domain
from sphinx.domains import Index
from sphinx.domains import Domain, Index
from sphinx.roles import XRefRole
from sphinx.util.nodes import make_refnode

View File

@ -61,6 +61,13 @@ def purge_todos(app, env, docname):
if todo['docname'] != docname]
def merge_todos(app, env, docnames, other):
if not hasattr(env, 'todo_all_todos'):
env.todo_all_todos = []
if hasattr(other, 'todo_all_todos'):
env.todo_all_todos.extend(other.todo_all_todos)
def process_todo_nodes(app, doctree, fromdocname):
if not app.config.todo_include_todos:
for node in doctree.traverse(todo):
@ -119,6 +126,7 @@ def setup(app):
app.add_directive('todolist', TodolistDirective)
app.connect('doctree-resolved', process_todo_nodes)
app.connect('env-purge-doc', purge_todos)
app.connect('env-merge-info', merge_todos)
return {
'version': '0.1',

View File

@ -1,8 +1,11 @@
.. _extension-tutorials-index:
Extension tutorials
===================
Refer to the following tutorials to get started with extension development.
.. toctree::
:caption: Directive tutorials
:maxdepth: 1

View File

@ -38,9 +38,10 @@ For that, we will need to add the following elements to Sphinx:
with the extension name, in order to stay unique) that controls whether todo
entries make it into the output.
* New event handlers: one for the :event:`doctree-resolved` event, to replace
the todo and todolist nodes, and one for :event:`env-purge-doc` (the reason
for that will be covered later).
* New event handlers: one for the :event:`doctree-resolved` event, to
replace the todo and todolist nodes, one for :event:`env-merge-info`
to merge intermediate results from parallel builds, and one for
:event:`env-purge-doc` (the reason for that will be covered later).
Prerequisites
@ -212,12 +213,23 @@ Here we clear out all todos whose docname matches the given one from the
``todo_all_todos`` list. If there are todos left in the document, they will be
added again during parsing.
The next handler, for the :event:`env-merge-info` event, is used
during parallel builds. As during parallel builds all threads have
their own ``env``, there's multiple ``todo_all_todos`` lists that need
to be merged:
.. literalinclude:: examples/todo.py
:language: python
:linenos:
:lines: 64-68
The other handler belongs to the :event:`doctree-resolved` event:
.. literalinclude:: examples/todo.py
:language: python
:linenos:
:lines: 64-103
:lines: 71-113
The :event:`doctree-resolved` event is emitted at the end of :ref:`phase 3
(resolving) <build-phases>` and allows custom resolving to be done. The handler
@ -230,7 +242,7 @@ where they come from. The list items are composed of the nodes from the
``todo`` entry and docutils nodes created on the fly: a paragraph for each
entry, containing text that gives the location, and a link (reference node
containing an italic node) with the backreference. The reference URI is built
by :meth:`sphinx.builders.Builder.get_relative_uri`` which creates a suitable
by :meth:`sphinx.builders.Builder.get_relative_uri` which creates a suitable
URI depending on the used builder, and appending the todo node's (the target's)
ID as the anchor name.
@ -245,7 +257,7 @@ the other parts of our extension. Let's look at our ``setup`` function:
.. literalinclude:: examples/todo.py
:language: python
:linenos:
:lines: 106-
:lines: 116-
The calls in this function refer to the classes and functions we added earlier.
What the individual calls do is the following:

View File

@ -25,75 +25,75 @@ package.
.. currentmodule:: sphinx.application
.. automethod:: Sphinx.setup_extension(name)
.. automethod:: Sphinx.setup_extension
.. automethod:: Sphinx.require_sphinx(version)
.. automethod:: Sphinx.require_sphinx
.. automethod:: Sphinx.connect(event, callback)
.. automethod:: Sphinx.connect
.. automethod:: Sphinx.disconnect(listener_id)
.. automethod:: Sphinx.disconnect
.. automethod:: Sphinx.add_builder(builder)
.. automethod:: Sphinx.add_builder
.. automethod:: Sphinx.add_config_value(name, default, rebuild)
.. automethod:: Sphinx.add_config_value
.. automethod:: Sphinx.add_event(name)
.. automethod:: Sphinx.add_event
.. automethod:: Sphinx.set_translator(name, translator_class)
.. automethod:: Sphinx.set_translator
.. automethod:: Sphinx.add_node(node, \*\*kwds)
.. automethod:: Sphinx.add_node
.. automethod:: Sphinx.add_enumerable_node(node, figtype, title_getter=None, \*\*kwds)
.. automethod:: Sphinx.add_enumerable_node
.. automethod:: Sphinx.add_directive(name, directiveclass)
.. automethod:: Sphinx.add_directive
.. automethod:: Sphinx.add_role(name, role)
.. automethod:: Sphinx.add_role
.. automethod:: Sphinx.add_generic_role(name, nodeclass)
.. automethod:: Sphinx.add_generic_role
.. automethod:: Sphinx.add_domain(domain)
.. automethod:: Sphinx.add_domain
.. automethod:: Sphinx.add_directive_to_domain(domain, name, directiveclass)
.. automethod:: Sphinx.add_directive_to_domain
.. automethod:: Sphinx.add_role_to_domain(domain, name, role)
.. automethod:: Sphinx.add_role_to_domain
.. automethod:: Sphinx.add_index_to_domain(domain, index)
.. automethod:: Sphinx.add_index_to_domain
.. automethod:: Sphinx.add_object_type(directivename, rolename, indextemplate='', parse_node=None, ref_nodeclass=None, objname='', doc_field_types=[])
.. automethod:: Sphinx.add_object_type
.. automethod:: Sphinx.add_crossref_type(directivename, rolename, indextemplate='', ref_nodeclass=None, objname='')
.. automethod:: Sphinx.add_crossref_type
.. automethod:: Sphinx.add_transform(transform)
.. automethod:: Sphinx.add_transform
.. automethod:: Sphinx.add_post_transform(transform)
.. automethod:: Sphinx.add_post_transform
.. automethod:: Sphinx.add_js_file(filename, **kwargs)
.. automethod:: Sphinx.add_js_file
.. automethod:: Sphinx.add_css_file(filename, **kwargs)
.. automethod:: Sphinx.add_css_file
.. automethod:: Sphinx.add_latex_package(packagename, options=None)
.. automethod:: Sphinx.add_latex_package
.. automethod:: Sphinx.add_lexer(alias, lexer)
.. automethod:: Sphinx.add_lexer
.. automethod:: Sphinx.add_autodocumenter(cls)
.. automethod:: Sphinx.add_autodocumenter
.. automethod:: Sphinx.add_autodoc_attrgetter(type, getter)
.. automethod:: Sphinx.add_autodoc_attrgetter
.. automethod:: Sphinx.add_search_language(cls)
.. automethod:: Sphinx.add_search_language
.. automethod:: Sphinx.add_source_suffix(suffix, filetype)
.. automethod:: Sphinx.add_source_suffix
.. automethod:: Sphinx.add_source_parser(parser)
.. automethod:: Sphinx.add_source_parser
.. automethod:: Sphinx.add_env_collector(collector)
.. automethod:: Sphinx.add_env_collector
.. automethod:: Sphinx.add_html_theme(name, theme_path)
.. automethod:: Sphinx.add_html_theme
.. automethod:: Sphinx.add_html_math_renderer(name, inline_renderers, block_renderers)
.. automethod:: Sphinx.add_html_math_renderer
.. automethod:: Sphinx.add_message_catalog(catalog, locale_dir)
.. automethod:: Sphinx.add_message_catalog
.. automethod:: Sphinx.is_parallel_allowed(typ)
.. automethod:: Sphinx.is_parallel_allowed
.. exception:: ExtensionError
@ -107,9 +107,9 @@ Emitting events
.. class:: Sphinx
:noindex:
.. automethod:: emit(event, \*arguments)
.. automethod:: emit
.. automethod:: emit_firstresult(event, \*arguments)
.. automethod:: emit_firstresult
Sphinx runtime information
@ -157,6 +157,42 @@ connect handlers to the events. Example:
app.connect('source-read', source_read_handler)
Below is an overview of each event that happens during a build. In the list
below, we include the event name, its callback parameters, and the input and output
type for that event::
1. event.config-inited(app,config)
2. event.builder-inited(app)
3. event.env-get-outdated(app, env, added, changed, removed)
4. event.env-before-read-docs(app, env, docnames)
for docname in docnames:
5. event.env-purge-doc(app, env, docname)
if doc changed and not removed:
6. source-read(app, docname, source)
7. run source parsers: text -> docutils.document (parsers can be added with the app.add_source_parser() API)
8. apply transforms (by priority): docutils.document -> docutils.document
- event.doctree-read(app, doctree) is called in the middly of transforms,
transforms come before/after this event depending on their priority.
9. (if running in parallel mode, for each process) event.env-merged-info(app, env, docnames, other)
10. event.env-updated(app, env)
11. event.env-get-updated(app, env)
12. event.env-check-consistency(app, env)
# The updated-docs list can be builder dependent, but generally includes all new/changed documents,
# plus any output from `env-get-updated`, and then all "parent" documents in the ToC tree
# For builders that output a single page, they are first joined into a single doctree before post-transforms/doctree-resolved
for docname in updated-docs:
13. apply post-transforms (by priority): docutils.document -> docutils.document
14. event.doctree-resolved(app, doctree, docname)
- (for any reference node that fails to resolve) event.missing-reference(env, node, contnode)
- (for any reference node that fails to resolve) event.warn-missing-reference(domain, node)
15. Generate output files
16. event.build-finished(app, exception)
Here is a more detailed list of these events.
.. event:: builder-inited (app)
Emitted when the builder object has been created. It is available as
@ -249,6 +285,14 @@ connect handlers to the events. Example:
.. versionadded:: 0.5
.. event:: warn-missing-reference (app, domain, node)
Emitted when a cross-reference to an object cannot be resolved even after
:event:`missing-reference`. If the event handler can emit warnings for
the missing reference, it should return ``True``.
.. versionadded:: 3.4
.. event:: doctree-resolved (app, doctree, docname)
Emitted when a doctree has been "resolved" by the environment, that is, all
@ -325,6 +369,9 @@ connect handlers to the events. Example:
You can return a string from the handler, it will then replace
``'page.html'`` as the HTML template for this page.
.. note:: You can install JS/CSS files for the specific page via
:meth:`Sphinx.add_js_file` and :meth:`Sphinx.add_css_file` since v3.5.0.
.. versionadded:: 0.4
.. versionchanged:: 1.3

View File

@ -26,6 +26,167 @@ The following is a list of deprecated interfaces.
- (will be) Removed
- Alternatives
* - pending_xref node for viewcode extension
- 3.5
- 5.0
- ``sphinx.ext.viewcode.viewcode_anchor``
* - ``sphinx.builders.linkcheck.CheckExternalLinksBuilder.broken``
- 3.5
- 5.0
- N/A
* - ``sphinx.builders.linkcheck.CheckExternalLinksBuilder.good``
- 3.5
- 5.0
- N/A
* - ``sphinx.builders.linkcheck.CheckExternalLinksBuilder.redirected``
- 3.5
- 5.0
- N/A
* - ``sphinx.builders.linkcheck.node_line_or_0()``
- 3.5
- 5.0
- ``sphinx.util.nodes.get_node_line()``
* - ``sphinx.ext.autodoc.AttributeDocumenter.isinstanceattribute()``
- 3.5
- 5.0
- N/A
* - ``sphinx.ext.autodoc.importer.get_module_members()``
- 3.5
- 5.0
- ``sphinx.ext.autodoc.ModuleDocumenter.get_module_members()``
* - ``sphinx.ext.autosummary.generate._simple_info()``
- 3.5
- 5.0
- :ref:`logging-api`
* - ``sphinx.ext.autosummary.generate._simple_warn()``
- 3.5
- 5.0
- :ref:`logging-api`
* - ``sphinx.writers.html.HTMLTranslator.permalink_text``
- 3.5
- 5.0
- :confval:`html_permalinks_icon`
* - ``sphinx.writers.html5.HTML5Translator.permalink_text``
- 3.5
- 5.0
- :confval:`html_permalinks_icon`
* - The ``follow_wrapped`` argument of ``sphinx.util.inspect.signature()``
- 3.4
- 5.0
- N/A
* - The ``no_docstring`` argument of
``sphinx.ext.autodoc.Documenter.add_content()``
- 3.4
- 5.0
- ``sphinx.ext.autodoc.Documenter.get_doc()``
* - ``sphinx.ext.autodoc.Documenter.get_object_members()``
- 3.4
- 6.0
- ``sphinx.ext.autodoc.ClassDocumenter.get_object_members()``
* - ``sphinx.ext.autodoc.DataDeclarationDocumenter``
- 3.4
- 5.0
- ``sphinx.ext.autodoc.DataDocumenter``
* - ``sphinx.ext.autodoc.GenericAliasDocumenter``
- 3.4
- 5.0
- ``sphinx.ext.autodoc.DataDocumenter``
* - ``sphinx.ext.autodoc.InstanceAttributeDocumenter``
- 3.4
- 5.0
- ``sphinx.ext.autodoc.AttributeDocumenter``
* - ``sphinx.ext.autodoc.SlotsAttributeDocumenter``
- 3.4
- 5.0
- ``sphinx.ext.autodoc.AttributeDocumenter``
* - ``sphinx.ext.autodoc.TypeVarDocumenter``
- 3.4
- 5.0
- ``sphinx.ext.autodoc.DataDocumenter``
* - ``sphinx.ext.autodoc.directive.DocumenterBridge.reporter``
- 3.5
- 5.0
- ``sphinx.util.logging``
* - ``sphinx.ext.autodoc.importer._getannotations()``
- 3.4
- 4.0
- ``sphinx.util.inspect.getannotations()``
* - ``sphinx.ext.autodoc.importer._getmro()``
- 3.4
- 4.0
- ``sphinx.util.inspect.getmro()``
* - ``sphinx.pycode.ModuleAnalyzer.parse()``
- 3.4
- 5.0
- ``sphinx.pycode.ModuleAnalyzer.analyze()``
* - ``sphinx.util.osutil.movefile()``
- 3.4
- 5.0
- ``os.replace()``
* - ``sphinx.util.requests.is_ssl_error()``
- 3.4
- 5.0
- N/A
* - ``sphinx.builders.latex.LaTeXBuilder.usepackages``
- 3.3
- 5.0
- N/A
* - ``sphinx.builders.latex.LaTeXBuilder.usepackages_afger_hyperref``
- 3.3
- 5.0
- N/A
* - ``sphinx.ext.autodoc.SingledispatchFunctionDocumenter``
- 3.3
- 5.0
- ``sphinx.ext.autodoc.FunctionDocumenter``
* - ``sphinx.ext.autodoc.SingledispatchMethodDocumenter``
- 3.3
- 5.0
- ``sphinx.ext.autodoc.MethodDocumenter``
* - ``sphinx.ext.autodoc.members_set_option()``
- 3.2
- 5.0
- N/A
* - ``sphinx.ext.autodoc.merge_special_members_option()``
- 3.2
- 5.0
- ``sphinx.ext.autodoc.merge_members_option()``
* - ``sphinx.writers.texinfo.TexinfoWriter.desc``
- 3.2
- 5.0
- ``sphinx.writers.texinfo.TexinfoWriter.descs``
* - The first argument for
``sphinx.ext.autosummary.generate.AutosummaryRenderer`` has been changed
to Sphinx object

View File

@ -1,7 +1,7 @@
.. _domain-api:
Domain API
----------
==========
.. module:: sphinx.domains
@ -12,3 +12,16 @@ Domain API
.. autoclass:: Index
:members:
Python Domain
-------------
.. module:: sphinx.domains.python
.. autoclass:: PythonDomain
.. autoattribute:: objects
.. autoattribute:: modules
.. automethod:: note_object
.. automethod:: note_module

View File

@ -3,54 +3,41 @@
Developing extensions for Sphinx
================================
Since many projects will need special features in their documentation, Sphinx is
designed to be extensible on several levels.
Since many projects will need special features in their documentation, Sphinx
is designed to be extensible on several levels.
This is what you can do in an extension: First, you can add new
:term:`builder`\s to support new output formats or actions on the parsed
documents. Then, it is possible to register custom reStructuredText roles and
directives, extending the markup. And finally, there are so-called "hook
points" at strategic places throughout the build process, where an extension can
register a hook and run specialized code.
Here are a few things you can do in an extension:
An extension is simply a Python module. When an extension is loaded, Sphinx
imports this module and executes its ``setup()`` function, which in turn
notifies Sphinx of everything the extension offers -- see the extension tutorial
for examples.
* Add new :term:`builder`\s to support new output formats or actions on the
parsed documents.
* Register custom reStructuredText roles and directives, extending the markup
using the :doc:`markupapi`.
* Add custom code to so-called "hook points" at strategic places throughout the
build process, allowing you to register a hook and run specialized code.
For example, see the :ref:`events`.
The configuration file itself can be treated as an extension if it contains a
``setup()`` function. All other extensions to load must be listed in the
:confval:`extensions` configuration value.
An extension is simply a Python module with a ``setup()`` function. A user
activates the extension by placing the extension's module name
(or a sub-module) in their :confval:`extensions` configuration value.
Discovery of builders by entry point
------------------------------------
When :program:`sphinx-build` is executed, Sphinx will attempt to import each
module that is listed, and execute ``yourmodule.setup(app)``. This
function is used to prepare the extension (e.g., by executing Python code),
linking resources that Sphinx uses in the build process (like CSS or HTML
files), and notifying Sphinx of everything the extension offers (such
as directive or role definitions). The ``app`` argument is an instance of
:class:`.Sphinx` and gives you control over most aspects of the Sphinx build.
.. versionadded:: 1.6
.. note::
:term:`builder` extensions can be discovered by means of `entry points`_ so
that they do not have to be listed in the :confval:`extensions` configuration
value.
The configuration file itself can be treated as an extension if it
contains a ``setup()`` function. All other extensions to load must be
listed in the :confval:`extensions` configuration value.
Builder extensions should define an entry point in the ``sphinx.builders``
group. The name of the entry point needs to match your builder's
:attr:`~.Builder.name` attribute, which is the name passed to the
:option:`sphinx-build -b` option. The entry point value should equal the
dotted name of the extension module. Here is an example of how an entry point
for 'mybuilder' can be defined in the extension's ``setup.py``::
setup(
# ...
entry_points={
'sphinx.builders': [
'mybuilder = my.extension.module',
],
}
)
Note that it is still necessary to register the builder using
:meth:`~.Sphinx.add_builder` in the extension's :func:`setup` function.
.. _entry points: https://setuptools.readthedocs.io/en/latest/setuptools.html#dynamic-discovery-of-services-and-plugins
The rest of this page describes some high-level aspects of developing
extensions and various parts of Sphinx's behavior that you can control.
For some examples of how extensions can be built and used to control different
parts of Sphinx, see the :ref:`extension-tutorials-index`.
.. _important-objects:
@ -192,6 +179,11 @@ as metadata of the extension. Metadata keys currently recognized are:
APIs used for writing extensions
--------------------------------
These sections provide a more complete description of the tools at your
disposal when developing Sphinx extensions. Some are core to Sphinx
(such as the :doc:`appapi`) while others trigger specific behavior
(such as the :doc:`i18n`)
.. toctree::
:maxdepth: 2

View File

@ -9,8 +9,8 @@ Glossary
A class (inheriting from :class:`~sphinx.builders.Builder`) that takes
parsed documents and performs an action on them. Normally, builders
translate the documents to an output format, but it is also possible to
use the builder builders that e.g. check for broken links in the
documentation, or build coverage information.
use builders that e.g. check for broken links in the documentation, or
build coverage information.
See :doc:`/usage/builders/index` for an overview over Sphinx's built-in
builders.

View File

@ -12,6 +12,9 @@ Getting help
The Sphinx community maintains a number of mailing lists and IRC channels.
Stack Overflow with tag `python-sphinx`_
Questions and answers about use and development.
sphinx-users <sphinx-users@googlegroups.com>
Mailing list for user support.
@ -21,6 +24,7 @@ sphinx-dev <sphinx-dev@googlegroups.com>
#sphinx-doc on irc.freenode.net
IRC channel for development questions and user support.
.. _python-sphinx: https://stackoverflow.com/questions/tagged/python-sphinx
Bug Reports and Feature Requests
--------------------------------
@ -134,10 +138,7 @@ Coding style
Please follow these guidelines when writing code for Sphinx:
* Try to use the same code style as used in the rest of the project. See the
`Pocoo Styleguide`__ for more information.
__ http://flask.pocoo.org/docs/styleguide/
* Try to use the same code style as used in the rest of the project.
* For non-trivial changes, please update the :file:`CHANGES` file. If your
changes alter existing behavior, please document this.
@ -268,9 +269,9 @@ identifier and put ``sphinx.po`` in there. Don't forget to update the possible
values for :confval:`language` in ``doc/usage/configuration.rst``.
The Sphinx core messages can also be translated on `Transifex
<https://www.transifex.com/sphinx-doc/>`_. There ``tx`` client tool, which is
provided by the ``transifex_client`` Python package, can be used to pull
translations in ``.po`` format from Transifex. To do this, go to
<https://www.transifex.com/sphinx-doc/sphinx-1/>`_. There ``tx`` client tool,
which is provided by the ``transifex_client`` Python package, can be used to
pull translations in ``.po`` format from Transifex. To do this, go to
``sphinx/locale`` and then run ``tx pull -f -l LANG`` where ``LANG`` is an
existing language identifier. It is good practice to run ``python setup.py
update_catalog`` afterwards to make sure the ``.po`` file has the canonical

View File

@ -95,6 +95,12 @@ Keys that you may want to override include:
A string which will be positioned early in the preamble, designed to
contain ``\\PassOptionsToPackage{options}{foo}`` commands.
.. hint::
It may be also used for loading LaTeX packages very early in the
preamble. For example package ``fancybox`` is incompatible with
being loaded via the ``'preamble'`` key, it must be loaded earlier.
Default: ``''``
.. versionadded:: 1.4
@ -195,8 +201,8 @@ Keys that you may want to override include:
"Bjornstrup". You can also set this to ``''`` to disable fncychap.
Default: ``'\\usepackage[Bjarne]{fncychap}'`` for English documents,
``'\\usepackage[Sonny]{fncychap}'`` for internationalized documents, and
``''`` for Japanese documents.
``'\\usepackage[Sonny]{fncychap}'`` for internationalized documents, and
``''`` for Japanese documents.
``'preamble'``
Additional preamble content. One may move all needed macros into some file
@ -300,7 +306,7 @@ Keys that don't need to be overridden unless in special cases are:
"inputenc" package inclusion.
Default: ``'\\usepackage[utf8]{inputenc}'`` when using pdflatex, else
``''``
``''``
.. versionchanged:: 1.4.3
Previously ``'\\usepackage[utf8]{inputenc}'`` was used for all
@ -389,7 +395,7 @@ Keys that don't need to be overridden unless in special cases are:
key is ignored.
Default: ``'\\usepackage{textalpha}'`` or ``''`` if ``fontenc`` does not
include the ``LGR`` option.
include the ``LGR`` option.
.. versionadded:: 2.0
@ -407,7 +413,7 @@ Keys that don't need to be overridden unless in special cases are:
<latexsphinxsetup>`.
Default: ``'\\usepackage{geometry}'`` (or
``'\\usepackage[dvipdfm]{geometry}'`` for Japanese documents)
``'\\usepackage[dvipdfm]{geometry}'`` for Japanese documents)
.. versionadded:: 1.5
@ -784,14 +790,14 @@ macros may be significant.
|warningbdcolors|
The colour for the admonition frame.
Default: ``{rgb}{0,0,0}`` (black)
Default: ``{rgb}{0,0,0}`` (black)
.. only:: latex
|wgbdcolorslatex|
The colour for the admonition frame.
Default: ``{rgb}{0,0,0}`` (black)
Default: ``{rgb}{0,0,0}`` (black)
|warningbgcolors|
The background colours for the respective admonitions.

View File

@ -20,7 +20,7 @@ Options
.. option:: -q, --quiet
Quiet mode that will skip interactive wizard to specify options.
Quiet mode that skips the interactive wizard for specifying options.
This option requires `-p`, `-a` and `-v` options.
.. option:: -h, --help, --version
@ -33,6 +33,10 @@ Options
If specified, separate source and build directories.
.. option:: --no-sep
If specified, create build directroy under source directroy.
.. option:: --dot=DOT
Inside the root directory, two more directories will be created;

View File

@ -7,7 +7,7 @@ Templating
==========
Sphinx uses the `Jinja <http://jinja.pocoo.org>`_ templating engine for its HTML
templates. Jinja is a text-based engine, and inspired by Django templates, so
templates. Jinja is a text-based engine, inspired by Django templates, so
anyone having used Django will already be familiar with it. It also has
excellent documentation for those who need to make themselves familiar with it.

View File

@ -1,159 +0,0 @@
.. highlight:: python
HTML theming support
====================
.. versionadded:: 0.6
.. note::
This document provides information about creating your own theme. If you
simply wish to use a pre-existing HTML themes, refer to
:doc:`/usage/theming`.
Sphinx supports changing the appearance of its HTML output via *themes*. A
theme is a collection of HTML templates, stylesheet(s) and other static files.
Additionally, it has a configuration file which specifies from which theme to
inherit, which highlighting style to use, and what options exist for customizing
the theme's look and feel.
Themes are meant to be project-unaware, so they can be used for different
projects without change.
Creating themes
---------------
Themes take the form of either a directory or a zipfile (whose name is the
theme name), containing the following:
* A :file:`theme.conf` file.
* HTML templates, if needed.
* A ``static/`` directory containing any static files that will be copied to the
output static directory on build. These can be images, styles, script files.
The :file:`theme.conf` file is in INI format [1]_ (readable by the standard
Python :mod:`ConfigParser` module) and has the following structure:
.. sourcecode:: ini
[theme]
inherit = base theme
stylesheet = main CSS name
pygments_style = stylename
sidebars = localtoc.html, relations.html, sourcelink.html, searchbox.html
[options]
variable = default value
* The **inherit** setting gives the name of a "base theme", or ``none``. The
base theme will be used to locate missing templates (most themes will not have
to supply most templates if they use ``basic`` as the base theme), its options
will be inherited, and all of its static files will be used as well. If you
want to also inherit the stylesheet, include it via CSS' ``@import`` in your
own.
* The **stylesheet** setting gives the name of a CSS file which will be
referenced in the HTML header. If you need more than one CSS file, either
include one from the other via CSS' ``@import``, or use a custom HTML template
that adds ``<link rel="stylesheet">`` tags as necessary. Setting the
:confval:`html_style` config value will override this setting.
* The **pygments_style** setting gives the name of a Pygments style to use for
highlighting. This can be overridden by the user in the
:confval:`pygments_style` config value.
* The **pygments_dark_style** setting gives the name of a Pygments style to use
for highlighting when the CSS media query ``(prefers-color-scheme: dark)``
evaluates to true. It is injected into the page using
:meth:`~Sphinx.add_css_file()`.
* The **sidebars** setting gives the comma separated list of sidebar templates
for constructing sidebars. This can be overridden by the user in the
:confval:`html_sidebars` config value.
* The **options** section contains pairs of variable names and default values.
These options can be overridden by the user in :confval:`html_theme_options`
and are accessible from all templates as ``theme_<name>``.
.. versionadded:: 1.7
sidebar settings
.. _distribute-your-theme:
Distribute your theme as a Python package
-----------------------------------------
As a way to distribute your theme, you can use Python package. Python package
brings to users easy setting up ways.
To distribute your theme as a Python package, please define an entry point
called ``sphinx.html_themes`` in your ``setup.py`` file, and write a ``setup()``
function to register your themes using ``add_html_theme()`` API in it::
# 'setup.py'
setup(
...
entry_points = {
'sphinx.html_themes': [
'name_of_theme = your_package',
]
},
...
)
# 'your_package.py'
from os import path
def setup(app):
app.add_html_theme('name_of_theme', path.abspath(path.dirname(__file__)))
If your theme package contains two or more themes, please call
``add_html_theme()`` twice or more.
.. versionadded:: 1.2
'sphinx_themes' entry_points feature.
.. deprecated:: 1.6
``sphinx_themes`` entry_points has been deprecated.
.. versionadded:: 1.6
``sphinx.html_themes`` entry_points feature.
Templating
----------
The :doc:`guide to templating <templating>` is helpful if you want to write your
own templates. What is important to keep in mind is the order in which Sphinx
searches for templates:
* First, in the user's ``templates_path`` directories.
* Then, in the selected theme.
* Then, in its base theme, its base's base theme, etc.
When extending a template in the base theme with the same name, use the theme
name as an explicit directory: ``{% extends "basic/layout.html" %}``. From a
user ``templates_path`` template, you can still use the "exclamation mark"
syntax as described in the templating document.
Static templates
~~~~~~~~~~~~~~~~
Since theme options are meant for the user to configure a theme more easily,
without having to write a custom stylesheet, it is necessary to be able to
template static files as well as HTML files. Therefore, Sphinx supports
so-called "static templates", like this:
If the name of a file in the ``static/`` directory of a theme (or in the user's
static path, for that matter) ends with ``_t``, it will be processed by the
template engine. The ``_t`` will be left from the final file name. For
example, the *classic* theme has a file ``static/classic.css_t`` which uses
templating to put the color options into the stylesheet. When a documentation
is built with the classic theme, the output directory will contain a
``_static/classic.css`` file where all template tags have been processed.
.. [1] It is not an executable Python file, as opposed to :file:`conf.py`,
because that would pose an unnecessary security risk if themes are
shared.

View File

@ -6,10 +6,10 @@ Internationalization
.. versionadded:: 1.1
Complementary to translations provided for Sphinx-generated messages such as
navigation bars, Sphinx provides mechanisms facilitating *document* translations
in itself. See the :ref:`intl-options` for details on configuration.
navigation bars, Sphinx provides mechanisms facilitating the translation of
*documents*. See the :ref:`intl-options` for details on configuration.
.. figure:: /_static/translation.svg
.. figure:: /_static/translation.*
:width: 100%
Workflow visualization of translations in Sphinx. (The figure is created by

View File

@ -442,6 +442,10 @@ name is ``rinoh``. Refer to the `rinohtype manual`_ for details.
Since Sphinx-1.5, the linkcheck builder comes to use requests module.
.. versionchanged:: 3.4
The linkcheck builder retries links when servers apply rate limits.
.. module:: sphinx.builders.xml
.. class:: XMLBuilder

View File

@ -70,9 +70,14 @@ Project information
The author name(s) of the document. The default value is ``'unknown'``.
.. confval:: copyright
.. confval:: project_copyright
A copyright statement in the style ``'2008, Author Name'``.
.. versionchanged:: 3.5
As an alias, ``project_copyright`` is also allowed.
.. confval:: version
The major project version, used as the replacement for ``|version|``. For
@ -316,6 +321,7 @@ General configuration
* ``toc.circular``
* ``toc.secnum``
* ``epub.unknown_project_files``
* ``epub.duplicated_toc_entry``
* ``autosectionlabel.*``
You can choose from these types.
@ -340,6 +346,10 @@ General configuration
Added ``autosectionlabel.*``
.. versionchanged:: 3.3.0
Added ``epub.duplicated_toc_entry``
.. confval:: needs_sphinx
If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will
@ -551,7 +561,7 @@ General configuration
* Otherwise, the current time is formatted using :func:`time.strftime` and
the format given in :confval:`today_fmt`.
The default is now :confval:`today` and a :confval:`today_fmt` of ``'%B %d,
The default is now :confval:`today` and a :confval:`today_fmt` of ``'%b %d,
%Y'`` (or, if translation is enabled with :confval:`language`, an equivalent
format for the selected locale).
@ -572,12 +582,27 @@ General configuration
.. confval:: highlight_options
A dictionary of options that modify how the lexer specified by
:confval:`highlight_language` generates highlighted source code. These are
lexer-specific; for the options understood by each, see the
`Pygments documentation <https://pygments.org/docs/lexers>`_.
A dictionary that maps language names to options for the lexer modules of
Pygments. These are lexer-specific; for the options understood by each,
see the `Pygments documentation <https://pygments.org/docs/lexers>`_.
Example::
highlight_options = {
'default': {'stripall': True},
'php': {'startinline': True},
}
A single dictionary of options are also allowed. Then it is recognized
as options to the lexer specified by :confval:`highlight_language`::
# configuration for the ``highlight_language``
highlight_options = {'stripall': True}
.. versionadded:: 1.3
.. versionchanged:: 3.5
Allow to configure highlight options for multiple languages
.. confval:: pygments_style
@ -660,10 +685,11 @@ documentation on :ref:`intl` for details.
generated by Sphinx will be in that language. Also, Sphinx will try to
substitute individual paragraphs from your documents with the translation
sets obtained from :confval:`locale_dirs`. Sphinx will search
language-specific figures named by `figure_language_filename` and substitute
them for original figures. In the LaTeX builder, a suitable language will
be selected as an option for the *Babel* package. Default is ``None``,
which means that no translation will be done.
language-specific figures named by :confval:`figure_language_filename`
(e.g. the German version of ``myfigure.png`` will be ``myfigure.de.png``
by default setting) and substitute them for original figures. In the LaTeX
builder, a suitable language will be selected as an option for the *Babel*
package. Default is ``None``, which means that no translation will be done.
.. versionadded:: 0.5
@ -755,9 +781,15 @@ documentation on :ref:`intl` for details.
If true, a document's text domain is its docname if it is a top-level
project file and its very base directory otherwise.
If set to string, all document's text domain is this string, making all
documents use single text domain.
By default, the document ``markup/code.rst`` ends up in the ``markup`` text
domain. With this option set to ``False``, it is ``markup/code``.
.. versionchanged:: 3.3
The string value is now accepted.
.. confval:: gettext_uuid
If true, Sphinx generates uuid information for version tracking in message
@ -820,6 +852,8 @@ documentation on :ref:`intl` for details.
extension, e.g. ``dirname/filename``
* ``{path}`` - the directory path component of the filename, with a trailing
slash if non-empty, e.g. ``dirname/``
* ``{docpath}`` - the directory path component for the current document, with
a trailing slash if non-empty.
* ``{basename}`` - the filename without the directory path or file extension
components, e.g. ``filename``
* ``{ext}`` - the file extension, e.g. ``.png``
@ -833,6 +867,9 @@ documentation on :ref:`intl` for details.
.. versionchanged:: 1.5
Added ``{path}`` and ``{basename}`` tokens.
.. versionchanged:: 3.2
Added ``{docpath}`` token.
.. _math-options:
@ -912,7 +949,7 @@ that use Sphinx's HTMLWriter class.
.. confval:: html_short_title
A shorter "title" for the HTML docs. This is used in for links in the
A shorter "title" for the HTML docs. This is used for links in the
header and in the HTML Help docs. If not given, it defaults to the value of
:confval:`html_title`.
@ -920,11 +957,23 @@ that use Sphinx's HTMLWriter class.
.. confval:: html_baseurl
The URL which points to the root of the HTML documentation. It is used to
indicate the location of document like ``canonical_url``.
The base URL which points to the root of the HTML documentation. It is used
to indicate the location of document using `The Canonical Link Relation`_.
Default: ``''``.
.. _The Canonical Link Relation: https://tools.ietf.org/html/rfc6596
.. versionadded:: 1.8
.. confval:: html_codeblock_linenos_style
The style of line numbers for code-blocks.
* ``'table'`` -- display line numbers using ``<table>`` tag (default)
* ``'inline'`` -- display line numbers using ``<span>`` tag
.. versionadded:: 3.2
.. confval:: html_context
A dictionary of values to pass into the template engine's context for all
@ -970,7 +1019,14 @@ that use Sphinx's HTMLWriter class.
'https://example.com/css/custom.css',
('print.css', {'media': 'print'})]
As a special attribute, *priority* can be set as an integer to load the CSS
file earlier or lazier step. For more information, refer
:meth:`Sphinx.add_css_files()`.
.. versionadded:: 1.8
.. versionchanged:: 3.5
Support priority attribute
.. confval:: html_js_files
@ -986,7 +1042,14 @@ that use Sphinx's HTMLWriter class.
'https://example.com/scripts/custom.js',
('custom.js', {'async': 'async'})]
As a special attribute, *priority* can be set as an integer to load the CSS
file earlier or lazier step. For more information, refer
:meth:`Sphinx.add_css_files()`.
.. versionadded:: 1.8
.. versionchanged:: 3.5
Support priority attribute
.. confval:: html_static_path
@ -1070,6 +1133,23 @@ that use Sphinx's HTMLWriter class.
This can now be a string to select the actual text of the link.
Previously, only boolean values were accepted.
.. deprecated:: 3.5
This has been replaced by :confval:`html_permalinks`
.. confval:: html_permalinks
If true, Sphinx will add "permalinks" for each heading and description
environment. Default: ``True``.
.. versionadded:: 3.5
.. confval:: html_permalinks_icon
A text for permalinks for each heading and description environment. HTML
tags are allowed. Default: a paragraph sign; ````
.. versionadded:: 3.5
.. confval:: html_sidebars
Custom sidebar templates, must be a dictionary that maps document names to
@ -2224,6 +2304,12 @@ These options influence manual page output.
.. versionadded:: 1.1
.. confval:: man_make_section_directory
If true, make a section directory on build man page. Default is False.
.. versionadded:: 3.3
.. _texinfo-options:
@ -2390,6 +2476,32 @@ Options for the linkcheck builder
.. versionadded:: 1.1
.. confval:: linkcheck_request_headers
A dictionary that maps baseurls to HTTP request headers.
The key is a URL base string like ``"https://sphinx-doc.org/"``. To specify
headers for other hosts, ``"*"`` can be used. It matches all hosts only when
the URL does not match other settings.
The value is a dictionary that maps header name to its value.
Example:
.. code-block:: python
linkcheck_request_headers = {
"https://sphinx-doc.org/": {
"Accept": "text/html",
"Accept-Encoding": "utf-8",
},
"*": {
"Accept": "text/html,application/xhtml+xml",
}
}
.. versionadded:: 3.1
.. confval:: linkcheck_retries
The number of times the linkcheck builder will attempt to check a URL before
@ -2467,6 +2579,23 @@ Options for the linkcheck builder
.. versionadded:: 2.3
.. confval:: linkcheck_rate_limit_timeout
The ``linkcheck`` builder may issue a large number of requests to the same
site over a short period of time. This setting controls the builder behavior
when servers indicate that requests are rate-limited.
If a server indicates when to retry (using the `Retry-After`_ header),
``linkcheck`` always follows the server indication.
Otherwise, ``linkcheck`` waits for a minute before to retry and keeps
doubling the wait time between attempts until it succeeds or exceeds the
``linkcheck_rate_limit_timeout``. By default, the timeout is 5 minutes.
.. _Retry-After: https://tools.ietf.org/html/rfc7231#section-7.1.3
.. versionadded:: 3.4
Options for the XML builder
---------------------------
@ -2509,6 +2638,23 @@ Options for the C domain
.. versionadded:: 3.0
.. confval:: c_allow_pre_v3
A boolean (default ``False``) controlling whether to parse and try to
convert pre-v3 style type directives and type roles.
.. versionadded:: 3.2
.. deprecated:: 3.2
Use the directives and roles added in v3.
.. confval:: c_warn_on_allowed_pre_v3
A boolean (default ``True``) controlling whether to warn when a pre-v3
style type directive/role is parsed and converted.
.. versionadded:: 3.2
.. deprecated:: 3.2
Use the directives and roles added in v3.
.. _cpp-config:

View File

@ -136,15 +136,28 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
:undoc-members:
* "Private" members (that is, those named like ``_private`` or ``__private``)
will be included if the ``private-members`` flag option is given.
will be included if the ``private-members`` flag option is given::
.. automodule:: noodle
:members:
:private-members:
It can also take an explicit list of member names to be documented as
arguments::
.. automodule:: noodle
:members:
:private-members: _spicy, _garlickly
.. versionadded:: 1.1
.. versionchanged:: 3.2
The option can now take arguments.
* autodoc considers a member private if its docstring contains
``:meta private:`` in its :ref:`info-field-lists`.
For example:
.. code-block:: rst
.. code-block:: python
def my_function(my_arg, my_other_arg):
"""blah blah blah
@ -159,7 +172,7 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
an underscore.
For example:
.. code-block:: rst
.. code-block:: python
def _my_function(my_arg, my_other_arg):
"""blah blah blah
@ -169,6 +182,16 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
.. versionadded:: 3.1
* autodoc considers a variable member does not have any default value if its
docstring contains ``:meta hide-value:`` in its :ref:`info-field-lists`.
Example:
.. code-block:: python
var1 = None #: :meta hide-value:
.. versionadded:: 3.5
* Python "special" members (that is, those named like ``__special__``) will
be included if the ``special-members`` flag option is given::
@ -216,7 +239,7 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
.. versionchanged:: 3.0
It takes an anchestor class name as an argument.
It takes an ancestor class name as an argument.
* It's possible to override the signature for explicitly documented callable
objects (functions, methods, classes) with the regular syntax that will
@ -280,6 +303,12 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
.. versionadded:: 1.3
* As a hint to autodoc extension, you can put a ``::`` separator in between
module name and object name to let autodoc know the correct module name if
it is ambiguous. ::
.. autoclass:: module.name::Noodle
.. rst:directive:: autofunction
autodecorator
@ -307,6 +336,15 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
By default, without ``annotation`` option, Sphinx tries to obtain the value of
the variable and print it after the name.
The ``no-value`` option can be used instead of a blank ``annotation`` to show the
type hint but not the value::
.. autodata:: CD_DRIVE
:no-value:
If both the ``annotation`` and ``no-value`` options are used, ``no-value`` has no
effect.
For module data members and class attributes, documentation can either be put
into a comment with special formatting (using a ``#:`` to start the comment
instead of just ``#``), or in a docstring *after* the definition. Comments
@ -346,6 +384,9 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
option.
.. versionchanged:: 2.0
:rst:dir:`autodecorator` added.
.. versionchanged:: 3.4
:rst:dir:`autodata` and :rst:dir:`autoattribute` now have a ``no-value``
option.
.. note::
@ -496,6 +537,44 @@ There are also config values that you can set:
New option ``'description'`` is added.
.. confval:: autodoc_type_aliases
A dictionary for users defined `type aliases`__ that maps a type name to the
full-qualified object name. It is used to keep type aliases not evaluated in
the document. Defaults to empty (``{}``).
The type aliases are only available if your program enables `Postponed
Evaluation of Annotations (PEP 563)`__ feature via ``from __future__ import
annotations``.
For example, there is code using a type alias::
from __future__ import annotations
AliasType = Union[List[Dict[Tuple[int, str], Set[int]]], Tuple[str, List[str]]]
def f() -> AliasType:
...
If ``autodoc_type_aliases`` is not set, autodoc will generate internal mark-up
from this code as following::
.. py:function:: f() -> Union[List[Dict[Tuple[int, str], Set[int]]], Tuple[str, List[str]]]
...
If you set ``autodoc_type_aliases`` as
``{'AliasType': 'your.module.AliasType'}``, it generates the following document
internally::
.. py:function:: f() -> your.module.AliasType:
...
.. __: https://www.python.org/dev/peps/pep-0563/
.. __: https://mypy.readthedocs.io/en/latest/kinds_of_types.html#type-aliases
.. versionadded:: 3.3
.. confval:: autodoc_warningiserror
This value controls the behavior of :option:`sphinx-build -W` during

View File

@ -175,7 +175,7 @@ also use these config values:
.. confval:: autosummary_generate_overwrite
If true, autosummary already overwrites stub files by generated contents.
If true, autosummary overwrites existing files by generated stub pages.
Defaults to true (enabled).
.. versionadded:: 3.0
@ -195,6 +195,15 @@ also use these config values:
.. versionadded:: 2.1
.. confval:: autosummary_filename_map
A dict mapping object names to filenames. This is necessary to avoid
filename conflicts where multiple objects have names that are
indistinguishable when case is ignored, on file systems where filenames
are case-insensitive.
.. versionadded:: 3.2
Customizing templates
---------------------
@ -295,7 +304,7 @@ The following variables available in the templates:
.. data:: modules
List containing names of "public" modules in the package. Only available for
modules that are packages.
modules that are packages and the ``recursive`` option is on.
.. versionadded:: 3.1

View File

@ -51,4 +51,11 @@ should check:
.. versionadded:: 1.1
.. _Python regular expressions: https://docs.python.org/library/re
.. confval:: coverage_show_missing_items
Print objects that are missing to standard output also.
``False`` by default.
.. versionadded:: 3.1
.. _Python regular expressions: https://docs.python.org/library/re

View File

@ -67,7 +67,7 @@ a comma-separated list of group names.
default set of flags is specified by the :confval:`doctest_default_flags`
configuration variable.
This directive supports three options:
This directive supports five options:
* ``hide``, a flag option, hides the doctest block in other builders. By
default it is shown as a highlighted doctest block.
@ -102,6 +102,11 @@ a comma-separated list of group names.
Supported PEP-440 operands and notations
* ``trim-doctest-flags`` and ``no-trim-doctest-flags``, a flag option,
doctest flags (comments looking like ``# doctest: FLAG, ...``) at the
ends of lines and ``<BLANKLINE>`` markers are removed (or not removed)
individually. Default is ``trim-doctest-flags``.
Note that like with standard doctests, you have to use ``<BLANKLINE>`` to
signal a blank line in the expected output. The ``<BLANKLINE>`` is removed
when building presentation output (HTML, LaTeX etc.).
@ -119,11 +124,16 @@ a comma-separated list of group names.
A code block for a code-output-style test.
This directive supports one option:
This directive supports three options:
* ``hide``, a flag option, hides the code block in other builders. By
default it is shown as a highlighted code block.
* ``trim-doctest-flags`` and ``no-trim-doctest-flags``, a flag option,
doctest flags (comments looking like ``# doctest: FLAG, ...``) at the
ends of lines and ``<BLANKLINE>`` markers are removed (or not removed)
individually. Default is ``trim-doctest-flags``.
.. note::
Code in a ``testcode`` block is always executed all at once, no matter how
@ -149,7 +159,7 @@ a comma-separated list of group names.
The corresponding output, or the exception message, for the last
:rst:dir:`testcode` block.
This directive supports two options:
This directive supports four options:
* ``hide``, a flag option, hides the output block in other builders. By
default it is shown as a literal block without highlighting.
@ -157,6 +167,11 @@ a comma-separated list of group names.
* ``options``, a string option, can be used to give doctest flags
(comma-separated) just like in normal doctest blocks.
* ``trim-doctest-flags`` and ``no-trim-doctest-flags``, a flag option,
doctest flags (comments looking like ``# doctest: FLAG, ...``) at the
ends of lines and ``<BLANKLINE>`` markers are removed (or not removed)
individually. Default is ``trim-doctest-flags``.
Example::
.. testcode::

View File

@ -294,3 +294,21 @@ class ExampleClass:
def _private_without_docstring(self):
pass
class ExamplePEP526Class:
"""The summary line for a class docstring should fit on one line.
If the class has public attributes, they may be documented here
in an ``Attributes`` section and follow the same formatting as a
function's ``Args`` section. If ``napoleon_attr_annotations``
is True, types can be specified in the class body using ``PEP 526``
annotations.
Attributes:
attr1: Description of `attr1`.
attr2: Description of `attr2`.
"""
attr1: str
attr2: int

View File

@ -75,8 +75,9 @@ linking:
A dictionary mapping unique identifiers to a tuple ``(target, inventory)``.
Each ``target`` is the base URI of a foreign Sphinx documentation set and can
be a local path or an HTTP URI. The ``inventory`` indicates where the
inventory file can be found: it can be ``None`` (at the same location as
the base URI) or another local or HTTP URI.
inventory file can be found: it can be ``None`` (an :file:`objects.inv` file
at the same location as the base URI) or another local file path or a full
HTTP URI to an inventory file.
The unique identifier can be used to prefix cross-reference targets, so that
it is clear which intersphinx set the target belongs to. A link like
@ -106,7 +107,7 @@ linking:
``https://docs.python.org/3``. It is up to you to update the inventory file
as new objects are added to the Python documentation.
**Multiple target for the inventory**
**Multiple targets for the inventory**
.. versionadded:: 1.3
@ -120,6 +121,16 @@ linking:
intersphinx_mapping = {'python': ('https://docs.python.org/3',
(None, 'python-inv.txt'))}
For a set of books edited and tested locally and then published
together, it could be helpful to try a local inventory file first,
to check references before publication::
intersphinx_mapping = {
'otherbook':
('https://myproj.readthedocs.io/projects/otherbook/en/latest',
('../../otherbook/build/html/objects.inv', None)),
}
.. confval:: intersphinx_cache_limit
The maximum number of days to cache remote inventories. The default is

View File

@ -115,6 +115,7 @@ All of the following section headers are supported:
* ``Parameters``
* ``Return`` *(alias of Returns)*
* ``Returns``
* ``Raise`` *(alias of Raises)*
* ``Raises``
* ``References``
* ``See Also``
@ -122,6 +123,7 @@ All of the following section headers are supported:
* ``Todo``
* ``Warning``
* ``Warnings`` *(alias of Warning)*
* ``Warn`` *(alias of Warns)*
* ``Warns``
* ``Yield`` *(alias of Yields)*
* ``Yields``
@ -201,7 +203,8 @@ Type Annotations
This is an alternative to expressing types directly in docstrings.
One benefit of expressing types according to `PEP 484`_ is that
type checkers and IDEs can take advantage of them for static code
analysis.
analysis. `PEP 484`_ was then extended by `PEP 526`_ which introduced
a similar way to annotate variables (and attributes).
Google style with Python 3 type annotations::
@ -219,6 +222,19 @@ Google style with Python 3 type annotations::
"""
return True
class Class:
"""Summary line.
Extended description of class
Attributes:
attr1: Description of attr1
attr2: Description of attr2
"""
attr1: int
attr2: str
Google style with types in docstrings::
@ -236,6 +252,16 @@ Google style with types in docstrings::
"""
return True
class Class:
"""Summary line.
Extended description of class
Attributes:
attr1 (int): Description of attr1
attr2 (str): Description of attr2
"""
.. Note::
`Python 2/3 compatible annotations`_ aren't currently
@ -244,6 +270,9 @@ Google style with types in docstrings::
.. _PEP 484:
https://www.python.org/dev/peps/pep-0484/
.. _PEP 526:
https://www.python.org/dev/peps/pep-0526/
.. _Python 2/3 compatible annotations:
https://www.python.org/dev/peps/pep-0484/#suggested-syntax-for-python-2-7-and-straddling-code
@ -272,11 +301,13 @@ sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
napoleon_use_ivar = False
napoleon_use_param = True
napoleon_use_rtype = True
napoleon_type_aliases = None
napoleon_attr_annotations = True
.. _Google style:
https://google.github.io/styleguide/pyguide.html
.. _NumPy style:
https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard
.. confval:: napoleon_google_docstring
@ -433,7 +464,7 @@ sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
:param arg1: Description of `arg1`
:type arg1: str
:param arg2: Description of `arg2`, defaults to 0
:type arg2: int, optional
:type arg2: :class:`int`, *optional*
**If False**::
@ -478,3 +509,65 @@ sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
**If False**::
:returns: *bool* -- True if successful, False otherwise
.. confval:: napoleon_type_aliases
A mapping to translate type names to other names or references. Works
only when ``napoleon_use_param = True``. *Defaults to None.*
With::
napoleon_type_aliases = {
"CustomType": "mypackage.CustomType",
"dict-like": ":term:`dict-like <mapping>`",
}
This `NumPy style`_ snippet::
Parameters
----------
arg1 : CustomType
Description of `arg1`
arg2 : dict-like
Description of `arg2`
becomes::
:param arg1: Description of `arg1`
:type arg1: mypackage.CustomType
:param arg2: Description of `arg2`
:type arg2: :term:`dict-like <mapping>`
.. versionadded:: 3.2
.. confval:: napoleon_attr_annotations
True to allow using `PEP 526`_ attributes annotations in classes.
If an attribute is documented in the docstring without a type and
has an annotation in the class body, that type is used.
.. versionadded:: 3.4
.. confval:: napoleon_custom_sections
Add a list of custom sections to include, expanding the list of parsed sections.
*Defaults to None.*
The entries can either be strings or tuples, depending on the intention:
* To create a custom "generic" section, just pass a string.
* To create an alias for an existing section, pass a tuple containing the
alias name and the original, in that order.
* To create a custom section that displays like the parameters or returns
section, pass a tuple containing the custom section name and a string
value, "params_style" or "returns_style".
If an entry is just a string, it is interpreted as a header for a generic
section. If the entry is a tuple/list/indexed container, the first entry
is the name of the section, the second is the section key to emulate. If the
second entry value is "params_style" or "returns_style", the custom section
will be displayed like the parameters section or returns section.
.. versionadded:: 1.8
.. versionchanged:: 3.5
Support ``params_style`` and ``returns_style``

View File

@ -171,7 +171,7 @@ Docker images for Sphinx are published on the `Docker Hub <https://hub.docker.co
- `sphinxdoc/sphinx <https://hub.docker.com/repository/docker/sphinxdoc/sphinx>`_
- `sphinxdoc/sphinx-latexpdf <https://hub.docker.com/repository/docker/sphinxdoc/sphinx-latexpdf>`_
Former one is used for standard usage of Sphinx, and latter one is mainly used for PDF builds using LaTeX.
Former one is used for standard usage of Sphinx, and latter one is mainly used for PDF builds using LaTeX.
Please choose one for your purpose.
.. note::

View File

@ -15,7 +15,7 @@ Much of Sphinx's power comes from the richness of its default plain-text markup
format, :doc:`reStructuredText </usage/restructuredtext/index>`, along with
it's :doc:`significant extensibility capabilities </development/index>`.
The goal of this document is to give you a quick taste of what Sphinx it is and
The goal of this document is to give you a quick taste of what Sphinx is and
how you might use it. When you're done here, you can check out the
:doc:`installation guide </usage/installation>` followed by the intro to the
default markup format used by Sphinx, :doc:`reStucturedText

View File

@ -114,9 +114,9 @@ tables of contents. The ``toctree`` directive is the central element.
**Additional options**
You can use ``caption`` option to provide a toctree caption and you can use
``name`` option to provide implicit target name that can be referenced by
using :rst:role:`ref`::
You can use the ``caption`` option to provide a toctree caption and you can
use the ``name`` option to provide an implicit target name that can be
referenced by using :rst:role:`ref`::
.. toctree::
:caption: Table of Contents
@ -246,7 +246,7 @@ The special document names (and pages generated for them) are:
* every name beginning with ``_``
Though only few such names are currently used by Sphinx, you should not
Though few such names are currently used by Sphinx, you should not
create documents or document-containing directories with such names. (Using
``_`` as a prefix for a custom template directory is fine.)
@ -569,12 +569,28 @@ __ http://pygments.org/docs/lexers
print 'Explicit is better than implicit.'
In order to cross-reference a code-block using either the
:rst:role:`ref` or the :rst:role:`numref` role, it is necessary
that both :strong:`name` and :strong:`caption` be defined. The
argument of :strong:`name` can then be given to :rst:role:`numref`
to generate the cross-reference. Example::
See :numref:`this-py` for an example.
When using :rst:role:`ref`, it is possible to generate a cross-reference
with only :strong:`name` defined, provided an explicit title is
given. Example::
See :ref:`this code snippet <this-py>` for an example.
.. versionadded:: 1.3
.. rst:directive:option:: dedent: number
:type: number
:type: number or no value
Strip indentation characters from the code block. For example::
Strip indentation characters from the code block. When number given,
leading N characters are removed. When no argument given, leading spaces
are removed via :func:`textwrap.dedent()`. For example::
.. code-block:: ruby
:dedent: 4
@ -582,6 +598,8 @@ __ http://pygments.org/docs/lexers
some ruby code
.. versionadded:: 1.3
.. versionchanged:: 3.5
Support automatic dedent.
.. rst:directive:option:: force
:type: no value
@ -656,9 +674,43 @@ __ http://pygments.org/docs/lexers
string are included. The ``start-at`` and ``end-at`` options behave in a
similar way, but the lines containing the matched string are included.
With lines selected using ``start-after`` it is still possible to use
``lines``, the first allowed line having by convention the line number
``1``.
``start-after``/``start-at`` and ``end-before``/``end-at`` can have same string.
``start-after``/``start-at`` filter lines before the line that contains
option string (``start-at`` will keep the line). Then ``end-before``/``end-at``
filter lines after the line that contains option string (``end-at`` will keep
the line and ``end-before`` skip the first line).
.. note::
If you want to select only ``[second-section]`` of ini file like the
following, you can use ``:start-at: [second-section]`` and
``:end-before: [third-section]``:
.. code-block:: ini
[first-section]
var_in_first=true
[second-section]
var_in_second=true
[third-section]
var_in_third=true
Useful cases of these option is working with tag comments.
``:start-after: [initialized]`` and ``:end-before: [initialized]`` options
keep lines between comments:
.. code-block:: py
if __name__ == "__main__":
# [initialize]
app.start(":8000")
# [initialize]
When lines have been selected in any of the ways described above, the line
numbers in ``emphasize-lines`` refer to those selected lines, counted
@ -708,6 +760,9 @@ __ http://pygments.org/docs/lexers
.. versionchanged:: 2.1
Added the ``force`` option.
.. versionchanged:: 3.5
Support automatic dedent.
.. _glossary-directive:
Glossary
@ -1165,20 +1220,29 @@ the definition of the symbol. There is this directive:
the following definition. If the definition spans multiple lines, each
continuation line must begin with a colon placed at the same column as in
the first line.
Blank lines are not allowed within ``productionlist`` directive arguments.
The definition can contain token names which are marked as interpreted text
(e.g., "``sum ::= `integer` "+" `integer```") -- this generates
cross-references to the productions of these tokens. Outside of the
production list, you can reference to token productions using
:rst:role:`token`.
The *productionGroup* argument to :rst:dir:`productionlist` serves to
distinguish different sets of production lists that belong to different
grammars. Multiple production lists with the same *productionGroup* thus
define rules in the same scope.
Blank lines are not allowed within ``productionlist`` directive arguments.
Inside of the production list, tokens implicitly refer to productions
from the current group. You can refer to the production of another
grammar by prefixing the token with its group name and a colon, e.g,
"``otherGroup:sum``". If the group of the token should not be shown in
the production, it can be prefixed by a tilde, e.g.,
"``~otherGroup:sum``". To refer to a production from an unnamed
grammar, the token should be prefixed by a colon, e.g., "``:sum``".
The definition can contain token names which are marked as interpreted text
(e.g. "``sum ::= `integer` "+" `integer```") -- this generates
cross-references to the productions of these tokens. Outside of the
production list, you can reference to token productions using
:rst:role:`token`.
However, if you have given a *productionGroup* argument you must prefix the
Outside of the production list,
if you have given a *productionGroup* argument you must prefix the
token name in the cross-reference with the group name and a colon,
e.g., "``myGroup:sum``" instead of just "``sum``".
If the group should not be shown in the title of the link either

View File

@ -42,9 +42,22 @@ Basic Markup
Most domains provide a number of :dfn:`object description directives`, used to
describe specific objects provided by modules. Each directive requires one or
more signatures to provide basic information about what is being described, and
the content should be the description. The basic version makes entries in the
general index; if no index entry is desired, you can give the directive option
flag ``:noindex:``. An example using a Python domain directive::
the content should be the description. A domain will typically keep an
internal index of all entites to aid cross-referencing. Typically it will
also add entries in the shown general index.
If you want to suppress the addition of an entry in the shown index, you can
give the directive option flag ``:noindexentry:``.
If you want to typeset an object description, without even making it available
for cross-referencing, you can give the directive option flag ``:noindex:``
(which implies ``:noindexentry:``).
Though, note that not every directive en every domain may support these
options.
.. versionadded:: 3.2
The directive option ``noindexentry`` in the Python, C, C++, and Javascript
domains.
An example using a Python domain directive::
.. py:function:: spam(eggs)
ham(eggs)
@ -699,6 +712,53 @@ Explicit ref: :c:var:`Data.@data.a`. Short-hand ref: :c:var:`Data.a`.
.. versionadded:: 3.0
Aliasing Declarations
~~~~~~~~~~~~~~~~~~~~~
.. c:namespace-push:: @alias
Sometimes it may be helpful list declarations elsewhere than their main
documentation, e.g., when creating a synopsis of an interface.
The following directive can be used for this purpose.
.. rst:directive:: .. c:alias:: name
Insert one or more alias declarations. Each entity can be specified
as they can in the :rst:role:`c:any` role.
For example::
.. c:var:: int data
.. c:function:: int f(double k)
.. c:alias:: data
f
becomes
.. c:var:: int data
.. c:function:: int f(double k)
.. c:alias:: data
f
.. versionadded:: 3.2
.. rubric:: Options
.. rst:directive:option:: maxdepth: int
Insert nested declarations as well, up to the total depth given.
Use 0 for infinite depth and 1 for just the mentioned declaration.
Defaults to 1.
.. versionadded:: 3.3
.. c:namespace-pop::
Inline Expressions and Types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1038,7 +1098,7 @@ Options
Some directives support options:
- ``:noindex:``, see :ref:`basic-domain-markup`.
- ``:noindexentry:``, see :ref:`basic-domain-markup`.
- ``:tparam-line-spec:``, for templated declarations.
If specified, each template parameter will be rendered on a separate line.

View File

@ -9,7 +9,14 @@ fields marked up like this::
:fieldname: Field content
Sphinx provides custom behavior for bibliographic fields compared to docutils.
Sphinx extends standard docutils behavior for field lists and adds some extra
functionality that is covered in this section.
.. note::
The values of field lists will be parsed as
strings. You cannot use Python collections such as lists or dictionaries.
.. _metadata:
@ -17,11 +24,20 @@ File-wide metadata
------------------
A field list near the top of a file is normally parsed by docutils as the
*docinfo* which is generally used to record the author, date of publication and
other metadata. However, in Sphinx, a field list preceding any other markup is
moved from the *docinfo* to the Sphinx environment as document metadata and is
not displayed in the output; a field list appearing after the document title
will be part of the *docinfo* as normal and will be displayed in the output.
*docinfo* and shown on the page. However, in Sphinx, a field list preceding
any other markup is moved from the *docinfo* to the Sphinx environment as
document metadata, and is not displayed in the output.
.. note::
A field list appearing after the document title *will* be part of the
*docinfo* as normal and will be displayed in the output.
Special metadata fields
-----------------------
Sphinx provides custom behavior for bibliographic fields compared to docutils.
At the moment, these metadata fields are recognized:

View File

@ -2,8 +2,8 @@
.. _html-themes:
HTML
====
HTML Theming
============
Sphinx provides a number of builders for HTML and HTML-based formats.
@ -21,7 +21,8 @@ Themes
.. note::
This section provides information about using pre-existing HTML themes. If
you wish to create your own theme, refer to :doc:`/theming`.
you wish to create your own theme, refer to
:doc:`/development/theming`.
Sphinx supports changing the appearance of its HTML output via *themes*. A
theme is a collection of HTML templates, stylesheet(s) and other static files.
@ -80,7 +81,7 @@ zipfile-based theme::
html_theme = "dotted"
For more information on the design of themes, including information about
writing your own themes, refer to :doc:`/theming`.
writing your own themes, refer to :doc:`/development/theming`.
.. _builtin-themes:
@ -172,6 +173,12 @@ These themes are:
.. versionadded:: 3.1
- **globaltoc_maxdepth** (int): The maximum depth of the toctree in
``globaltoc.html`` (see :confval:`html_sidebars`). Set it to -1 to allow
unlimited depth. Defaults to the max depth selected in the toctree directive.
.. versionadded:: 3.2
**alabaster**
`Alabaster theme`_ is a modified "Kr" Sphinx theme from @kennethreitz
(especially as used in his Requests project), which was itself originally
@ -341,7 +348,7 @@ Third Party Themes
There are many third-party themes available. Some of these are general use,
while others are specific to an individual project. A section of third-party
themes is listed below. Many more can be found on PyPI__, GitHub__ and
themes is listed below. Many more can be found on PyPI__, GitHub__, GitLab__ and
sphinx-themes.org__.
.. cssclass:: clear
@ -357,6 +364,8 @@ sphinx-themes.org__.
.. versionchanged:: 1.4
**sphinx_rtd_theme** has become optional.
.. __: https://pypi.org/search/?q=&o=&c=Framework+%3A%3A+Sphinx+%3A%3A+Theme
.. __: https://github.com/search?utf8=%E2%9C%93&q=sphinx+theme&type=
.. __: https://gitlab.com/explore?name=sphinx+theme
.. __: https://sphinx-themes.org/

28
package-lock.json generated
View File

@ -385,12 +385,6 @@
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=",
"dev": true
},
"eventemitter3": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
"integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==",
"dev": true
},
"extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@ -535,14 +529,22 @@
}
},
"http-proxy": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz",
"integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==",
"version": "1.18.1",
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
"dev": true,
"requires": {
"eventemitter3": "^3.0.0",
"eventemitter3": "^4.0.0",
"follow-redirects": "^1.0.0",
"requires-port": "^1.0.0"
},
"dependencies": {
"eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
"dev": true
}
}
},
"iconv-lite": {
@ -702,9 +704,9 @@
}
},
"lodash": {
"version": "4.17.14",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.14.tgz",
"integrity": "sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw==",
"version": "4.17.19",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz",
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==",
"dev": true
},
"log4js": {

View File

@ -29,9 +29,11 @@ directory = sphinx/locale/
[flake8]
max-line-length = 95
ignore = E116,E241,E251,E741,W504,I101
exclude = .git,.tox,.venv,tests/*,build/*,doc/_build/*,sphinx/search/*,doc/usage/extensions/example*.py
exclude = .git,.tox,.venv,tests/roots/*,build/*,doc/_build/*,sphinx/search/*,doc/usage/extensions/example*.py
application-import-names = sphinx
import-order-style = smarkets
per-file-ignores =
tests/*: E501
[flake8:local-plugins]
extension =
@ -39,6 +41,9 @@ extension =
paths =
.
[isort]
line_length = 95
[mypy]
python_version = 3.5
disallow_incomplete_defs = True
@ -55,12 +60,11 @@ filterwarnings =
all
ignore::DeprecationWarning:docutils.io
ignore::DeprecationWarning:pyximport.pyximport
ignore::ImportWarning:importlib._bootstrap
ignore::PendingDeprecationWarning:sphinx.util.pycompat
markers =
sphinx
apidoc
setup_command
test_params
testpaths = tests
[coverage:run]

View File

@ -43,15 +43,15 @@ extras_require = {
],
'lint': [
'flake8>=3.5.0',
'flake8-import-order',
'mypy>=0.770',
'isort',
'mypy>=0.800',
'docutils-stubs',
],
'test': [
'pytest',
'pytest-cov',
'html5lib',
'typed_ast', # for py35-37
"typed_ast; python_version < '3.8'",
'cython',
],
}
@ -76,9 +76,10 @@ class Tee:
try:
from babel.messages.pofile import read_po
from babel.messages.frontend import compile_catalog
from json import dump
from babel.messages.frontend import compile_catalog
from babel.messages.pofile import read_po
except ImportError:
pass
else:
@ -139,7 +140,7 @@ else:
domain + '.js'))
for js_file, (locale, po_file) in zip(js_files, po_files):
with open(po_file) as infile:
with open(po_file, encoding='utf8') as infile:
catalog = read_po(infile, locale)
if catalog.fuzzy and not self.use_fuzzy:
@ -157,13 +158,13 @@ else:
msgid = msgid[0]
jscatalog[msgid] = message.string
with open(js_file, 'wt') as outfile:
with open(js_file, 'wt', encoding='utf8') as outfile:
outfile.write('Documentation.addTranslations(')
dump({
'messages': jscatalog,
'plural_expr': catalog.plural_expr,
'locale': str(catalog.locale)
}, outfile, sort_keys=True)
}, outfile, sort_keys=True, indent=4)
outfile.write(');')
cmdclass['compile_catalog'] = compile_catalog_plusjs
@ -203,6 +204,7 @@ setup(
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Framework :: Setuptools Plugin',

View File

@ -4,7 +4,7 @@
The Sphinx documentation toolchain.
: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.
"""
@ -32,8 +32,8 @@ if 'PYTHONWARNINGS' not in os.environ:
warnings.filterwarnings('ignore', "'U' mode is deprecated",
DeprecationWarning, module='docutils.io')
__version__ = '3.1.0+'
__released__ = '3.1.0' # used when Sphinx builds its own docs
__version__ = '3.5.0+'
__released__ = '3.5.0' # used when Sphinx builds its own docs
#: Version info for better programmatic use.
#:
@ -43,7 +43,7 @@ __released__ = '3.1.0' # used when Sphinx builds its own docs
#:
#: .. versionadded:: 1.2
#: Before version 1.2, check the string ``sphinx.__version__``.
version_info = (3, 1, 0, 'beta', 0)
version_info = (3, 5, 0, 'beta', 0)
package_dir = path.abspath(path.dirname(__file__))

View File

@ -4,7 +4,7 @@
The Sphinx documentation toolchain.
: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.
"""

View File

@ -4,7 +4,7 @@
Additional docutils nodes.
: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.
"""
@ -21,6 +21,33 @@ if False:
from sphinx.application import Sphinx
class document(nodes.document):
"""The document root element patched by Sphinx.
This fixes that document.set_id() does not support a node having multiple node Ids.
see https://sourceforge.net/p/docutils/patches/167/
.. important:: This is only for Sphinx internal use. Please don't use this
in your extensions. It will be removed without deprecation period.
"""
def set_id(self, node: Element, msgnode: Element = None,
suggested_prefix: str = '') -> str:
from sphinx.util import docutils
if docutils.__version_info__ >= (0, 16):
ret = super().set_id(node, msgnode, suggested_prefix) # type: ignore
else:
ret = super().set_id(node, msgnode)
if docutils.__version_info__ < (0, 17):
# register other node IDs forcedly
for node_id in node['ids']:
if node_id not in self.ids:
self.ids[node_id] = node
return ret
class translatable(nodes.Node):
"""Node which supports translation.

View File

@ -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.
"""
self.registry.add_js_file(filename, **kwargs)
if hasattr(self.builder, 'add_js_file'):
self.builder.add_js_file(filename, **kwargs) # type: ignore
def add_css_file(self, filename: str, **kwargs: str) -> None:
.. versionchanged:: 3.5
Take priority argument. Allow to add a JavaScript file to the specific page.
"""
self.registry.add_js_file(filename, priority=priority, **kwargs)
if hasattr(self.builder, 'add_js_file'):
self.builder.add_js_file(filename, priority=priority, **kwargs) # type: ignore
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.

View File

@ -4,7 +4,7 @@
Builder superclass for all builders.
: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.
"""
@ -17,26 +17,24 @@ from docutils import nodes
from docutils.nodes import Node
from sphinx.config import Config
from sphinx.environment import BuildEnvironment, CONFIG_OK, CONFIG_CHANGED_REASON
from sphinx.environment import CONFIG_CHANGED_REASON, CONFIG_OK, BuildEnvironment
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 import import_object, logging, progress_message, rst, 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 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.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
from sphinx import directives # noqa
from sphinx import directives # NOQA isort:skip
from sphinx import roles # NOQA isort:skip
try:
import multiprocessing
except ImportError:
@ -45,6 +43,7 @@ except ImportError:
if False:
# For type annotation
from typing import Type # for python3.5.1
from sphinx.application import Sphinx

View File

@ -4,7 +4,7 @@
Base class of epub2/epub3 builders.
: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.
"""
@ -25,11 +25,10 @@ from sphinx import addnodes
from sphinx.builders.html import BuildInfo, StandaloneHTMLBuilder
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util import status_iterator
from sphinx.util import logging, status_iterator
from sphinx.util.fileutil import copy_asset_file
from sphinx.util.i18n import format_date
from sphinx.util.osutil import ensuredir, copyfile
from sphinx.util.osutil import copyfile, ensuredir
try:
from PIL import Image
@ -208,7 +207,12 @@ class EpubBuilder(StandaloneHTMLBuilder):
appeared = set() # type: Set[str]
for node in nodes:
if node['refuri'] in appeared:
logger.warning(__('duplicated ToC entry found: %s'), node['refuri'])
logger.warning(
__('duplicated ToC entry found: %s'),
node['refuri'],
type="epub",
subtype="duplicated_toc_entry",
)
else:
appeared.add(node['refuri'])
@ -388,7 +392,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
return ext in VECTOR_GRAPHICS_EXTENSIONS
def copy_image_files_pil(self) -> None:
"""Copy images using Pillow, the Python Imaging Libary.
"""Copy images using Pillow, the Python Imaging Library.
The method tries to read and write the files with Pillow, converting
the format and resizing the image if necessary/possible.
"""

View File

@ -4,30 +4,33 @@
Build Apple help books.
: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.
"""
import warnings
from typing import Any, Dict
from sphinxcontrib.applehelp import (
AppleHelpCodeSigningFailed,
AppleHelpIndexerFailed,
AppleHelpBuilder,
)
from sphinxcontrib.applehelp import (AppleHelpBuilder, AppleHelpCodeSigningFailed,
AppleHelpIndexerFailed)
from sphinx.application import Sphinx
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
deprecated_alias('sphinx.builders.applehelp',
{
'AppleHelpCodeSigningFailed': AppleHelpCodeSigningFailed,
'AppleHelpIndexerFailed': AppleHelpIndexerFailed,
'AppleHelpBuilder': AppleHelpBuilder,
},
RemovedInSphinx40Warning)
RemovedInSphinx40Warning,
{
'AppleHelpCodeSigningFailed':
'sphinxcontrib.applehelp.AppleHelpCodeSigningFailed',
'AppleHelpIndexerFailed':
'sphinxcontrib.applehelp.AppleHelpIndexerFailed',
'AppleHelpBuilder': 'sphinxcontrib.applehelp.AppleHelpBuilder',
})
def setup(app: Sphinx) -> Dict[str, Any]:

View File

@ -4,14 +4,13 @@
Changelog builder.
: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.
"""
import html
from os import path
from typing import Any, Dict, List, Tuple
from typing import cast
from typing import Any, Dict, List, Tuple, cast
from sphinx import package_dir
from sphinx.application import Sphinx
@ -24,7 +23,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
logger = logging.getLogger(__name__)

View File

@ -6,7 +6,7 @@
.. _Devhelp: https://wiki.gnome.org/Apps/Devhelp
: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,12 +18,14 @@ from sphinxcontrib.devhelp import DevhelpBuilder
from sphinx.application import Sphinx
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
deprecated_alias('sphinx.builders.devhelp',
{
'DevhelpBuilder': DevhelpBuilder,
},
RemovedInSphinx40Warning)
RemovedInSphinx40Warning,
{
'DevhelpBuilder': 'sphinxcontrib.devhelp.DevhelpBuilder'
})
def setup(app: Sphinx) -> Dict[str, Any]:

View File

@ -4,7 +4,7 @@
Directory HTML builders.
: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.
"""
@ -49,9 +49,12 @@ class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
# for compatibility
deprecated_alias('sphinx.builders.html',
{
'DirectoryHTMLBuilder': DirectoryHTMLBuilder,
'DirectoryHTMLBuilder': DirectoryHTMLBuilder,
},
RemovedInSphinx40Warning)
RemovedInSphinx40Warning,
{
'DirectoryHTMLBuilder': 'sphinx.builders.dirhtml.DirectoryHTMLBuilder',
})
def setup(app: Sphinx) -> Dict[str, Any]:

View File

@ -4,7 +4,7 @@
Do syntax checks, but no writing.
:copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""

View File

@ -5,7 +5,7 @@
Build epub3 files.
Originally derived from epub.py.
:copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
@ -18,7 +18,7 @@ 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 Config, ENUM
from sphinx.config import ENUM, Config
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.locale import __
from sphinx.util import logging, xmlname_checker

View File

@ -4,33 +4,32 @@
The MessageCatalogBuilder class.
: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.
"""
from codecs import open
from collections import defaultdict, OrderedDict
from datetime import datetime, tzinfo, timedelta
from os import path, walk, getenv
from collections import OrderedDict, defaultdict
from datetime import datetime, timedelta, tzinfo
from os import getenv, path, walk
from time import time
from typing import Any, Dict, Iterable, Generator, List, Set, Tuple, Union
from typing import Any, Dict, Generator, Iterable, List, Set, Tuple, Union
from uuid import uuid4
from docutils import nodes
from docutils.nodes import Element
from sphinx import addnodes
from sphinx import package_dir
from sphinx import addnodes, package_dir
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 import logging, split_index_msg, status_iterator
from sphinx.util.console import bold # type: ignore
from sphinx.util.i18n import CatalogInfo, docname_to_domain
from sphinx.util.nodes import extract_messages, traverse_translatable_index
from sphinx.util.osutil import ensuredir, canon_path, relpath
from sphinx.util.osutil import canon_path, ensuredir, relpath
from sphinx.util.tags import Tags
from sphinx.util.template import SphinxRenderer
@ -278,7 +277,7 @@ class MessageCatalogBuilder(I18nBuilder):
origin = MsgOrigin(template, line)
self.catalogs['sphinx'].add(msg, origin)
except Exception as exc:
raise ThemeError('%s: %r' % (template, exc))
raise ThemeError('%s: %r' % (template, exc)) from exc
def build(self, docnames: Iterable[str], summary: str = None, method: str = 'update') -> None: # NOQA
self._extract_from_template()
@ -316,7 +315,7 @@ class MessageCatalogBuilder(I18nBuilder):
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_builder(MessageCatalogBuilder)
app.add_config_value('gettext_compact', True, 'gettext')
app.add_config_value('gettext_compact', True, 'gettext', {bool, str})
app.add_config_value('gettext_location', True, 'gettext')
app.add_config_value('gettext_uuid', False, 'gettext')
app.add_config_value('gettext_auto_build', True, 'env')

View File

@ -4,17 +4,19 @@
Several HTML builders.
: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.
"""
import html
import os
import posixpath
import re
import sys
import warnings
from os import path
from typing import Any, Dict, IO, Iterable, Iterator, List, Set, Tuple
from typing import IO, Any, Dict, Iterable, Iterator, List, Set, Tuple
from urllib.parse import quote
from docutils import nodes
from docutils.core import publish_parts
@ -23,10 +25,10 @@ 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 import __display_version__, package_dir
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.config import Config
from sphinx.config import ENUM, Config
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.domains import Domain, Index, IndexEntry
from sphinx.environment.adapters.asset import ImageAdapter
@ -37,15 +39,15 @@ from sphinx.highlighting import PygmentsBridge
from sphinx.locale import _, __
from sphinx.search import js_index
from sphinx.theming import HTMLThemeFactory
from sphinx.util import logging, progress_message, status_iterator, md5
from sphinx.util import logging, md5, progress_message, status_iterator
from sphinx.util.docutils import is_html5_writer_available, new_document
from sphinx.util.fileutil import copy_asset
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.matching import DOTFILES, Matcher, patmatch
from sphinx.util.osutil import copyfile, ensuredir, os_path, relative_uri
from sphinx.util.tags import Tags
from sphinx.writers.html import HTMLWriter, HTMLTranslator
from sphinx.writers.html import HTMLTranslator, HTMLWriter
if False:
# For type annotation
@ -88,10 +90,13 @@ class Stylesheet(str):
attributes = None # type: Dict[str, str]
filename = None # type: str
priority = None # type: int
def __new__(cls, filename: str, *args: str, **attributes: str) -> "Stylesheet":
self = str.__new__(cls, filename) # type: ignore
def __new__(cls, filename: str, *args: str, priority: int = 500, **attributes: Any
) -> "Stylesheet":
self = str.__new__(cls, filename)
self.filename = filename
self.priority = priority
self.attributes = attributes
self.attributes.setdefault('rel', 'stylesheet')
self.attributes.setdefault('type', 'text/css')
@ -111,10 +116,12 @@ class JavaScript(str):
attributes = None # type: Dict[str, str]
filename = None # type: str
priority = None # type: int
def __new__(cls, filename: str, **attributes: str) -> "JavaScript":
self = str.__new__(cls, filename) # type: ignore
def __new__(cls, filename: str, priority: int = 500, **attributes: str) -> "JavaScript":
self = str.__new__(cls, filename)
self.filename = filename
self.priority = priority
self.attributes = attributes
return self
@ -140,7 +147,7 @@ class BuildInfo:
build_info.tags_hash = lines[3].split()[1].strip()
return build_info
except Exception as exc:
raise ValueError(__('build info file is broken: %r') % exc)
raise ValueError(__('build info file is broken: %r') % exc) from exc
def __init__(self, config: Config = None, tags: Tags = None, config_categories: List[str] = []) -> None: # NOQA
self.config_hash = ''
@ -288,30 +295,31 @@ class StandaloneHTMLBuilder(Builder):
self.add_css_file(filename, **attrs)
for filename, attrs in self.get_builder_config('css_files', 'html'):
attrs.setdefault('priority', 800) # User's CSSs are loaded after extensions'
self.add_css_file(filename, **attrs)
def add_css_file(self, filename: str, **kwargs: str) -> None:
def add_css_file(self, filename: str, **kwargs: Any) -> None:
if '://' not in filename:
filename = posixpath.join('_static', filename)
self.css_files.append(Stylesheet(filename, **kwargs)) # type: ignore
def init_js_files(self) -> None:
self.add_js_file('jquery.js')
self.add_js_file('underscore.js')
self.add_js_file('doctools.js')
self.add_js_file('language_data.js')
self.add_js_file('jquery.js', priority=200)
self.add_js_file('underscore.js', priority=200)
self.add_js_file('doctools.js', priority=200)
for filename, attrs in self.app.registry.js_files:
self.add_js_file(filename, **attrs)
for filename, attrs in self.get_builder_config('js_files', 'html'):
attrs.setdefault('priority', 800) # User's JSs are loaded after extensions'
self.add_js_file(filename, **attrs)
if self.config.language and self._get_translations_js():
self.add_js_file('translations.js')
def add_js_file(self, filename: str, **kwargs: str) -> None:
def add_js_file(self, filename: str, **kwargs: Any) -> None:
if filename and '://' not in filename:
filename = posixpath.join('_static', filename)
@ -447,9 +455,6 @@ class StandaloneHTMLBuilder(Builder):
logo = path.basename(self.config.html_logo) if self.config.html_logo else ''
favicon = path.basename(self.config.html_favicon) if self.config.html_favicon else ''
if not isinstance(self.config.html_use_opensearch, str):
logger.warning(__('html_use_opensearch config value must now be a string'))
self.relations = self.env.collect_relations()
rellinks = [] # type: List[Tuple[str, str, str, str]]
@ -461,6 +466,10 @@ class StandaloneHTMLBuilder(Builder):
rellinks.append((indexname, indexcls.localname,
'', indexcls.shortname))
# back up script_files and css_files to allow adding JS/CSS files to a specific page.
self._script_files = list(self.script_files)
self._css_files = list(self.css_files)
if self.config.html_style is not None:
stylename = self.config.html_style
elif self.theme:
@ -640,17 +649,17 @@ class StandaloneHTMLBuilder(Builder):
def gen_additional_pages(self) -> None:
# additional pages from conf.py
for pagename, template in self.config.html_additional_pages.items():
logger.info(' ' + pagename, nonl=True)
logger.info(pagename + ' ', nonl=True)
self.handle_page(pagename, {}, template)
# the search page
if self.search:
logger.info(' search', nonl=True)
logger.info('search ', nonl=True)
self.handle_page('search', {}, 'search.html')
# the opensearch xml file
if self.config.html_use_opensearch and self.search:
logger.info(' opensearch', nonl=True)
logger.info('opensearch ', nonl=True)
fn = path.join(self.outdir, '_static', 'opensearch.xml')
self.handle_page('opensearch', {}, 'opensearch.xml', outfilename=fn)
@ -668,7 +677,7 @@ class StandaloneHTMLBuilder(Builder):
'genindexcounts': indexcounts,
'split_index': self.config.html_split_index,
}
logger.info(' genindex', nonl=True)
logger.info('genindex ', nonl=True)
if self.config.html_split_index:
self.handle_page('genindex', genindexcontext,
@ -690,7 +699,7 @@ class StandaloneHTMLBuilder(Builder):
'content': content,
'collapse_index': collapse,
}
logger.info(' ' + indexname, nonl=True)
logger.info(indexname + ' ', nonl=True)
self.handle_page(indexname, indexcontext, 'domainindex.html')
def copy_image_files(self) -> None:
@ -750,18 +759,27 @@ class StandaloneHTMLBuilder(Builder):
copyfile(jsfile, path.join(self.outdir, '_static', '_stemmer.js'))
def copy_theme_static_files(self, context: Dict) -> None:
def onerror(filename: str, error: Exception) -> None:
logger.warning(__('Failed to copy a file in html_static_file: %s: %r'),
filename, error)
if self.theme:
for entry in self.theme.get_theme_dirs()[::-1]:
copy_asset(path.join(entry, 'static'),
path.join(self.outdir, '_static'),
excluded=DOTFILES, context=context, renderer=self.templates)
excluded=DOTFILES, context=context,
renderer=self.templates, onerror=onerror)
def copy_html_static_files(self, context: Dict) -> None:
def onerror(filename: str, error: Exception) -> None:
logger.warning(__('Failed to copy a file in html_static_file: %s: %r'),
filename, error)
excluded = Matcher(self.config.exclude_patterns + ["**/.*"])
for entry in self.config.html_static_path:
copy_asset(path.join(self.confdir, entry),
path.join(self.outdir, '_static'),
excluded, context=context, renderer=self.templates)
excluded, context=context, renderer=self.templates, onerror=onerror)
def copy_html_logo(self) -> None:
if self.config.html_logo:
@ -775,7 +793,7 @@ class StandaloneHTMLBuilder(Builder):
def copy_static_files(self) -> None:
try:
with progress_message(__('copying static files... ')):
with progress_message(__('copying static files')):
ensuredir(path.join(self.outdir, '_static'))
# prepare context for templates
@ -886,6 +904,8 @@ class StandaloneHTMLBuilder(Builder):
def _get_local_toctree(self, docname: str, collapse: bool = True, **kwargs: Any) -> str:
if 'includehidden' not in kwargs:
kwargs['includehidden'] = False
if kwargs.get('maxdepth') == '':
kwargs.pop('maxdepth')
return self.render_partial(TocTree(self.env).get_toctree_for(
docname, self, collapse, **kwargs))['fragment']
@ -945,7 +965,7 @@ class StandaloneHTMLBuilder(Builder):
# --------- these are overwritten by the serialization builder
def get_target_uri(self, docname: str, typ: str = None) -> str:
return docname + self.link_suffix
return quote(docname) + self.link_suffix
def handle_page(self, pagename: str, addctx: Dict, templatename: str = 'page.html',
outfilename: str = None, event_arg: Any = None) -> None:
@ -1000,12 +1020,20 @@ class StandaloneHTMLBuilder(Builder):
self.add_sidebars(pagename, ctx)
ctx.update(addctx)
# revert script_files and css_files
self.script_files[:] = self._script_files
self.css_files[:] = self.css_files
self.update_page_context(pagename, templatename, ctx, event_arg)
newtmpl = self.app.emit_firstresult('html-page-context', pagename,
templatename, ctx, event_arg)
if newtmpl:
templatename = newtmpl
# sort JS/CSS before rendering HTML
ctx['script_files'].sort(key=lambda js: js.priority)
ctx['css_files'].sort(key=lambda js: js.priority)
try:
output = self.templates.render(templatename, ctx)
except UnicodeError:
@ -1015,7 +1043,7 @@ class StandaloneHTMLBuilder(Builder):
return
except Exception as exc:
raise ThemeError(__("An error happened in rendering the page %s.\nReason: %r") %
(pagename, exc))
(pagename, exc)) from exc
if not outfilename:
outfilename = self.get_outfilename(pagename)
@ -1059,7 +1087,7 @@ class StandaloneHTMLBuilder(Builder):
else:
with open(searchindexfn + '.tmp', 'wb') as fb:
self.indexer.dump(fb, self.indexer_format)
movefile(searchindexfn + '.tmp', searchindexfn)
os.replace(searchindexfn + '.tmp', searchindexfn)
def convert_html_css_files(app: Sphinx, config: Config) -> None:
@ -1177,10 +1205,21 @@ def validate_html_favicon(app: Sphinx, config: Config) -> None:
config.html_favicon = None # type: ignore
def migrate_html_add_permalinks(app: Sphinx, config: Config) -> None:
"""Migrate html_add_permalinks to html_permalinks*."""
if config.html_add_permalinks:
if (isinstance(config.html_add_permalinks, bool) and
config.html_add_permalinks is False):
config.html_permalinks = False # type: ignore
else:
config.html_permalinks_icon = html.escape(config.html_add_permalinks) # type: ignore # NOQA
# for compatibility
import sphinxcontrib.serializinghtml # NOQA
import sphinx.builders.dirhtml # NOQA
import sphinx.builders.singlehtml # NOQA
import sphinxcontrib.serializinghtml # NOQA
def setup(app: Sphinx) -> Dict[str, Any]:
@ -1206,7 +1245,9 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_config_value('html_sidebars', {}, 'html')
app.add_config_value('html_additional_pages', {}, 'html')
app.add_config_value('html_domain_indices', True, 'html', [list])
app.add_config_value('html_add_permalinks', '', 'html')
app.add_config_value('html_add_permalinks', None, 'html')
app.add_config_value('html_permalinks', True, 'html')
app.add_config_value('html_permalinks_icon', '', 'html')
app.add_config_value('html_use_index', True, 'html')
app.add_config_value('html_split_index', False, 'html')
app.add_config_value('html_copy_source', True, 'html')
@ -1226,12 +1267,19 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_config_value('html_search_scorer', '', None)
app.add_config_value('html_scaled_image_link', True, 'html')
app.add_config_value('html_baseurl', '', 'html')
app.add_config_value('html_codeblock_linenos_style', 'table', 'html',
ENUM('table', 'inline'))
app.add_config_value('html_math_renderer', None, 'env')
app.add_config_value('html4_writer', False, 'html')
# events
app.add_event('html-collect-pages')
app.add_event('html-page-context')
# event handlers
app.connect('config-inited', convert_html_css_files, priority=800)
app.connect('config-inited', convert_html_js_files, priority=800)
app.connect('config-inited', migrate_html_add_permalinks, priority=800)
app.connect('config-inited', validate_html_extra_path, priority=800)
app.connect('config-inited', validate_html_static_path, priority=800)
app.connect('config-inited', validate_html_logo, priority=800)

View File

@ -4,12 +4,12 @@
Transforms for HTML builder.
: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.
"""
import re
from typing import Any, Dict
from typing import Any, Dict, List
from docutils import nodes
@ -28,7 +28,7 @@ class KeyboardTransform(SphinxPostTransform):
After::
<literal class="kbd">
<literal class="kbd compound">
<literal class="kbd">
Control
-
@ -37,18 +37,30 @@ class KeyboardTransform(SphinxPostTransform):
"""
default_priority = 400
builders = ('html',)
pattern = re.compile(r'(-|\+|\^|\s+)')
pattern = re.compile(r'(?<=.)(-|\+|\^|\s+)(?=.)')
multiwords_keys = (('caps', 'lock'),
('page' 'down'),
('page', 'up'),
('scroll' 'lock'),
('num', 'lock'),
('sys' 'rq'),
('back' 'space'))
def run(self, **kwargs: Any) -> None:
matcher = NodeMatcher(nodes.literal, classes=["kbd"])
for node in self.document.traverse(matcher): # type: nodes.literal
parts = self.pattern.split(node[-1].astext())
if len(parts) == 1:
if len(parts) == 1 or self.is_multiwords_key(parts):
continue
node['classes'].append('compound')
node.pop()
while parts:
key = parts.pop(0)
if self.is_multiwords_key(parts):
key = ''.join(parts[:3])
parts[:3] = []
else:
key = parts.pop(0)
node += nodes.literal('', key, classes=["kbd"])
try:
@ -58,6 +70,16 @@ class KeyboardTransform(SphinxPostTransform):
except IndexError:
pass
def is_multiwords_key(self, parts: List[str]) -> bool:
if len(parts) >= 3 and parts[1].strip() == '':
name = parts[0].lower(), parts[2].lower()
if name in self.multiwords_keys:
return True
else:
return False
else:
return False
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_post_transform(KeyboardTransform)

View File

@ -5,29 +5,34 @@
Build HTML help support files.
Parts adapted from Python's Doc/tools/prechm.py.
: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.
"""
import warnings
from typing import Any, Dict
from sphinxcontrib.htmlhelp import (
chm_locales, chm_htmlescape, HTMLHelpBuilder, default_htmlhelp_basename
)
from sphinxcontrib.htmlhelp import (HTMLHelpBuilder, chm_htmlescape, chm_locales,
default_htmlhelp_basename)
from sphinx.application import Sphinx
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
deprecated_alias('sphinx.builders.htmlhelp',
{
'chm_locales': chm_locales,
'chm_htmlescape': chm_htmlescape,
'HTMLHelpBuilder': HTMLHelpBuilder,
'HTMLHelpBuilder': HTMLHelpBuilder,
'default_htmlhelp_basename': default_htmlhelp_basename,
},
RemovedInSphinx40Warning)
RemovedInSphinx40Warning,
{
'chm_locales': 'sphinxcontrib.htmlhelp.chm_locales',
'chm_htmlescape': 'sphinxcontrib.htmlhelp.chm_htmlescape',
'HTMLHelpBuilder': 'sphinxcontrib.htmlhelp.HTMLHelpBuilder',
'default_htmlhelp_basename':
'sphinxcontrib.htmlhelp.default_htmlhelp_basename',
})
def setup(app: Sphinx) -> Dict[str, Any]:

View File

@ -4,7 +4,7 @@
LaTeX builder.
: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.
"""
@ -17,18 +17,18 @@ 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 import addnodes, highlighting, package_dir
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.builders.latex.constants import ADDITIONAL_SETTINGS, DEFAULT_SETTINGS, SHORTHANDOFF
from sphinx.builders.latex.theming import Theme, ThemeFactory
from sphinx.builders.latex.util import ExtBabel
from sphinx.config import Config, ENUM
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.config import ENUM, Config
from sphinx.deprecation import RemovedInSphinx40Warning, RemovedInSphinx50Warning
from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.errors import NoUri, SphinxError
from sphinx.locale import _, __
from sphinx.util import texescape, logging, progress_message, status_iterator
from sphinx.util import logging, progress_message, status_iterator, texescape
from sphinx.util.console import bold, darkgreen # type: ignore
from sphinx.util.docutils import SphinxFileOutput, new_document
from sphinx.util.fileutil import copy_asset_file
@ -36,11 +36,10 @@ from sphinx.util.i18n import format_date
from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.osutil import SEP, make_filename_from_project
from sphinx.util.template import LaTeXRenderer
from sphinx.writers.latex import LaTeXWriter, LaTeXTranslator
from sphinx.writers.latex import LaTeXTranslator, LaTeXWriter
# load docutils.nodes after loading sphinx.builders.latex.nodes
from docutils import nodes # NOQA
from docutils import nodes # isort:skip
XINDY_LANG_OPTIONS = {
# language codes from docutils.writers.latex2e.Babel
@ -128,8 +127,6 @@ class LaTeXBuilder(Builder):
self.docnames = [] # type: Iterable[str]
self.document_data = [] # type: List[Tuple[str, str, str, str, str, bool]]
self.themes = ThemeFactory(self.app)
self.usepackages = self.app.registry.latex_packages
self.usepackages_after_hyperref = self.app.registry.latex_packages_after_hyperref
texescape.init()
self.init_context()
@ -179,10 +176,6 @@ class LaTeXBuilder(Builder):
key = (self.config.latex_engine, self.config.language[:2])
self.context.update(ADDITIONAL_SETTINGS.get(key, {}))
# Apply extension settings to context
self.context['packages'] = self.usepackages
self.context['packages_after_hyperref'] = self.usepackages_after_hyperref
# Apply user settings to context
self.context.update(self.config.latex_elements)
self.context['release'] = self.config.release
@ -203,6 +196,13 @@ class LaTeXBuilder(Builder):
# Show the release label only if release value exists
self.context.setdefault('releasename', _('Release'))
def update_context(self) -> None:
"""Update template variables for .tex file just before writing."""
# Apply extension settings to context
registry = self.app.registry
self.context['packages'] = registry.latex_packages
self.context['packages_after_hyperref'] = registry.latex_packages_after_hyperref
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():
@ -290,6 +290,7 @@ class LaTeXBuilder(Builder):
doctree['tocdepth'] = tocdepth
self.post_process_images(doctree)
self.update_doc_context(title, author, theme)
self.update_context()
with progress_message(__("writing")):
docsettings._author = author
@ -448,6 +449,18 @@ class LaTeXBuilder(Builder):
filename = path.join(package_dir, 'templates', 'latex', 'sphinxmessages.sty_t')
copy_asset_file(filename, self.outdir, context=context, renderer=LaTeXRenderer())
@property
def usepackages(self) -> List[Tuple[str, str]]:
warnings.warn('LaTeXBuilder.usepackages is deprecated.',
RemovedInSphinx50Warning, stacklevel=2)
return self.app.registry.latex_packages
@property
def usepackages_after_hyperref(self) -> List[Tuple[str, str]]:
warnings.warn('LaTeXBuilder.usepackages_after_hyperref is deprecated.',
RemovedInSphinx50Warning, stacklevel=2)
return self.app.registry.latex_packages_after_hyperref
def patch_settings(settings: Any) -> Any:
"""Make settings object to show deprecation messages."""
@ -503,9 +516,9 @@ def validate_latex_theme_options(app: Sphinx, config: Config) -> None:
config.latex_theme_options.pop(key)
def install_pakcages_for_ja(app: Sphinx) -> None:
def install_packages_for_ja(app: Sphinx) -> None:
"""Install packages for Japanese."""
if app.config.language == 'ja':
if app.config.language == 'ja' and app.config.latex_engine in ('platex', 'uplatex'):
app.add_latex_package('pxjahyper', after_hyperref=True)
@ -556,7 +569,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_builder(LaTeXBuilder)
app.connect('config-inited', validate_config_values, priority=800)
app.connect('config-inited', validate_latex_theme_options, priority=800)
app.connect('builder-inited', install_pakcages_for_ja)
app.connect('builder-inited', install_packages_for_ja)
app.add_config_value('latex_engine', default_latex_engine, None,
ENUM('pdflatex', 'xelatex', 'lualatex', 'platex', 'uplatex'))

View File

@ -4,13 +4,12 @@
consntants for LaTeX builder.
: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.
"""
from typing import Any, Dict
PDFLATEX_DEFAULT_FONTPKG = r'''
\usepackage{times}
\expandafter\ifx\csname T@LGR\endcsname\relax

View File

@ -4,7 +4,7 @@
Additional nodes for LaTeX writer.
: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.
"""

View File

@ -4,7 +4,7 @@
Theming support for LaTeX builder.
: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.
"""
@ -87,10 +87,12 @@ class UserTheme(Theme):
try:
value = self.config.get('theme', key)
setattr(self, key, value)
except configparser.NoSectionError:
raise ThemeError(__('%r doesn\'t have "theme" setting') % filename)
except configparser.NoSectionError as exc:
raise ThemeError(__('%r doesn\'t have "theme" setting') %
filename) from exc
except configparser.NoOptionError as exc:
raise ThemeError(__('%r doesn\'t have "%s" setting') % (filename, exc.args[0]))
raise ThemeError(__('%r doesn\'t have "%s" setting') %
(filename, exc.args[0])) from exc
for key in self.OPTIONAL_CONFIG_KEYS:
try:

View File

@ -4,21 +4,20 @@
Transforms for LaTeX builder.
: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.
"""
from typing import Any, Dict, List, Set, Tuple
from typing import cast
from typing import Any, Dict, List, Set, Tuple, cast
from docutils import nodes
from docutils.nodes import Element, Node
from docutils.transforms.references import Substitutions
from sphinx import addnodes
from sphinx.application import Sphinx
from sphinx.builders.latex.nodes import (
captioned_literal_block, footnotemark, footnotetext, math_reference, thebibliography
)
from sphinx.builders.latex.nodes import (captioned_literal_block, footnotemark, footnotetext,
math_reference, thebibliography)
from sphinx.domains.citation import CitationDomain
from sphinx.transforms import SphinxTransform
from sphinx.transforms.post_transforms import SphinxPostTransform
@ -38,6 +37,18 @@ class FootnoteDocnameUpdater(SphinxTransform):
node['docname'] = self.env.docname
class SubstitutionDefinitionsRemover(SphinxPostTransform):
"""Remove ``substitution_definition node from doctrees."""
# should be invoked after Substitutions process
default_priority = Substitutions.default_priority + 1
builders = ('latex',)
def apply(self, **kwargs: Any) -> None:
for node in self.document.traverse(nodes.substitution_definition):
node.parent.remove(node)
class ShowUrlsTransform(SphinxPostTransform):
"""Expand references to inline text or footnotes.
@ -602,6 +613,7 @@ class IndexInSectionTitleTransform(SphinxTransform):
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_transform(FootnoteDocnameUpdater)
app.add_post_transform(SubstitutionDefinitionsRemover)
app.add_post_transform(BibliographyTransform)
app.add_post_transform(CitationReferenceTransform)
app.add_post_transform(DocumentTargetTransform)

View File

@ -4,7 +4,7 @@
Utilities for LaTeX builder.
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""

View File

@ -4,7 +4,7 @@
The CheckExternalLinksBuilder class.
: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.
"""
@ -13,28 +13,56 @@ import queue
import re
import socket
import threading
import time
import warnings
from datetime import datetime, timezone
from email.utils import parsedate_to_datetime
from html.parser import HTMLParser
from os import path
from typing import Any, Dict, List, Set, Tuple
from urllib.parse import unquote
from typing import Any, Dict, List, NamedTuple, Optional, Set, Tuple, cast
from urllib.parse import unquote, urlparse
from docutils import nodes
from docutils.nodes import Node
from requests.exceptions import HTTPError
from docutils.nodes import Element
from requests import Response
from requests.exceptions import HTTPError, TooManyRedirects
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.builders.dummy import DummyBuilder
from sphinx.deprecation import RemovedInSphinx50Warning
from sphinx.locale import __
from sphinx.util import encode_uri, requests, logging
from sphinx.util.console import ( # type: ignore
purple, red, darkgreen, darkgray, turquoise
)
from sphinx.transforms.post_transforms import SphinxPostTransform
from sphinx.util import encode_uri, logging, requests
from sphinx.util.console import darkgray, darkgreen, purple, red, turquoise # type: ignore
from sphinx.util.nodes import get_node_line
from sphinx.util.requests import is_ssl_error
logger = logging.getLogger(__name__)
uri_re = re.compile('([a-z]+:)?//') # matches to foo:// and // (a protocol relative URL)
Hyperlink = NamedTuple('Hyperlink', (('next_check', float),
('uri', Optional[str]),
('docname', Optional[str]),
('lineno', Optional[int])))
RateLimit = NamedTuple('RateLimit', (('delay', float), ('next_check', float)))
DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml;q=0.9,*/*;q=0.8',
}
CHECK_IMMEDIATELY = 0
QUEUE_POLL_SECS = 1
DEFAULT_DELAY = 60.0
def node_line_or_0(node: Element) -> int:
"""
PriorityQueue items must be comparable. The line number is part of the
tuple used by the PriorityQueue, keep an homogeneous type for comparison.
"""
warnings.warn('node_line_or_0() is deprecated.',
RemovedInSphinx50Warning, stacklevel=2)
return get_node_line(node) or 0
class AnchorCheckParser(HTMLParser):
"""Specialized HTML parser that looks for a specific anchor."""
@ -70,7 +98,7 @@ def check_anchor(response: requests.requests.Response, anchor: str) -> bool:
return parser.found
class CheckExternalLinksBuilder(Builder):
class CheckExternalLinksBuilder(DummyBuilder):
"""
Checks for broken external links.
"""
@ -79,14 +107,15 @@ class CheckExternalLinksBuilder(Builder):
'%(outdir)s/output.txt')
def init(self) -> None:
self.hyperlinks = {} # type: Dict[str, Hyperlink]
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]
self.auth = [(re.compile(pattern), auth_info) for pattern, auth_info
in self.app.config.linkcheck_auth]
self.good = set() # type: Set[str]
self.broken = {} # type: Dict[str, str]
self.redirected = {} # type: Dict[str, Tuple[str, int]]
self._good = set() # type: Set[str]
self._broken = {} # type: Dict[str, str]
self._redirected = {} # type: Dict[str, Tuple[str, int]]
# set a timeout for non-responding servers
socket.setdefaulttimeout(5.0)
# create output file
@ -95,25 +124,62 @@ class CheckExternalLinksBuilder(Builder):
open(path.join(self.outdir, 'output.json'), 'w').close()
# create queues and worker threads
self.wqueue = queue.Queue() # type: queue.Queue
self.rate_limits = {} # type: Dict[str, RateLimit]
self.wqueue = queue.PriorityQueue() # type: queue.PriorityQueue
self.rqueue = queue.Queue() # type: queue.Queue
self.workers = [] # type: List[threading.Thread]
for i in range(self.app.config.linkcheck_workers):
thread = threading.Thread(target=self.check_thread)
thread.setDaemon(True)
thread = threading.Thread(target=self.check_thread, daemon=True)
thread.start()
self.workers.append(thread)
@property
def good(self):
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "good"),
RemovedInSphinx50Warning,
stacklevel=2,
)
return self._good
@property
def broken(self):
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "broken"),
RemovedInSphinx50Warning,
stacklevel=2,
)
return self._broken
@property
def redirected(self):
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "redirected"),
RemovedInSphinx50Warning,
stacklevel=2,
)
return self._redirected
def check_thread(self) -> None:
kwargs = {
'allow_redirects': True,
'headers': {
'Accept': 'text/html,application/xhtml+xml;q=0.9,*/*;q=0.8',
},
}
kwargs = {}
if self.app.config.linkcheck_timeout:
kwargs['timeout'] = self.app.config.linkcheck_timeout
def get_request_headers() -> Dict:
url = urlparse(uri)
candidates = ["%s://%s" % (url.scheme, url.netloc),
"%s://%s/" % (url.scheme, url.netloc),
uri,
"*"]
for u in candidates:
if u in self.config.linkcheck_request_headers:
headers = dict(DEFAULT_REQUEST_HEADERS)
headers.update(self.config.linkcheck_request_headers[u])
return headers
return {}
def check_uri() -> Tuple[str, str, int]:
# split off anchor
if '#' in uri:
@ -139,11 +205,15 @@ class CheckExternalLinksBuilder(Builder):
else:
auth_info = None
# update request headers for the URL
kwargs['headers'] = get_request_headers()
try:
if anchor and self.app.config.linkcheck_anchors:
# Read the whole document and see if #anchor exists
response = requests.get(req_url, stream=True, config=self.app.config,
auth=auth_info, **kwargs)
response.raise_for_status()
found = check_anchor(response, unquote(anchor))
if not found:
@ -152,29 +222,42 @@ class CheckExternalLinksBuilder(Builder):
try:
# try a HEAD request first, which should be easier on
# the server and the network
response = requests.head(req_url, config=self.app.config,
auth=auth_info, **kwargs)
response = requests.head(req_url, allow_redirects=True,
config=self.app.config, auth=auth_info,
**kwargs)
response.raise_for_status()
except HTTPError:
except (HTTPError, TooManyRedirects) as err:
if isinstance(err, HTTPError) and err.response.status_code == 429:
raise
# retry with GET request if that fails, some servers
# don't like HEAD requests.
response = requests.get(req_url, stream=True, config=self.app.config,
response = requests.get(req_url, stream=True,
config=self.app.config,
auth=auth_info, **kwargs)
response.raise_for_status()
except HTTPError as err:
if err.response.status_code == 401:
# We'll take "Unauthorized" as working.
return 'working', ' - unauthorized', 0
elif err.response.status_code == 429:
next_check = self.limit_rate(err.response)
if next_check is not None:
self.wqueue.put((next_check, uri, docname, lineno), False)
return 'rate-limited', '', 0
return 'broken', str(err), 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:
if is_ssl_error(err):
return 'ignored', str(err), 0
else:
return 'broken', str(err), 0
return 'broken', str(err), 0
else:
netloc = urlparse(req_url).netloc
try:
del self.rate_limits[netloc]
except KeyError:
pass
if response.url.rstrip('/') == req_url.rstrip('/'):
return 'working', '', 0
else:
@ -188,18 +271,31 @@ class CheckExternalLinksBuilder(Builder):
else:
return 'redirected', new_url, 0
def check() -> Tuple[str, str, int]:
def check(docname: str) -> Tuple[str, str, int]:
# check for various conditions without bothering the network
if len(uri) == 0 or uri.startswith(('#', 'mailto:', 'ftp:')):
if len(uri) == 0 or uri.startswith(('#', 'mailto:', 'tel:')):
return 'unchecked', '', 0
elif not uri.startswith(('http:', 'https:')):
return 'local', '', 0
elif uri in self.good:
if uri_re.match(uri):
# non supported URI schemes (ex. ftp)
return 'unchecked', '', 0
else:
srcdir = path.dirname(self.env.doc2path(docname))
if path.exists(path.join(srcdir, uri)):
return 'working', '', 0
else:
for rex in self.to_ignore:
if rex.match(uri):
return 'ignored', '', 0
else:
self._broken[uri] = ''
return 'broken', '', 0
elif uri in self._good:
return 'working', 'old', 0
elif uri in self.broken:
return 'broken', self.broken[uri], 0
elif uri in self.redirected:
return 'redirected', self.redirected[uri][0], self.redirected[uri][1]
elif uri in self._broken:
return 'broken', self._broken[uri], 0
elif uri in self._redirected:
return 'redirected', self._redirected[uri][0], self._redirected[uri][1]
for rex in self.to_ignore:
if rex.match(uri):
return 'ignored', '', 0
@ -211,20 +307,78 @@ class CheckExternalLinksBuilder(Builder):
break
if status == "working":
self.good.add(uri)
self._good.add(uri)
elif status == "broken":
self.broken[uri] = info
self._broken[uri] = info
elif status == "redirected":
self.redirected[uri] = (info, code)
self._redirected[uri] = (info, code)
return (status, info, code)
while True:
uri, docname, lineno = self.wqueue.get()
next_check, uri, docname, lineno = self.wqueue.get()
if uri is None:
break
status, info, code = check()
self.rqueue.put((uri, docname, lineno, status, info, code))
netloc = urlparse(uri).netloc
try:
# Refresh rate limit.
# When there are many links in the queue, workers are all stuck waiting
# for responses, but the builder keeps queuing. Links in the queue may
# have been queued before rate limits were discovered.
next_check = self.rate_limits[netloc].next_check
except KeyError:
pass
if next_check > time.time():
# Sleep before putting message back in the queue to avoid
# waking up other threads.
time.sleep(QUEUE_POLL_SECS)
self.wqueue.put((next_check, uri, docname, lineno), False)
self.wqueue.task_done()
continue
status, info, code = check(docname)
if status == 'rate-limited':
logger.info(darkgray('-rate limited- ') + uri + darkgray(' | sleeping...'))
else:
self.rqueue.put((uri, docname, lineno, status, info, code))
self.wqueue.task_done()
def limit_rate(self, response: Response) -> Optional[float]:
next_check = None
retry_after = response.headers.get("Retry-After")
if retry_after:
try:
# Integer: time to wait before next attempt.
delay = float(retry_after)
except ValueError:
try:
# An HTTP-date: time of next attempt.
until = parsedate_to_datetime(retry_after)
except (TypeError, ValueError):
# TypeError: Invalid date format.
# ValueError: Invalid date, e.g. Oct 52th.
pass
else:
next_check = datetime.timestamp(until)
delay = (until - datetime.now(timezone.utc)).total_seconds()
else:
next_check = time.time() + delay
netloc = urlparse(response.url).netloc
if next_check is None:
max_delay = self.app.config.linkcheck_rate_limit_timeout
try:
rate_limit = self.rate_limits[netloc]
except KeyError:
delay = DEFAULT_DELAY
else:
last_wait_time = rate_limit.delay
delay = 2.0 * last_wait_time
if delay > max_delay and last_wait_time < max_delay:
delay = max_delay
if delay > max_delay:
return None
next_check = time.time() + delay
self.rate_limits[netloc] = RateLimit(delay, next_check)
return next_check
def process_result(self, result: Tuple[str, str, int, str, str, int]) -> None:
uri, docname, lineno, status, info, code = result
@ -279,44 +433,6 @@ class CheckExternalLinksBuilder(Builder):
lineno, uri + ' to ' + info)
self.write_linkstat(linkstat)
def get_target_uri(self, docname: str, typ: str = None) -> str:
return ''
def get_outdated_docs(self) -> Set[str]:
return self.env.found_docs
def prepare_writing(self, docnames: Set[str]) -> None:
return
def write_doc(self, docname: str, doctree: Node) -> None:
logger.info('')
n = 0
# reference nodes
for refnode in doctree.traverse(nodes.reference):
if 'refuri' not in refnode:
continue
uri = refnode['refuri']
lineno = get_node_line(refnode)
self.wqueue.put((uri, docname, lineno), False)
n += 1
# image nodes
for imgnode in doctree.traverse(nodes.image):
uri = imgnode['candidates'].get('?')
if uri and '://' in uri:
lineno = get_node_line(imgnode)
self.wqueue.put((uri, docname, lineno), False)
n += 1
done = 0
while done < n:
self.process_result(self.rqueue.get())
done += 1
if self.broken:
self.app.statuscode = 1
def write_entry(self, what: str, docname: str, filename: str, line: int,
uri: str) -> None:
with open(path.join(self.outdir, 'output.txt'), 'a') as output:
@ -328,15 +444,62 @@ class CheckExternalLinksBuilder(Builder):
output.write('\n')
def finish(self) -> None:
logger.info('')
n = 0
for hyperlink in self.hyperlinks.values():
self.wqueue.put(hyperlink, False)
n += 1
done = 0
while done < n:
self.process_result(self.rqueue.get())
done += 1
if self._broken:
self.app.statuscode = 1
self.wqueue.join()
# Shutdown threads.
for worker in self.workers:
self.wqueue.put((None, None, None), False)
self.wqueue.put((CHECK_IMMEDIATELY, None, None, None), False)
class HyperlinkCollector(SphinxPostTransform):
builders = ('linkcheck',)
default_priority = 800
def run(self, **kwargs: Any) -> None:
builder = cast(CheckExternalLinksBuilder, self.app.builder)
hyperlinks = builder.hyperlinks
# reference nodes
for refnode in self.document.traverse(nodes.reference):
if 'refuri' not in refnode:
continue
uri = refnode['refuri']
lineno = get_node_line(refnode)
uri_info = Hyperlink(CHECK_IMMEDIATELY, uri, self.env.docname, lineno)
if uri not in hyperlinks:
hyperlinks[uri] = uri_info
# image nodes
for imgnode in self.document.traverse(nodes.image):
uri = imgnode['candidates'].get('?')
if uri and '://' in uri:
lineno = get_node_line(imgnode)
uri_info = Hyperlink(CHECK_IMMEDIATELY, uri, self.env.docname, lineno)
if uri not in hyperlinks:
hyperlinks[uri] = uri_info
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_builder(CheckExternalLinksBuilder)
app.add_post_transform(HyperlinkCollector)
app.add_config_value('linkcheck_ignore', [], None)
app.add_config_value('linkcheck_auth', [], None)
app.add_config_value('linkcheck_request_headers', {}, None)
app.add_config_value('linkcheck_retries', 1, None)
app.add_config_value('linkcheck_timeout', None, None, [int])
app.add_config_value('linkcheck_workers', 5, None)
@ -344,6 +507,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
# Anchors starting with ! are ignored since they are
# commonly used for dynamic pages
app.add_config_value('linkcheck_anchors_ignore', ["^!"], None)
app.add_config_value('linkcheck_rate_limit_timeout', 300.0, None)
return {
'version': 'builtin',

View File

@ -4,7 +4,7 @@
Manual pages builder.
: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.
"""
@ -20,13 +20,11 @@ from sphinx.builders import Builder
from sphinx.config import Config
from sphinx.errors import NoUri
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util import progress_message
from sphinx.util import logging, progress_message
from sphinx.util.console import darkgreen # type: ignore
from sphinx.util.nodes import inline_all_toctrees
from sphinx.util.osutil import make_filename_from_project
from sphinx.writers.manpage import ManualPageWriter, ManualPageTranslator
from sphinx.util.osutil import ensuredir, make_filename_from_project
from sphinx.writers.manpage import ManualPageTranslator, ManualPageWriter
logger = logging.getLogger(__name__)
@ -80,7 +78,12 @@ class ManualPageBuilder(Builder):
docsettings.authors = authors
docsettings.section = section
targetname = '%s.%s' % (name, section)
if self.config.man_make_section_directory:
ensuredir(path.join(self.outdir, str(section)))
targetname = '%s/%s.%s' % (section, name, section)
else:
targetname = '%s.%s' % (name, section)
logger.info(darkgreen(targetname) + ' { ', nonl=True)
destination = FileOutput(
destination_path=path.join(self.outdir, targetname),
@ -115,6 +118,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_config_value('man_pages', default_man_pages, None)
app.add_config_value('man_show_urls', False, None)
app.add_config_value('man_make_section_directory', False, None)
return {
'version': 'builtin',

View File

@ -4,7 +4,7 @@
Build input files for the Qt collection generator.
: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.
"""
@ -17,13 +17,16 @@ import sphinx
from sphinx.application import Sphinx
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
deprecated_alias('sphinx.builders.qthelp',
{
'render_file': render_file,
'QtHelpBuilder': QtHelpBuilder,
},
RemovedInSphinx40Warning)
RemovedInSphinx40Warning,
{
'render_file': 'sphinxcontrib.qthelp.render_file',
'QtHelpBuilder': 'sphinxcontrib.qthelp.QtHelpBuilder',
})
def setup(app: Sphinx) -> Dict[str, Any]:

View File

@ -4,7 +4,7 @@
Single HTML builders.
: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.
"""
@ -19,8 +19,7 @@ from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
from sphinx.environment.adapters.toctree import TocTree
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util import progress_message
from sphinx.util import logging, progress_message
from sphinx.util.console import darkgreen # type: ignore
from sphinx.util.nodes import inline_all_toctrees
@ -193,7 +192,11 @@ deprecated_alias('sphinx.builders.html',
{
'SingleFileHTMLBuilder': SingleFileHTMLBuilder,
},
RemovedInSphinx40Warning)
RemovedInSphinx40Warning,
{
'SingleFileHTMLBuilder':
'sphinx.builders.singlehtml.SingleFileHTMLBuilder',
})
def setup(app: Sphinx) -> Dict[str, Any]:

View File

@ -4,7 +4,7 @@
Texinfo builder.
: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.
"""
@ -16,23 +16,20 @@ from docutils import nodes
from docutils.frontend import OptionParser
from docutils.io import FileOutput
from sphinx import addnodes
from sphinx import package_dir
from sphinx import addnodes, 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 _, __
from sphinx.util import logging
from sphinx.util import progress_message, status_iterator
from sphinx.util import logging, progress_message, status_iterator
from sphinx.util.console import darkgreen # type: ignore
from sphinx.util.docutils import new_document
from sphinx.util.fileutil import copy_asset_file
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
from sphinx.writers.texinfo import TexinfoTranslator, TexinfoWriter
logger = logging.getLogger(__name__)
template_dir = os.path.join(package_dir, 'templates', 'texinfo')
@ -182,7 +179,8 @@ class TexinfoBuilder(Builder):
try:
imagedir = path.join(self.outdir, targetname + '-figures')
ensuredir(imagedir)
copy_asset_file(path.join(self.srcdir, dest), imagedir)
copy_asset_file(path.join(self.srcdir, src),
path.join(imagedir, dest))
except Exception as err:
logger.warning(__('cannot copy image file %r: %s'),
path.join(self.srcdir, src), err)

View File

@ -4,7 +4,7 @@
Plain-text Sphinx builder.
: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.
"""
@ -19,7 +19,7 @@ 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
from sphinx.writers.text import TextTranslator, TextWriter
logger = logging.getLogger(__name__)

View File

@ -4,7 +4,7 @@
Docutils-native XML and pseudo-XML builders.
: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.
"""
@ -21,7 +21,7 @@ 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
from sphinx.writers.xml import PseudoXMLWriter, XMLWriter
if False:
# For type annotation

View File

@ -4,6 +4,6 @@
Modules for command line executables.
: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.
"""

View File

@ -4,7 +4,7 @@
Build documentation from a provided source.
: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.
"""
@ -16,7 +16,7 @@ import os
import pdb
import sys
import traceback
from typing import Any, IO, List
from typing import IO, Any, List
from docutils.utils import SystemMessage
@ -26,7 +26,7 @@ from sphinx.application import Sphinx
from sphinx.errors import SphinxError
from sphinx.locale import __
from sphinx.util import Tee, format_exception_cut_frames, save_traceback
from sphinx.util.console import red, nocolor, color_terminal, terminal_safe # type: ignore
from sphinx.util.console import color_terminal, nocolor, red, terminal_safe # type: ignore
from sphinx.util.docutils import docutils_namespace, patch_docutils

View File

@ -10,7 +10,7 @@
This is in its own module so that importing it is fast. It should not
import the main Sphinx modules (like sphinx.applications, sphinx.builders).
: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.
"""
@ -22,10 +22,9 @@ from typing import List
import sphinx
from sphinx.cmd.build import build_main
from sphinx.util.console import color_terminal, nocolor, bold, blue # type: ignore
from sphinx.util.console import blue, bold, color_terminal, nocolor # type: ignore
from sphinx.util.osutil import cd, rmtree
BUILDERS = [
("", "html", "to make standalone HTML files"),
("", "dirhtml", "to make HTML files named index.html in directories"),

View File

@ -4,7 +4,7 @@
Quickly setup documentation source to work with Sphinx.
: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.
"""
@ -37,9 +37,8 @@ import sphinx.locale
from sphinx import __display_version__, package_dir
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.locale import __
from sphinx.util.console import ( # type: ignore
colorize, bold, red, turquoise, nocolor, color_terminal
)
from sphinx.util.console import (bold, color_terminal, colorize, nocolor, red, # type: ignore
turquoise)
from sphinx.util.osutil import ensuredir
from sphinx.util.template import SphinxRenderer
@ -489,8 +488,10 @@ def get_parser() -> argparse.ArgumentParser:
help=__('project root'))
group = parser.add_argument_group(__('Structure options'))
group.add_argument('--sep', action='store_true', default=None,
group.add_argument('--sep', action='store_true', dest='sep', default=None,
help=__('if specified, separate source and build dirs'))
group.add_argument('--no-sep', action='store_false', dest='sep',
help=__('if specified, create build dir under source dir'))
group.add_argument('--dot', metavar='DOT', default='_',
help=__('replacement for dot in _templates etc.'))

View File

@ -4,7 +4,7 @@
Build configuration file handling.
: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.
"""
@ -13,10 +13,9 @@ import traceback
import types
import warnings
from collections import OrderedDict
from os import path, getenv
from typing import (
Any, Callable, Dict, Generator, Iterator, List, NamedTuple, Set, Tuple, Union
)
from os import getenv, path
from typing import (Any, Callable, Dict, Generator, Iterator, List, NamedTuple, Set, Tuple,
Union)
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.errors import ConfigError, ExtensionError
@ -99,7 +98,8 @@ class Config:
# general options
'project': ('Python', 'env', []),
'author': ('unknown', 'env', []),
'copyright': ('', 'html', []),
'project_copyright': ('', 'html', [str]),
'copyright': (lambda c: c.project_copyright, 'html', [str]),
'version': ('', 'env', []),
'release': ('', 'env', []),
'today': ('', 'env', []),
@ -131,7 +131,7 @@ class Config:
'rst_epilog': (None, 'env', [str]),
'rst_prolog': (None, 'env', [str]),
'trim_doctest_flags': (True, 'env', []),
'primary_domain': ('py', 'env', [NoneType]), # type: ignore
'primary_domain': ('py', 'env', [NoneType]),
'needs_sphinx': (None, None, [str]),
'needs_extensions': ({}, None, []),
'manpages_url': (None, 'env', []),
@ -181,6 +181,14 @@ class Config:
defvalue = self.values[name][0]
if self.values[name][2] == Any:
return value
elif self.values[name][2] == {bool, str}:
if value == '0':
# given falsy string from command line option
return False
elif value == '1':
return True
else:
return value
elif type(defvalue) is bool or self.values[name][2] == [bool]:
if value == '0':
# given falsy string from command line option
@ -196,9 +204,9 @@ class Config:
elif isinstance(defvalue, int):
try:
return int(value)
except ValueError:
except ValueError as exc:
raise ValueError(__('invalid number %r for config value %r, ignoring') %
(value, name))
(value, name)) from exc
elif hasattr(defvalue, '__call__'):
return value
elif defvalue is not None and not isinstance(defvalue, str):
@ -319,17 +327,17 @@ def eval_config_file(filename: str, tags: Tags) -> Dict[str, Any]:
execfile_(filename, namespace)
except SyntaxError as err:
msg = __("There is a syntax error in your configuration file: %s\n")
raise ConfigError(msg % err)
except SystemExit:
raise ConfigError(msg % err) from err
except SystemExit as exc:
msg = __("The configuration file (or one of the modules it imports) "
"called sys.exit()")
raise ConfigError(msg)
raise ConfigError(msg) from exc
except ConfigError:
# pass through ConfigError from conf.py as is. It will be shown in console.
raise
except Exception:
except Exception as exc:
msg = __("There is a programmable error in your configuration file:\n\n%s")
raise ConfigError(msg % traceback.format_exc())
raise ConfigError(msg % traceback.format_exc()) from exc
return namespace
@ -359,6 +367,18 @@ def convert_source_suffix(app: "Sphinx", config: Config) -> None:
"But `%r' is given." % source_suffix))
def convert_highlight_options(app: "Sphinx", config: Config) -> None:
"""Convert old styled highlight_options to new styled one.
* old style: options
* new style: dict that maps language names to options
"""
options = config.highlight_options
if options and not all(isinstance(v, dict) for v in options.values()):
# old styled option detected because all values are not dictionary.
config.highlight_options = {config.highlight_language: options} # type: ignore
def init_numfig_format(app: "Sphinx", config: Config) -> None:
"""Initialize :confval:`numfig_format`."""
numfig_format = {'section': _('Section %s'),
@ -479,6 +499,7 @@ def check_master_doc(app: "Sphinx", env: "BuildEnvironment", added: Set[str],
def setup(app: "Sphinx") -> Dict[str, Any]:
app.connect('config-inited', convert_source_suffix, priority=800)
app.connect('config-inited', convert_highlight_options, priority=800)
app.connect('config-inited', init_numfig_format, priority=800)
app.connect('config-inited', correct_copyright_year, priority=800)
app.connect('config-inited', check_confval_types, priority=800)

View File

@ -4,7 +4,7 @@
Sphinx deprecation classes and utilities.
: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.
"""
@ -26,30 +26,46 @@ class RemovedInSphinx50Warning(PendingDeprecationWarning):
pass
class RemovedInSphinx60Warning(PendingDeprecationWarning):
pass
RemovedInNextVersionWarning = RemovedInSphinx40Warning
def deprecated_alias(modname: str, objects: Dict, warning: "Type[Warning]") -> None:
def deprecated_alias(modname: str, objects: Dict[str, object],
warning: "Type[Warning]", names: Dict[str, str] = None) -> None:
module = import_module(modname)
sys.modules[modname] = _ModuleWrapper(module, modname, objects, warning) # type: ignore
sys.modules[modname] = _ModuleWrapper( # type: ignore
module, modname, objects, warning, names)
class _ModuleWrapper:
def __init__(self, module: Any, modname: str, objects: Dict, warning: "Type[Warning]"
) -> None:
def __init__(self, module: Any, modname: str,
objects: Dict[str, object],
warning: "Type[Warning]",
names: Dict[str, str]) -> None:
self._module = module
self._modname = modname
self._objects = objects
self._warning = warning
self._names = names
def __getattr__(self, name: str) -> Any:
if name in self._objects:
warnings.warn("%s.%s is deprecated. Check CHANGES for Sphinx "
"API modifications." % (self._modname, name),
self._warning, stacklevel=3)
return self._objects[name]
if name not in self._objects:
return getattr(self._module, name)
return getattr(self._module, name)
canonical_name = self._names.get(name, None)
if canonical_name is not None:
warnings.warn(
"The alias '{}.{}' is deprecated, use '{}' instead. Check CHANGES for "
"Sphinx API modifications.".format(self._modname, name, canonical_name),
self._warning, stacklevel=3)
else:
warnings.warn("{}.{} is deprecated. Check CHANGES for Sphinx "
"API modifications.".format(self._modname, name),
self._warning, stacklevel=3)
return self._objects[name]
class DeprecatedDict(dict):

View File

@ -4,13 +4,12 @@
Handlers for additional ReST directives.
: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.
"""
import re
from typing import Any, Dict, List, Tuple
from typing import cast
from typing import Any, Dict, Generic, List, Tuple, TypeVar, cast
from docutils import nodes
from docutils.nodes import Node
@ -18,9 +17,8 @@ from docutils.parsers.rst import directives, roles
from sphinx import addnodes
from sphinx.addnodes import desc_signature
from sphinx.deprecation import (
RemovedInSphinx40Warning, RemovedInSphinx50Warning, deprecated_alias
)
from sphinx.deprecation import (RemovedInSphinx40Warning, RemovedInSphinx50Warning,
deprecated_alias)
from sphinx.util import docutils
from sphinx.util.docfields import DocFieldTransformer, Field, TypedField
from sphinx.util.docutils import SphinxDirective
@ -35,6 +33,8 @@ if False:
nl_escape_re = re.compile(r'\\\n')
strip_backslash_re = re.compile(r'\\(.)')
T = TypeVar('T')
def optional_int(argument: str) -> int:
"""
@ -49,7 +49,7 @@ def optional_int(argument: str) -> int:
return value
class ObjectDescription(SphinxDirective):
class ObjectDescription(SphinxDirective, Generic[T]):
"""
Directive to describe a class, function or similar object. Not used
directly, but subclassed (in domain-specific directives) to add custom
@ -99,7 +99,7 @@ class ObjectDescription(SphinxDirective):
else:
return [line.strip() for line in lines]
def handle_signature(self, sig: str, signode: desc_signature) -> Any:
def handle_signature(self, sig: str, signode: desc_signature) -> T:
"""
Parse the signature *sig* into individual nodes and append them to
*signode*. If ValueError is raised, parsing is aborted and the whole
@ -111,7 +111,7 @@ class ObjectDescription(SphinxDirective):
"""
raise ValueError
def add_target_and_index(self, name: Any, sig: str, signode: desc_signature) -> None:
def add_target_and_index(self, name: T, sig: str, signode: desc_signature) -> None:
"""
Add cross-reference IDs and entries to self.indexnode, if applicable.
@ -175,7 +175,7 @@ class ObjectDescription(SphinxDirective):
if self.domain:
node['classes'].append(self.domain)
self.names = [] # type: List[Any]
self.names = [] # type: List[T]
signatures = self.get_signatures()
for i, sig in enumerate(signatures):
# add a signature node for each signature in the current unit
@ -266,16 +266,10 @@ class DefaultDomain(SphinxDirective):
self.env.temp_data['default_domain'] = self.env.domains.get(domain_name)
return []
from sphinx.directives.code import ( # noqa
Highlight, CodeBlock, LiteralInclude
)
from sphinx.directives.other import ( # noqa
TocTree, Author, VersionChange, SeeAlso,
TabularColumns, Centered, Acks, HList, Only, Include, Class
)
from sphinx.directives.patches import ( # noqa
Figure, Meta
)
from sphinx.directives.code import CodeBlock, Highlight, LiteralInclude # noqa
from sphinx.directives.other import (Acks, Author, Centered, Class, HList, Include, # noqa
Only, SeeAlso, TabularColumns, TocTree, VersionChange)
from sphinx.directives.patches import Figure, Meta # noqa
from sphinx.domains.index import IndexDirective # noqa
deprecated_alias('sphinx.directives',
@ -298,13 +292,35 @@ deprecated_alias('sphinx.directives',
'Figure': Figure,
'Meta': Meta,
},
RemovedInSphinx40Warning)
RemovedInSphinx40Warning,
{
'Highlight': 'sphinx.directives.code.Highlight',
'CodeBlock': 'sphinx.directives.code.CodeBlock',
'LiteralInclude': 'sphinx.directives.code.LiteralInclude',
'TocTree': 'sphinx.directives.other.TocTree',
'Author': 'sphinx.directives.other.Author',
'Index': 'sphinx.directives.other.IndexDirective',
'VersionChange': 'sphinx.directives.other.VersionChange',
'SeeAlso': 'sphinx.directives.other.SeeAlso',
'TabularColumns': 'sphinx.directives.other.TabularColumns',
'Centered': 'sphinx.directives.other.Centered',
'Acks': 'sphinx.directives.other.Acks',
'HList': 'sphinx.directives.other.HList',
'Only': 'sphinx.directives.other.Only',
'Include': 'sphinx.directives.other.Include',
'Class': 'sphinx.directives.other.Class',
'Figure': 'sphinx.directives.patches.Figure',
'Meta': 'sphinx.directives.patches.Meta',
})
deprecated_alias('sphinx.directives',
{
'DescDirective': ObjectDescription,
},
RemovedInSphinx50Warning)
RemovedInSphinx50Warning,
{
'DescDirective': 'sphinx.directives.ObjectDescription',
})
def setup(app: "Sphinx") -> Dict[str, Any]:

View File

@ -2,11 +2,12 @@
sphinx.directives.code
~~~~~~~~~~~~~~~~~~~~~~
: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.
"""
import sys
import textwrap
import warnings
from difflib import unified_diff
from typing import Any, Dict, List, Tuple
@ -19,9 +20,9 @@ from docutils.statemachine import StringList
from sphinx import addnodes
from sphinx.config import Config
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.directives import optional_int
from sphinx.locale import __
from sphinx.util import logging
from sphinx.util import parselinenos
from sphinx.util import logging, parselinenos
from sphinx.util.docutils import SphinxDirective
if False:
@ -69,10 +70,10 @@ class HighlightLang(Highlight):
def dedent_lines(lines: List[str], dedent: int, location: Tuple[str, int] = None) -> List[str]:
if not dedent:
return lines
return textwrap.dedent(''.join(lines)).splitlines(True)
if any(s[:dedent].strip() for s in lines):
logger.warning(__('Over dedent has detected'), location=location)
logger.warning(__('non-whitespace stripped by dedent'), location=location)
new_lines = []
for line in lines:
@ -118,7 +119,7 @@ class CodeBlock(SphinxDirective):
option_spec = {
'force': directives.flag,
'linenos': directives.flag,
'dedent': int,
'dedent': optional_int,
'lineno-start': int,
'emphasize-lines': directives.unchanged_required,
'caption': directives.unchanged_required,
@ -227,12 +228,13 @@ class LiteralIncludeReader:
text = text.expandtabs(self.options['tab-width'])
return text.splitlines(True)
except OSError:
raise OSError(__('Include file %r not found or reading it failed') % filename)
except UnicodeError:
except OSError as exc:
raise OSError(__('Include file %r not found or reading it failed') %
filename) from exc
except UnicodeError as exc:
raise UnicodeError(__('Encoding %r used for reading included file %r seems to '
'be wrong, try giving an :encoding: option') %
(self.encoding, filename))
(self.encoding, filename)) from exc
def read(self, location: Tuple[str, int] = None) -> Tuple[str, int]:
if 'diff' in self.options:
@ -391,7 +393,7 @@ class LiteralInclude(SphinxDirective):
optional_arguments = 0
final_argument_whitespace = True
option_spec = {
'dedent': int,
'dedent': optional_int,
'linenos': directives.flag,
'lineno-start': int,
'lineno-match': directives.flag,

View File

@ -2,13 +2,12 @@
sphinx.directives.other
~~~~~~~~~~~~~~~~~~~~~~~
: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.
"""
import re
from typing import Any, Dict, List
from typing import cast
from typing import Any, Dict, List, cast
from docutils import nodes
from docutils.nodes import Element, Node
@ -21,7 +20,7 @@ from sphinx import addnodes
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
from sphinx.domains.changeset import VersionChange # NOQA # for compatibility
from sphinx.locale import _
from sphinx.util import url_re, docname_join
from sphinx.util import docname_join, url_re
from sphinx.util.docutils import SphinxDirective
from sphinx.util.matching import Matcher, patfilter
from sphinx.util.nodes import explicit_title_re
@ -368,7 +367,10 @@ deprecated_alias('sphinx.directives.other',
{
'Index': IndexDirective,
},
RemovedInSphinx40Warning)
RemovedInSphinx40Warning,
{
'Index': 'sphinx.domains.index.IndexDirective',
})
def setup(app: "Sphinx") -> Dict[str, Any]:

View File

@ -2,17 +2,16 @@
sphinx.directives.patches
~~~~~~~~~~~~~~~~~~~~~~~~~
: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.
"""
from typing import Any, Dict, List, Tuple
from typing import cast
from typing import Any, Dict, List, Tuple, cast
from docutils import nodes
from docutils.nodes import Node, make_id, system_message
from docutils.parsers.rst import directives
from docutils.parsers.rst.directives import images, html, tables
from docutils.parsers.rst.directives import html, images, tables
from sphinx import addnodes
from sphinx.directives import optional_int

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