Merge remote-tracking branch 'upstream/3.x' into exclude-members-fix

This commit is contained in:
pbudzyns 2021-02-01 10:46:44 +01:00
commit 270921d73a
455 changed files with 10059 additions and 3870 deletions

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

View File

@ -8,7 +8,7 @@ jobs:
strategy:
fail-fast: false
matrix:
tool: [docslint, flake8, mypy, twine]
tool: [docslint, flake8, isort, mypy, twine]
steps:
- uses: actions/checkout@v2

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:

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,46 +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
- 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 -- -vv; fi
- if [ $IS_PYTHON = false ]; then npm test; fi
after_success:
- if [[ -e .coverage ]]; then codecov -e $TOXENV; fi

346
CHANGES
View File

@ -1,4 +1,127 @@
Release 3.3.0 (in development)
Release 3.5.0 (in development)
==============================
Dependencies
------------
* LaTeX: ``multicol`` (it is anyhow a required part of the official latex2e
base distribution)
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`
* #1638: html: Add permalink icons to glossary terms
* #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
* #7642: std domain: Optimize case-insensitive match of term
* #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
* #8134: autodoc: crashes when mocked decorator takes arguments
* #8306: autosummary: mocked modules are documented as empty page when using
:recursive: option
* #8232: graphviz: Image node is not rendered if graph file is in subdirectory
* #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
* #8123: html search: fix searching for terms containing + (Requires a custom
search language that does not split on +)
* #8665: html theme: Could not override globaltoc_maxdepth in theme.conf
* #8446: html: consecutive spaces are displayed as single space
* #8745: i18n: crashes with KeyError when translation message adds a new auto
footnote reference
* #4304: linkcheck: Fix race condition that could lead to checking the
availability of the same URL twice
* #7118: sphinx-quickstart: questionare got Mojibake if libreadline unavailable
* #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
* #8756: viewcode: highlighted code is generated even if not referenced
* #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
* #7576: LaTeX with French babel and memoir crash: "Illegal parameter number
in definition of ``\FNH@prefntext``"
* #8072: LaTeX: Directive :rst:dir:`hlist` not implemented in LaTeX
* #8214: LaTeX: The :rst:role:`index` role and the glossary generate duplicate
entries in the LaTeX index (if both used for same term)
* #8735: LaTeX: wrong internal links in pdf to captioned code-blocks when
:confval:`numfig` is not True
* #8442: LaTeX: some indexed terms are ignored when using xelatex engine
(or pdflatex and :confval:`latex_use_xindy` set to True) with memoir class
* #8780: LaTeX: long words in narrow columns may not be hyphenated
* #8788: LaTeX: ``\titleformat`` last argument in sphinx.sty should be
bracketed, not braced (and is anyhow not needed)
Testing
--------
Release 3.4.4 (in development)
==============================
Dependencies
@ -10,6 +133,175 @@ 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.
* #8796: LaTeX: potentially critical low level TeX coding mistake has gone
unnoticed so far
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``
@ -26,6 +318,15 @@ Features added
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
----------
@ -43,52 +344,45 @@ Bugs fixed
* #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.2 (in development)
==============================
Dependencies
------------
Incompatible changes
--------------------
Deprecated
----------
Features added
--------------
Bugs fixed
----------
* #8188: C, add missing items to internal object types dictionary,
e.g., preventing intersphinx from resolving them.
Testing
--------
Release 3.2.1 (released Aug 14, 2020)
=====================================

View File

@ -14,4 +14,5 @@ You can also browse it from this repository from
``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/>`__

View File

@ -1,7 +1,7 @@
License for Sphinx
==================
Copyright (c) 2007-2020 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

@ -66,11 +66,11 @@ doclinter:
.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:

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

View File

@ -33,9 +33,9 @@
<li>{%trans path=pathto('ext/builtins')%}<b>Extensions:</b> automatic testing of code snippets, inclusion of
docstrings from Python modules (API docs), and
<a href="{{ path }}#builtin-sphinx-extensions">more</a>{%endtrans%}</li>
<li>{%trans path=pathto('develop')%}<b>Contributed extensions:</b> more than
50 extensions <a href="{{ path }}#extensions">contributed by users</a>
in a second repository; most of them installable from PyPI{%endtrans%}</li>
<li>{%trans path=pathto("usage/extensions")%}<b>Contributed extensions:</b> dozens of
extensions <a href="{{ path }}#third-party-extensions">contributed by users</a>;
most of them installable from PyPI{%endtrans%}</li>
</ul>
<p>{%trans%}
Sphinx uses <a href="http://docutils.sourceforge.net/rst.html">reStructuredText</a>

View File

@ -67,7 +67,7 @@
<li><a href="{{ pathto('index') }}">Home</a></li>
<li><a href="{{ pathto('usage/installation') }}">Get it</a></li>
<li><a href="{{ pathto('contents') }}">Docs</a></li>
<li><a href="{{ pathto('develop') }}">Extend/Develop</a></li>
<li><a href="{{ pathto('development') }}">Extend</a></li>
</ul>
<div>
<a href="{{ pathto('index') }}">

View File

@ -8,4 +8,9 @@
Changelog
=========
.. raw:: latex
\hypersetup{bookmarksdepth=1}% pdf bookmarks
\addtocontents{toc}{\protect\setcounter{tocdepth}{1}}%
.. include:: ../CHANGES

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'
@ -69,8 +69,15 @@ latex_elements = {
\substitutefont{X2}{\sfdefault}{cmss}
\substitutefont{X2}{\ttdefault}{cmtt}
''',
'passoptionstopackages': '\\PassOptionsToPackage{svgnames}{xcolor}',
'preamble': '\\DeclareUnicodeCharacter{229E}{\\ensuremath{\\boxplus}}',
'passoptionstopackages': r'''
\PassOptionsToPackage{svgnames}{xcolor}
\PassOptionsToPackage{bookmarksdepth=3}{hyperref}% depth of pdf bookmarks
''',
'preamble': r'''
\DeclareUnicodeCharacter{229E}{\ensuremath{\boxplus}}
\setcounter{tocdepth}{3}% depth of what is kept from toc file
\setcounter{secnumdepth}{1}% depth of section numbering
''',
'fvset': '\\fvset{fontsize=auto}',
# fix missing index entry due to RTD doing only once pdflatex after makeindex
'printindex': r'''
@ -110,7 +117,10 @@ texinfo_documents = [
1),
]
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

@ -1,153 +0,0 @@
:orphan:
Sphinx development
==================
Sphinx is a maintained by a group of volunteers. We value every contribution!
* The code can be found in a Git repository, at
https://github.com/sphinx-doc/sphinx/.
* Issues and feature requests should be raised in the `tracker
<https://github.com/sphinx-doc/sphinx/issues>`_.
* The mailing list for development is at `Google Groups
<https://groups.google.com/forum/#!forum/sphinx-dev>`_.
* There is also the #sphinx-doc IRC channel on `freenode
<https://freenode.net/>`_.
For more about our development process and methods, refer to
:doc:`/internals/index`.
Extensions
==========
To learn how to write your own extension, see :ref:`dev-extensions`.
The `sphinx-contrib <https://bitbucket.org/birkenfeld/sphinx-contrib/>`_
repository contains many contributed extensions. Some of them have their own
releases on PyPI, others you can install from a checkout.
This is the current list of contributed extensions in that repository:
- aafig: render embedded ASCII art as nice images using aafigure_
- actdiag: embed activity diagrams by using actdiag_
- adadomain: an extension for Ada support (Sphinx 1.0 needed)
- ansi: parse ANSI color sequences inside documents
- argdoc: automatically generate documentation for command-line arguments,
descriptions and help text
- astah: embed diagram by using astah
- autoanysrc: Gather reST documentation from any source files
- autorun: Execute code in a ``runblock`` directive
- beamer_: A builder for Beamer (LaTeX) output.
- blockdiag: embed block diagrams by using blockdiag_
- cacoo: embed diagram from Cacoo
- cf3domain: a domain for CFEngine 3 policies
- cheader: The missing c:header directive for Sphinx's built-in C domain
- cheeseshop: easily link to PyPI packages
- clearquest: create tables from ClearQuest_ queries
- cmakedomain_: a domain for CMake_
- coffeedomain: a domain for (auto)documenting CoffeeScript source code
- context: a builder for ConTeXt
- disqus: embed Disqus comments in documents
- documentedlist: converts a Python list to a table in the generated
documentation
- doxylink: Link to external Doxygen-generated HTML documentation
- domaintools_: A tool for easy domain creation
- email: obfuscate email addresses
- erlangdomain: an extension for Erlang support (Sphinx 1.0 needed)
- exceltable: embed Excel spreadsheets into documents using exceltable_
- feed: an extension for creating syndication feeds and time-based overviews
from your site content
- findanything_: an extension to add Sublime Text 2-like findanything panels
to your documentation to find pages, sections and index entries while typing
- gnuplot: produces images using gnuplot_ language
- googleanalytics: track web visitor statistics by using `Google Analytics`_
- googlechart: embed charts by using `Google Chart`_
- googlemaps: embed maps by using `Google Maps`_
- httpdomain: a domain for documenting RESTful HTTP APIs
- hyphenator: client-side hyphenation of HTML using hyphenator_
- imgur: embed Imgur images, albums, and metadata in documents
- inlinesyntaxhighlight_: inline syntax highlighting
- lassodomain: a domain for documenting Lasso_ source code
- libreoffice: an extension to include any drawing supported by LibreOffice
(e.g. odg, vsd, ...)
- lilypond: an extension inserting music scripts from Lilypond_ in PNG format
- makedomain_: a domain for `GNU Make`_
- matlabdomain: document MATLAB_ code
- mockautodoc: mock imports
- mscgen: embed mscgen-formatted MSC (Message Sequence Chart)s
- napoleon: supports `Google style`_ and `NumPy style`_ docstrings
- nicovideo: embed videos from nicovideo
- nwdiag: embed network diagrams by using nwdiag_
- omegat: support tools to collaborate with OmegaT_ (Sphinx 1.1 needed)
- osaka: convert standard Japanese doc to Osaka dialect (this is a joke
extension)
- paverutils: an alternate integration of Sphinx with Paver_
- phpdomain: an extension for PHP support
- plantuml: embed UML diagram by using PlantUML_
- py_directive: Execute python code in a ``py`` directive and return a math
node
- rawfiles: copy raw files, like a CNAME
- requirements: declare requirements wherever you need (e.g. in test
docstrings), mark statuses and collect them in a single list
- restbuilder: a builder for reST (reStructuredText) files
- rubydomain: an extension for Ruby support (Sphinx 1.0 needed)
- sadisplay: display SqlAlchemy model sadisplay_
- sdedit: an extension inserting sequence diagram by using Quick Sequence
Diagram Editor (sdedit_)
- seqdiag: embed sequence diagrams by using seqdiag_
- slide: embed presentation slides on slideshare_ and other sites
- swf_: embed flash files
- sword: an extension inserting Bible verses from Sword_
- tikz: draw pictures with the `TikZ/PGF LaTeX package`_
- traclinks: create TracLinks_ to a Trac_ instance from within Sphinx
- versioning: Sphinx extension that allows building versioned docs for
self-hosting
- whooshindex: whoosh indexer extension
- youtube: embed videos from YouTube_
- zopeext: provide an ``autointerface`` directive for using `Zope interfaces`_
See the :doc:`extension tutorials <../development/tutorials/index>` on getting
started with writing your own extensions.
.. _aafigure: https://launchpad.net/aafigure
.. _gnuplot: http://www.gnuplot.info/
.. _paver: https://paver.readthedocs.io/en/latest/
.. _Sword: https://www.crosswire.org/sword/
.. _Lilypond: http://lilypond.org/
.. _sdedit: http://sdedit.sourceforge.net/
.. _Trac: https://trac.edgewall.org/
.. _TracLinks: https://trac.edgewall.org/wiki/TracLinks
.. _OmegaT: https://omegat.org/
.. _PlantUML: http://plantuml.com/
.. _PyEnchant: https://pythonhosted.org/pyenchant/
.. _sadisplay: https://bitbucket.org/estin/sadisplay/wiki/Home
.. _blockdiag: http://blockdiag.com/en/
.. _seqdiag: http://blockdiag.com/en/
.. _actdiag: http://blockdiag.com/en/
.. _nwdiag: http://blockdiag.com/en/
.. _Google Analytics: https://www.google.com/analytics/
.. _Google Chart: https://developers.google.com/chart/
.. _Google Maps: https://www.google.com/maps
.. _Google style: https://google.github.io/styleguide/pyguide.html
.. _NumPy style: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
.. _hyphenator: https://github.com/mnater/hyphenator
.. _exceltable: https://pythonhosted.org/sphinxcontrib-exceltable/
.. _YouTube: https://www.youtube.com/
.. _ClearQuest: https://www.ibm.com/us-en/marketplace/rational-clearquest
.. _Zope interfaces: https://zopeinterface.readthedocs.io/en/latest/README.html
.. _slideshare: https://www.slideshare.net/
.. _TikZ/PGF LaTeX package: https://sourceforge.net/projects/pgf/
.. _MATLAB: https://www.mathworks.com/products/matlab.html
.. _swf: https://github.com/sphinx-contrib/swf
.. _findanything: https://github.com/sphinx-contrib/findanything
.. _cmakedomain: https://github.com/sphinx-contrib/cmakedomain
.. _GNU Make: https://www.gnu.org/software/make/
.. _makedomain: https://github.com/sphinx-contrib/makedomain
.. _inlinesyntaxhighlight: https://sphinxcontrib-inlinesyntaxhighlight.readthedocs.io/
.. _CMake: https://cmake.org
.. _domaintools: https://github.com/sphinx-contrib/domaintools
.. _restbuilder: https://pypi.org/project/sphinxcontrib-restbuilder/
.. _Lasso: http://www.lassosoft.com/
.. _beamer: https://pypi.org/project/sphinxcontrib-beamer/

View File

@ -2,10 +2,12 @@
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

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

@ -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
@ -186,6 +186,7 @@ type for that event::
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)
@ -284,6 +285,14 @@ Here is a more detailed list of these events.
.. 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
@ -360,6 +369,9 @@ Here is a more detailed list of these events.
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

@ -12,20 +12,142 @@ The following is a list of deprecated interfaces.
.. tabularcolumns:: |>{\raggedright}\Y{.4}|>{\centering}\Y{.1}|>{\centering}\Y{.12}|>{\raggedright\arraybackslash}\Y{.38}|
.. |LaTeXHyphenate| raw:: latex
\hspace{0pt}
.. list-table:: deprecated APIs
:header-rows: 1
:class: deprecated
:widths: 40, 10, 10, 40
* - Target
- |LaTeXHyphenate|\ Deprecated
- Deprecated
- (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

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

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

@ -138,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.
@ -272,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.
@ -1018,6 +1024,14 @@ Environments
Miscellany
~~~~~~~~~~
- Every text paragraph in document body starts with ``\sphinxAtStartPar``.
Currently, this is used to insert a zero width horizontal skip which
is a trick to allow TeX hyphenation of the first word of a paragraph
in a narrow context (like a table cell). For ``'lualatex'`` which
does not need the trick, the ``\sphinxAtStartPar`` does nothing.
.. versionadded:: 3.5.0
- The section, subsection, ... headings are set using *titlesec*'s
``\titleformat`` command.

View File

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

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

@ -73,6 +73,12 @@ Project information
A copyright statement in the style ``'2008, Author Name'``.
.. confval:: project_copyright
An alias of :confval:`copyright`.
.. versionadded:: 3.5
.. confval:: version
The major project version, used as the replacement for ``|version|``. For
@ -316,6 +322,7 @@ General configuration
* ``toc.circular``
* ``toc.secnum``
* ``epub.unknown_project_files``
* ``epub.duplicated_toc_entry``
* ``autosectionlabel.*``
You can choose from these types.
@ -340,6 +347,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 +562,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 +583,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
@ -932,8 +958,11 @@ 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
@ -991,7 +1020,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
@ -1007,7 +1043,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
@ -1091,6 +1134,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
@ -2520,6 +2580,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
---------------------------

View File

@ -168,7 +168,7 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
``: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
@ -183,7 +183,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
@ -193,6 +193,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::
@ -337,6 +347,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
@ -376,6 +395,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::
@ -553,7 +575,7 @@ There are also config values that you can set:
...
If you set ``autodoc_type_aliases`` as
``{'AliasType': 'your.module.TypeAlias'}``, it generates a following document
``{'AliasType': 'your.module.AliasType'}``, it generates the following document
internally::
.. py:function:: f() -> your.module.AliasType:

View File

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

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

@ -41,22 +41,20 @@ These extensions are built in and can be activated by respective entries in the
Third-party extensions
----------------------
.. todo:: This should reference the GitHub organization now
You can find several extensions contributed by users in the `sphinx-contrib`__
organization. If you wish to include your extension in this organization,
simply follow the instructions provided in the `github-administration`__
project. This is optional and there are several extensions hosted elsewhere.
The `awesome-sphinxdoc`__ project contains a curated list of Sphinx packages,
and many packages use the `Framework :: Sphinx :: Extension`__ and
`Framework :: Sphinx :: Theme`__ trove classifiers for Sphinx extensions and
themes, respectively.
You can find several extensions contributed by users in the `Sphinx Contrib`_
repository. It is open for anyone who wants to maintain an extension publicly;
just send a short message asking for write permissions.
There are also several extensions hosted elsewhere. The `Sphinx extension
survey <https://sphinxext-survey.readthedocs.io/>`__ and `awesome-sphinxdoc
<https://github.com/yoloseem/awesome-sphinxdoc>`__ contains a comprehensive
list.
If you write an extension that you think others will find useful or you think
should be included as a part of Sphinx, please write to the project mailing
list (`join here <https://groups.google.com/forum/#!forum/sphinx-dev>`_).
.. _Sphinx Contrib: https://bitbucket.org/birkenfeld/sphinx-contrib
.. __: https://github.com/sphinx-contrib/
.. __: https://github.com/sphinx-contrib/github-administration
.. __: https://github.com/yoloseem/awesome-sphinxdoc
.. __: https://pypi.org/search/?c=Framework+%3A%3A+Sphinx+%3A%3A+Extension
.. __: https://pypi.org/search/?c=Framework+%3A%3A+Sphinx+%3A%3A+Theme
Where to put your own extensions?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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

@ -203,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::
@ -221,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::
@ -238,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
@ -246,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
@ -275,6 +302,7 @@ sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
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
@ -511,3 +539,35 @@ sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
: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

@ -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
@ -742,6 +760,9 @@ __ http://pygments.org/docs/lexers
.. versionchanged:: 2.1
Added the ``force`` option.
.. versionchanged:: 3.5
Support automatic dedent.
.. _glossary-directive:
Glossary
@ -1199,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

@ -18,6 +18,7 @@ module.exports = function(config) {
'sphinx/themes/basic/static/underscore.js',
'sphinx/themes/basic/static/jquery.js',
'sphinx/themes/basic/static/doctools.js',
'sphinx/themes/basic/static/searchtools.js',
'tests/js/*.js'
],

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.780',
'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:
@ -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.3.0+'
__released__ = '3.3.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.3.0' # used when Sphinx builds its own docs
#:
#: .. versionadded:: 1.2
#: Before version 1.2, check the string ``sphinx.__version__``.
version_info = (3, 3, 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.
"""

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,7 +18,7 @@ import warnings
from collections import deque
from io import StringIO
from os import path
from typing import Any, Callable, Dict, IO, List, Optional, Tuple, Union
from typing import IO, Any, Callable, Dict, List, Optional, Tuple, Union
from docutils import nodes
from docutils.nodes import Element, TextElement
@ -28,7 +28,7 @@ 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
@ -43,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
@ -56,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
@ -135,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,
@ -294,8 +294,8 @@ class Sphinx:
if catalog.domain == 'sphinx' and catalog.is_outdated():
catalog.write_mo(self.config.language)
locale_dirs = [None] # type: List[Optional[str]]
locale_dirs += 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)
@ -404,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
"""
@ -420,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
@ -436,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)
@ -447,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
@ -459,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
@ -472,10 +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`.
If *override* is True, the given *builder* is forcedly installed even if
a builder having the same name is already installed.
: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.
@ -488,27 +499,34 @@ class Sphinx:
"""Register a configuration value.
This is necessary for Sphinx to recognize new values and set default
values accordingly. The *name* should be prefixed with the extension
name, to avoid clashes. The *default* value can be any Python object.
The string value *rebuild* must be one of those values:
values accordingly.
* ``'env'`` if a change in the setting only takes effect when a
document is parsed -- this means that the whole environment must be
rebuilt.
* ``'html'`` if a change in the setting needs a full rebuild of HTML
documents.
* ``''`` if a change in the setting will not need any special rebuild.
.. versionchanged:: 0.6
Changed *rebuild* from a simple boolean (equivalent to ``''`` or
``'env'``) to a string. However, booleans are still accepted and
converted internally.
:param name: The name of configuration value. It is recommended to be prefixed
with the extension name (ex. ``html_logo``, ``epub_title``)
:param default: The default value of the configuration.
:param rebuild: The condition of rebuild. It must be one of those values:
* ``'env'`` if a change in the setting only takes effect when a
document is parsed -- this means that the whole environment must be
rebuilt.
* ``'html'`` if a change in the setting needs a full rebuild of HTML
documents.
* ``''`` if a change in the setting will not need any special rebuild.
:param types: The type of configuration value. A list of types can be specified. For
example, ``[str]`` is used to describe a configuration that takes string
value.
.. versionchanged:: 0.4
If the *default* value is a callable, it will be called with the
config object as its argument in order to get the default value.
This can be used to implement config values whose default depends on
other values.
.. versionchanged:: 0.6
Changed *rebuild* from a simple boolean (equivalent to ``''`` or
``'env'``) to a string. However, booleans are still accepted and
converted internally.
"""
logger.debug('[app] adding config value: %r',
(name, default, rebuild) + ((types,) if types else ()))
@ -520,6 +538,8 @@ class Sphinx:
"""Register an event called *name*.
This is needed to be able to emit it.
:param name: The name of the event
"""
logger.debug('[app] adding event: %r', name)
self.events.add(name)
@ -532,8 +552,10 @@ class Sphinx:
builtin translator. This allows extensions to use custom translator
and define custom nodes for the translator (see :meth:`add_node`).
If *override* is True, the given *translator_class* is forcedly installed even if
a translator for *name* is already installed.
: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
@ -548,6 +570,11 @@ class Sphinx:
This is necessary for Docutils internals. It may also be used in the
future to validate nodes in the parsed documents.
:param node: A node class
:param kwargs: Visitor functions for each builder (see below)
:param override: If true, install the node forcedly even if another node is already
installed as the same name
Node visitor functions for the Sphinx HTML, LaTeX, text and manpage
writers can be given as keyword arguments: the keyword should be one or
more of ``'html'``, ``'latex'``, ``'text'``, ``'man'``, ``'texinfo'``
@ -569,9 +596,6 @@ 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.
"""
@ -591,24 +615,21 @@ class Sphinx:
Sphinx numbers the node automatically. And then the users can refer it
using :rst:role:`numref`.
*figtype* is a type of enumerable nodes. Each figtypes have individual
numbering sequences. As a system figtypes, ``figure``, ``table`` and
``code-block`` are defined. It is able to add custom nodes to these
default figtypes. It is also able to define new custom figtype if new
figtype is given.
*title_getter* is a getter function to obtain the title of node. It
takes an instance of the enumerable node, and it must return its title
as string. The title is used to the default title of references for
:rst:role:`ref`. By default, Sphinx searches
``docutils.nodes.caption`` or ``docutils.nodes.title`` from the node as
a title.
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.
:param node: A node class
:param figtype: The type of enumerable nodes. Each figtypes have individual numbering
sequences. As a system figtypes, ``figure``, ``table`` and
``code-block`` are defined. It is able to add custom nodes to these
default figtypes. It is also able to define new custom figtype if new
figtype is given.
:param title_getter: A getter function to obtain the title of node. It takes an
instance of the enumerable node, and it must return its title as
string. The title is used to the default title of references for
:rst:role:`ref`. By default, Sphinx searches
``docutils.nodes.caption`` or ``docutils.nodes.title`` from the
node as a title.
:param kwargs: Visitor functions for each builder (same as :meth:`add_node`)
:param override: If true, install the node forcedly even if another node is already
installed as the same name
.. versionadded:: 1.4
"""
@ -618,10 +639,10 @@ 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, a custom directive named ``my-directive`` would be added
like this:
@ -646,8 +667,8 @@ class Sphinx:
def setup(app):
add_directive('my-directive', MyDirective)
If *override* is True, the given *cls* is forcedly installed even if
a directive named as *name* is already installed.
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.
@ -666,13 +687,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 role: A role function
:param override: If true, install the role forcedly even if another role is already
installed as the same name
If *override* is True, the given *role* is forcedly installed even if
a role named as *name* is already installed.
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.
@ -708,11 +729,9 @@ class Sphinx:
def add_domain(self, domain: "Type[Domain]", override: bool = False) -> None:
"""Register a domain.
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.
:param domain: A domain class
:param override: If true, install the domain forcedly even if another domain
is already installed as the same name
.. versionadded:: 1.0
.. versionchanged:: 1.8
@ -727,8 +746,11 @@ 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.
:param domain: The name of target domain
:param name: A 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
.. versionadded:: 1.0
.. versionchanged:: 1.8
@ -743,8 +765,11 @@ 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.
:param domain: The name of target domain
:param name: A name of role
:param role: A role function
:param override: If true, install the role forcedly even if another role is already
installed as the same name
.. versionadded:: 1.0
.. versionchanged:: 1.8
@ -756,11 +781,12 @@ class Sphinx:
) -> None:
"""Register a custom index for a domain.
Add a custom *index* class to the domain named *domain*. *index* must
be a subclass of :class:`~sphinx.domains.Index`.
Add a custom *index* class to the domain named *domain*.
If *override* is True, the given *index* is forcedly installed even if
an index having the same name is already installed.
:param domain: The name of target domain
:param index: A index class
:param override: If true, install the index forcedly even if another index is
already installed as the same name
.. versionadded:: 1.0
.. versionchanged:: 1.8
@ -881,6 +907,8 @@ class Sphinx:
the list of transforms that are applied after Sphinx parses a reST
document.
:param transform: A transform class
.. list-table:: priority range categories for Sphinx transforms
:widths: 20,80
@ -913,25 +941,29 @@ class Sphinx:
Add the standard docutils :class:`Transform` subclass *transform* to
the list of transforms that are applied before Sphinx writes a
document.
:param transform: A transform class
"""
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::
@ -944,23 +976,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::
@ -975,6 +1027,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
@ -987,11 +1052,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:
@ -1000,7 +1068,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:
@ -1103,7 +1171,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
@ -1175,9 +1243,10 @@ class Sphinx:
def add_message_catalog(self, catalog: str, locale_dir: str) -> None:
"""Register a message catalog.
The *catalog* is a name of catalog, and *locale_dir* is a base path
of message catalog. For more details, see
:func:`sphinx.locale.get_translation()`.
:param catalog: A name of catalog
:param locale_dir: The base path of message catalog
For more details, see :func:`sphinx.locale.get_translation()`.
.. versionadded:: 1.8
"""
@ -1188,7 +1257,7 @@ class Sphinx:
def is_parallel_allowed(self, typ: str) -> bool:
"""Check parallel processing is allowed or not.
``typ`` is a type of processing; ``'read'`` or ``'write'``.
:param typ: A type of processing; ``'read'`` or ``'write'``.
"""
if typ == 'read':
attrname = 'parallel_read_safe'

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

View File

@ -4,23 +4,19 @@
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,

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,7 +18,6 @@ from sphinxcontrib.devhelp import DevhelpBuilder
from sphinx.application import Sphinx
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
deprecated_alias('sphinx.builders.devhelp',
{
'DevhelpBuilder': DevhelpBuilder,

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.
"""

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
@ -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', Any)
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,18 @@
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
@ -24,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, ENUM
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
@ -38,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
@ -89,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')
@ -112,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
@ -289,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)
@ -448,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]]
@ -462,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:
@ -1012,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:
@ -1071,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:
@ -1189,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]:
@ -1218,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')
@ -1243,9 +1272,14 @@ def setup(app: Sphinx) -> Dict[str, Any]:
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,21 +5,19 @@
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,

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

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.
"""

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,34 +13,55 @@ 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 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):
@ -77,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.
"""
@ -86,37 +107,59 @@ class CheckExternalLinksBuilder(Builder):
'%(outdir)s/output.txt')
def init(self) -> None:
self.to_ignore = [re.compile(x) for x in self.app.config.linkcheck_ignore]
self.hyperlinks = {} # type: Dict[str, Hyperlink]
self.to_ignore = [re.compile(x) for x in self.config.linkcheck_ignore]
self.anchors_ignore = [re.compile(x)
for x in self.app.config.linkcheck_anchors_ignore]
for x in self.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]]
in self.config.linkcheck_auth]
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
open(path.join(self.outdir, 'output.txt'), 'w').close()
# create JSON output file
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)
for i in range(self.config.linkcheck_workers):
thread = threading.Thread(target=self.check_thread, daemon=True)
thread.start()
self.workers.append(thread)
@property
def good(self) -> Set[str]:
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "good"),
RemovedInSphinx50Warning,
stacklevel=2,
)
return self._good
@property
def broken(self) -> Dict[str, str]:
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "broken"),
RemovedInSphinx50Warning,
stacklevel=2,
)
return self._broken
@property
def redirected(self) -> Dict[str, Tuple[str, int]]:
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,
} # type: Dict
if self.app.config.linkcheck_timeout:
kwargs['timeout'] = self.app.config.linkcheck_timeout
kwargs = {}
if self.config.linkcheck_timeout:
kwargs['timeout'] = self.config.linkcheck_timeout
def get_request_headers() -> Dict:
url = urlparse(uri)
@ -162,9 +205,9 @@ class CheckExternalLinksBuilder(Builder):
kwargs['headers'] = get_request_headers()
try:
if anchor and self.app.config.linkcheck_anchors:
if anchor and self.config.linkcheck_anchors:
# Read the whole document and see if #anchor exists
response = requests.get(req_url, stream=True, config=self.app.config,
response = requests.get(req_url, stream=True, config=self.config,
auth=auth_info, **kwargs)
response.raise_for_status()
found = check_anchor(response, unquote(anchor))
@ -175,29 +218,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.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.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:
@ -213,7 +269,7 @@ class CheckExternalLinksBuilder(Builder):
def check(docname: str) -> Tuple[str, str, int]:
# check for various conditions without bothering the network
if len(uri) == 0 or uri.startswith(('#', 'mailto:')):
if len(uri) == 0 or uri.startswith(('#', 'mailto:', 'tel:')):
return 'unchecked', '', 0
elif not uri.startswith(('http:', 'https:')):
if uri_re.match(uri):
@ -228,38 +284,97 @@ class CheckExternalLinksBuilder(Builder):
if rex.match(uri):
return 'ignored', '', 0
else:
self._broken[uri] = ''
return 'broken', '', 0
elif uri in self.good:
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
# need to actually check the URI
for _ in range(self.app.config.linkcheck_retries):
for _ in range(self.config.linkcheck_retries):
status, info, code = check_uri()
if status != "broken":
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
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)
self.rqueue.put((uri, docname, lineno, status, info, code))
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.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
@ -313,62 +428,71 @@ class CheckExternalLinksBuilder(Builder):
self.write_entry('redirected ' + text, docname, filename,
lineno, uri + ' to ' + info)
self.write_linkstat(linkstat)
else:
raise ValueError("Unknown status %s." % status)
def get_target_uri(self, docname: str, typ: str = None) -> str:
return ''
def write_entry(self, what: str, docname: str, filename: str, line: int,
uri: str) -> None:
self.txt_outfile.write("%s:%s: [%s] %s\n" % (filename, line, what, uri))
def get_outdated_docs(self) -> Set[str]:
return self.env.found_docs
def write_linkstat(self, data: dict) -> None:
self.json_outfile.write(json.dumps(data))
self.json_outfile.write('\n')
def prepare_writing(self, docnames: Set[str]) -> None:
return
def write_doc(self, docname: str, doctree: Node) -> None:
def finish(self) -> None:
logger.info('')
n = 0
for hyperlink in self.hyperlinks.values():
self.wqueue.put(hyperlink, False)
total_links = len(self.hyperlinks)
done = 0
with open(path.join(self.outdir, 'output.txt'), 'w') as self.txt_outfile,\
open(path.join(self.outdir, 'output.json'), 'w') as self.json_outfile:
while done < total_links:
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((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 doctree.traverse(nodes.reference):
for refnode in self.document.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
uri_info = Hyperlink(CHECK_IMMEDIATELY, uri, self.env.docname, lineno)
if uri not in hyperlinks:
hyperlinks[uri] = uri_info
# image nodes
for imgnode in doctree.traverse(nodes.image):
for imgnode in self.document.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:
output.write("%s:%s: [%s] %s\n" % (filename, line, what, uri))
def write_linkstat(self, data: dict) -> None:
with open(path.join(self.outdir, 'output.json'), 'a') as output:
output.write(json.dumps(data))
output.write('\n')
def finish(self) -> None:
for worker in self.workers:
self.wqueue.put((None, None, None), False)
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)
@ -380,6 +504,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 ensuredir, make_filename_from_project
from sphinx.writers.manpage import ManualPageWriter, ManualPageTranslator
from sphinx.writers.manpage import ManualPageTranslator, ManualPageWriter
logger = logging.getLogger(__name__)

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,7 +17,6 @@ import sphinx
from sphinx.application import Sphinx
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
deprecated_alias('sphinx.builders.qthelp',
{
'render_file': render_file,

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

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.
"""
@ -29,6 +29,7 @@ try:
readline.parse_and_bind("tab: complete")
USE_LIBEDIT = False
except ImportError:
readline = None
USE_LIBEDIT = False
from docutils.utils import column_width
@ -37,9 +38,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
@ -170,8 +170,11 @@ def do_prompt(text: str, default: str = None, validator: Callable[[str], Any] =
# sequence (see #5335). To avoid the problem, all prompts are not colored
# on libedit.
pass
else:
elif readline:
# pass input_mode=True if readline available
prompt = colorize(COLOR_QUESTION, prompt, input_mode=True)
else:
prompt = colorize(COLOR_QUESTION, prompt, input_mode=False)
x = term_input(prompt).strip()
if default and not x:
x = default
@ -489,8 +492,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', []),
@ -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
@ -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,6 +26,10 @@ class RemovedInSphinx50Warning(PendingDeprecationWarning):
pass
class RemovedInSphinx60Warning(PendingDeprecationWarning):
pass
RemovedInNextVersionWarning = RemovedInSphinx40Warning

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',

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,7 +70,7 @@ 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(__('non-whitespace stripped by dedent'), location=location)
@ -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,
@ -392,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
@ -277,6 +276,7 @@ class HList(SphinxDirective):
npercol, nmore = divmod(len(fulllist), ncolumns)
index = 0
newnode = addnodes.hlist()
newnode['ncolumns'] = str(ncolumns)
for column in range(ncolumns):
endindex = index + ((npercol + 1) if column < nmore else npercol)
bullet_list = nodes.bullet_list()

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

View File

@ -5,13 +5,12 @@
Support for domains, which are groupings of description directives
and roles describing e.g. constructs of one programming language.
: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 copy
from typing import Any, Callable, Dict, Iterable, List, NamedTuple, Tuple, Union
from typing import cast
from typing import Any, Callable, Dict, Iterable, List, NamedTuple, Tuple, Union, cast
from docutils import nodes
from docutils.nodes import Element, Node, system_message
@ -26,6 +25,7 @@ from sphinx.util.typing import RoleFunction
if False:
# For type annotation
from typing import Type # for python3.5.1
from sphinx.builders import Builder
from sphinx.environment import BuildEnvironment

View File

@ -4,15 +4,13 @@
The C language domain.
: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, Callable, Dict, Generator, Iterator, List, Type, TypeVar, Tuple, Union
)
from typing import cast
from typing import (Any, Callable, Dict, Generator, Iterator, List, Tuple, Type, TypeVar,
Union, cast)
from docutils import nodes
from docutils.nodes import Element, Node, TextElement, system_message
@ -31,15 +29,13 @@ from sphinx.roles import SphinxRole, XRefRole
from sphinx.transforms import SphinxTransform
from sphinx.transforms.post_transforms import ReferencesResolver
from sphinx.util import logging
from sphinx.util.cfamily import (
NoOldIdError, ASTBaseBase, ASTAttribute, ASTBaseParenExprList,
verify_description_mode, StringifyTransform,
BaseParser, DefinitionError, UnsupportedMultiCharacterCharLiteral,
identifier_re, anon_identifier_re, integer_literal_re, octal_literal_re,
hex_literal_re, binary_literal_re, integers_literal_suffix_re,
float_literal_re, float_literal_suffix_re,
char_literal_re
)
from sphinx.util.cfamily import (ASTAttribute, ASTBaseBase, ASTBaseParenExprList, BaseParser,
DefinitionError, NoOldIdError, StringifyTransform,
UnsupportedMultiCharacterCharLiteral, anon_identifier_re,
binary_literal_re, char_literal_re, float_literal_re,
float_literal_suffix_re, hex_literal_re, identifier_re,
integer_literal_re, integers_literal_suffix_re,
octal_literal_re, verify_description_mode)
from sphinx.util.docfields import Field, TypedField
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import make_refnode
@ -47,6 +43,11 @@ from sphinx.util.nodes import make_refnode
logger = logging.getLogger(__name__)
T = TypeVar('T')
DeclarationType = Union[
"ASTStruct", "ASTUnion", "ASTEnum", "ASTEnumerator",
"ASTType", "ASTTypeWithInit", "ASTMacro",
]
# https://en.cppreference.com/w/c/keyword
_keywords = [
'auto', 'break', 'case', 'char', 'const', 'continue', 'default', 'do', 'double',
@ -136,8 +137,7 @@ class ASTIdentifier(ASTBaseBase):
reftype='identifier',
reftarget=targetText, modname=None,
classname=None)
key = symbol.get_lookup_key()
pnode['c:parent_key'] = key
pnode['c:parent_key'] = symbol.get_lookup_key()
if self.is_anon():
pnode += nodes.strong(text="[anonymous]")
else:
@ -636,6 +636,10 @@ class ASTFunctionParameter(ASTBase):
self.arg = arg
self.ellipsis = ellipsis
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
# the anchor will be our parent
return symbol.parent.declaration.get_id(version, prefixed=False)
def _stringify(self, transform: StringifyTransform) -> str:
if self.ellipsis:
return '...'
@ -1149,6 +1153,9 @@ class ASTType(ASTBase):
def name(self) -> ASTNestedName:
return self.decl.name
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
return symbol.get_full_nested_name().get_id(version)
@property
def function_params(self) -> List[ASTFunctionParameter]:
return self.decl.function_params
@ -1191,6 +1198,9 @@ class ASTTypeWithInit(ASTBase):
def name(self) -> ASTNestedName:
return self.type.name
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
return self.type.get_id(version, objectType, symbol)
def _stringify(self, transform: StringifyTransform) -> str:
res = []
res.append(transform(self.type))
@ -1242,6 +1252,9 @@ class ASTMacro(ASTBase):
def name(self) -> ASTNestedName:
return self.ident
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
return symbol.get_full_nested_name().get_id(version)
def _stringify(self, transform: StringifyTransform) -> str:
res = []
res.append(transform(self.ident))
@ -1342,7 +1355,8 @@ class ASTEnumerator(ASTBase):
class ASTDeclaration(ASTBaseBase):
def __init__(self, objectType: str, directiveType: str, declaration: Any,
def __init__(self, objectType: str, directiveType: str,
declaration: Union[DeclarationType, ASTFunctionParameter],
semicolon: bool = False) -> None:
self.objectType = objectType
self.directiveType = directiveType
@ -1359,18 +1373,20 @@ class ASTDeclaration(ASTBaseBase):
@property
def name(self) -> ASTNestedName:
return self.declaration.name
decl = cast(DeclarationType, self.declaration)
return decl.name
@property
def function_params(self) -> List[ASTFunctionParameter]:
if self.objectType != 'function':
return None
return self.declaration.function_params
decl = cast(ASTType, self.declaration)
return decl.function_params
def get_id(self, version: int, prefixed: bool = True) -> str:
if self.objectType == 'enumerator' and self.enumeratorScopedSymbol:
return self.enumeratorScopedSymbol.declaration.get_id(version, prefixed)
id_ = self.symbol.get_full_nested_name().get_id(version)
id_ = self.declaration.get_id(version, self.objectType, self.symbol)
if prefixed:
return _id_prefix[version] + id_
else:
@ -1413,7 +1429,8 @@ class ASTDeclaration(ASTBaseBase):
elif self.objectType == 'enumerator':
mainDeclNode += addnodes.desc_annotation('enumerator ', 'enumerator ')
elif self.objectType == 'type':
prefix = self.declaration.get_type_declaration_prefix()
decl = cast(ASTType, self.declaration)
prefix = decl.get_type_declaration_prefix()
prefix += ' '
mainDeclNode += addnodes.desc_annotation(prefix, prefix)
else:
@ -1454,7 +1471,7 @@ class Symbol:
assert False # shouldn't happen
else:
# the domain base class makes a copy of the initial data, which is fine
return Symbol(None, None, None, None)
return Symbol(None, None, None, None, None)
@staticmethod
def debug_print(*args: Any) -> None:
@ -1477,7 +1494,7 @@ class Symbol:
return super().__setattr__(key, value)
def __init__(self, parent: "Symbol", ident: ASTIdentifier,
declaration: ASTDeclaration, docname: str) -> None:
declaration: ASTDeclaration, docname: str, line: int) -> None:
self.parent = parent
# declarations in a single directive are linked together
self.siblingAbove = None # type: Symbol
@ -1485,6 +1502,7 @@ class Symbol:
self.ident = ident
self.declaration = declaration
self.docname = docname
self.line = line
self.isRedeclaration = False
self._assert_invariants()
@ -1500,15 +1518,18 @@ class Symbol:
# Do symbol addition after self._children has been initialised.
self._add_function_params()
def _fill_empty(self, declaration: ASTDeclaration, docname: str) -> None:
def _fill_empty(self, declaration: ASTDeclaration, docname: str, line: int) -> None:
self._assert_invariants()
assert not self.declaration
assert not self.docname
assert declaration
assert docname
assert self.declaration is None
assert self.docname is None
assert self.line is None
assert declaration is not None
assert docname is not None
assert line is not None
self.declaration = declaration
self.declaration.symbol = self
self.docname = docname
self.line = line
self._assert_invariants()
# and symbol addition should be done as well
self._add_function_params()
@ -1532,7 +1553,7 @@ class Symbol:
decl = ASTDeclaration('functionParam', None, p)
assert not nn.rooted
assert len(nn.names) == 1
self._add_symbols(nn, decl, self.docname)
self._add_symbols(nn, decl, self.docname, self.line)
if Symbol.debug_lookup:
Symbol.debug_indent -= 1
@ -1549,6 +1570,7 @@ class Symbol:
if sChild.declaration and sChild.docname == docname:
sChild.declaration = None
sChild.docname = None
sChild.line = None
if sChild.siblingAbove is not None:
sChild.siblingAbove.siblingBelow = sChild.siblingBelow
if sChild.siblingBelow is not None:
@ -1559,13 +1581,11 @@ class Symbol:
def get_all_symbols(self) -> Iterator["Symbol"]:
yield self
for sChild in self._children:
for s in sChild.get_all_symbols():
yield s
yield from sChild.get_all_symbols()
@property
def children(self) -> Iterator["Symbol"]:
for c in self._children:
yield c
yield from self._children
@property
def children_recurse_anon(self) -> Iterator["Symbol"]:
@ -1742,7 +1762,7 @@ class Symbol:
return SymbolLookupResult(symbols, parentSymbol, ident)
def _add_symbols(self, nestedName: ASTNestedName,
declaration: ASTDeclaration, docname: str) -> "Symbol":
declaration: ASTDeclaration, docname: str, line: int) -> "Symbol":
# TODO: further simplification from C++ to C
# Used for adding a whole path of symbols, where the last may or may not
# be an actual declaration.
@ -1751,9 +1771,9 @@ class Symbol:
Symbol.debug_indent += 1
Symbol.debug_print("_add_symbols:")
Symbol.debug_indent += 1
Symbol.debug_print("nn: ", nestedName)
Symbol.debug_print("decl: ", declaration)
Symbol.debug_print("doc: ", docname)
Symbol.debug_print("nn: ", nestedName)
Symbol.debug_print("decl: ", declaration)
Symbol.debug_print("location: {}:{}".format(docname, line))
def onMissingQualifiedSymbol(parentSymbol: "Symbol", ident: ASTIdentifier) -> "Symbol":
if Symbol.debug_lookup:
@ -1763,7 +1783,7 @@ class Symbol:
Symbol.debug_print("ident: ", ident)
Symbol.debug_indent -= 2
return Symbol(parent=parentSymbol, ident=ident,
declaration=None, docname=None)
declaration=None, docname=None, line=None)
lookupResult = self._symbol_lookup(nestedName,
onMissingQualifiedSymbol,
@ -1779,12 +1799,12 @@ class Symbol:
Symbol.debug_indent += 1
Symbol.debug_print("ident: ", lookupResult.ident)
Symbol.debug_print("declaration: ", declaration)
Symbol.debug_print("docname: ", docname)
Symbol.debug_print("location: {}:{}".format(docname, line))
Symbol.debug_indent -= 1
symbol = Symbol(parent=lookupResult.parentSymbol,
ident=lookupResult.ident,
declaration=declaration,
docname=docname)
docname=docname, line=line)
if Symbol.debug_lookup:
Symbol.debug_indent -= 2
return symbol
@ -1832,7 +1852,7 @@ class Symbol:
symbol = Symbol(parent=lookupResult.parentSymbol,
ident=lookupResult.ident,
declaration=declaration,
docname=docname)
docname=docname, line=line)
if Symbol.debug_lookup:
Symbol.debug_print("end: creating candidate symbol")
return symbol
@ -1898,7 +1918,7 @@ class Symbol:
# .. namespace:: Test
# .. namespace:: nullptr
# .. class:: Test
symbol._fill_empty(declaration, docname)
symbol._fill_empty(declaration, docname, line)
return symbol
def merge_with(self, other: "Symbol", docnames: List[str],
@ -1919,13 +1939,15 @@ class Symbol:
continue
if otherChild.declaration and otherChild.docname in docnames:
if not ourChild.declaration:
ourChild._fill_empty(otherChild.declaration, otherChild.docname)
ourChild._fill_empty(otherChild.declaration,
otherChild.docname, otherChild.line)
elif ourChild.docname != otherChild.docname:
name = str(ourChild.declaration)
msg = __("Duplicate C declaration, also defined in '%s'.\n"
"Declaration is '%s'.")
msg = msg % (ourChild.docname, name)
logger.warning(msg, location=otherChild.docname)
msg = __("Duplicate C declaration, also defined at %s:%s.\n"
"Declaration is '.. c:%s:: %s'.")
msg = msg % (ourChild.docname, ourChild.line,
ourChild.declaration.directiveType, name)
logger.warning(msg, location=(otherChild.docname, otherChild.line))
else:
# Both have declarations, and in the same docname.
# This can apparently happen, it should be safe to
@ -1939,19 +1961,21 @@ class Symbol:
if Symbol.debug_lookup:
Symbol.debug_indent += 1
Symbol.debug_print("add_name:")
res = self._add_symbols(nestedName, declaration=None, docname=None)
res = self._add_symbols(nestedName, declaration=None, docname=None, line=None)
if Symbol.debug_lookup:
Symbol.debug_indent -= 1
return res
def add_declaration(self, declaration: ASTDeclaration, docname: str) -> "Symbol":
def add_declaration(self, declaration: ASTDeclaration,
docname: str, line: int) -> "Symbol":
if Symbol.debug_lookup:
Symbol.debug_indent += 1
Symbol.debug_print("add_declaration:")
assert declaration
assert docname
assert declaration is not None
assert docname is not None
assert line is not None
nestedName = declaration.name
res = self._add_symbols(nestedName, declaration, docname)
res = self._add_symbols(nestedName, declaration, docname, line)
if Symbol.debug_lookup:
Symbol.debug_indent -= 1
return res
@ -2988,7 +3012,7 @@ class DefinitionParser(BaseParser):
def parse_pre_v3_type_definition(self) -> ASTDeclaration:
self.skip_ws()
declaration = None # type: Any
declaration = None # type: DeclarationType
if self.skip_word('struct'):
typ = 'struct'
declaration = self._parse_struct()
@ -3011,7 +3035,7 @@ class DefinitionParser(BaseParser):
'macro', 'struct', 'union', 'enum', 'enumerator', 'type'):
raise Exception('Internal error, unknown directiveType "%s".' % directiveType)
declaration = None # type: Any
declaration = None # type: DeclarationType
if objectType == 'member':
declaration = self._parse_type_with_init(named=True, outer='member')
elif objectType == 'function':
@ -3074,7 +3098,7 @@ def _make_phony_error_name() -> ASTNestedName:
return ASTNestedName([ASTIdentifier("PhonyNameDueToError")], rooted=False)
class CObject(ObjectDescription):
class CObject(ObjectDescription[ASTDeclaration]):
"""
Description of a C language object.
"""
@ -3128,7 +3152,7 @@ class CObject(ObjectDescription):
declClone.enumeratorScopedSymbol = symbol
Symbol(parent=targetSymbol, ident=symbol.ident,
declaration=declClone,
docname=self.env.docname)
docname=self.env.docname, line=self.get_source_info()[1])
def add_target_and_index(self, ast: ASTDeclaration, sig: str,
signode: TextElement) -> None:
@ -3158,10 +3182,6 @@ class CObject(ObjectDescription):
self.state.document.note_explicit_target(signode)
domain = cast(CDomain, self.env.get_domain('c'))
if name not in domain.objects:
domain.objects[name] = (domain.env.docname, newestId, self.objtype)
if 'noindexentry' not in self.options:
indexText = self.get_index_text(name)
self.indexnode['entries'].append(('single', indexText, newestId, '', None))
@ -3183,7 +3203,8 @@ class CObject(ObjectDescription):
def parse_pre_v3_type_definition(self, parser: DefinitionParser) -> ASTDeclaration:
return parser.parse_pre_v3_type_definition()
def describe_signature(self, signode: TextElement, ast: Any, options: Dict) -> None:
def describe_signature(self, signode: TextElement, ast: ASTDeclaration,
options: Dict) -> None:
ast.describe_signature(signode, 'lastIsName', self.env, options)
def run(self) -> List[Node]:
@ -3235,7 +3256,8 @@ class CObject(ObjectDescription):
raise ValueError from e
try:
symbol = parentSymbol.add_declaration(ast, docname=self.env.docname)
symbol = parentSymbol.add_declaration(
ast, docname=self.env.docname, line=self.get_source_info()[1])
# append the new declaration to the sibling list
assert symbol.siblingAbove is None
assert symbol.siblingBelow is None
@ -3248,9 +3270,9 @@ class CObject(ObjectDescription):
# Assume we are actually in the old symbol,
# instead of the newly created duplicate.
self.env.temp_data['c:last_symbol'] = e.symbol
msg = __("Duplicate C declaration, also defined in '%s'.\n"
"Declaration is '%s'.")
msg = msg % (e.symbol.docname, sig)
msg = __("Duplicate C declaration, also defined at %s:%s.\n"
"Declaration is '.. c:%s:: %s'.")
msg = msg % (e.symbol.docname, e.symbol.line, self.display_object_type, sig)
logger.warning(msg, location=signode)
if ast.objectType == 'enumerator':
@ -3429,8 +3451,9 @@ class AliasNode(nodes.Element):
assert parentKey is not None
self.parentKey = parentKey
def copy(self: T) -> T:
return self.__class__(self.sig, env=None, parentKey=self.parentKey) # type: ignore
def copy(self) -> 'AliasNode':
return self.__class__(self.sig, self.maxdepth, self.document,
env=None, parentKey=self.parentKey)
class AliasTransform(SphinxTransform):
@ -3619,7 +3642,7 @@ class CExprRole(SphinxRole):
location=self.get_source_info())
# see below
return [self.node_type(text, text, classes=classes)], []
parentSymbol = self.env.temp_data.get('cpp:parent_symbol', None)
parentSymbol = self.env.temp_data.get('c:parent_symbol', None)
if parentSymbol is None:
parentSymbol = self.env.domaindata['c']['root_symbol']
# ...most if not all of these classes should really apply to the individual references,
@ -3634,15 +3657,18 @@ class CDomain(Domain):
name = 'c'
label = 'C'
object_types = {
'function': ObjType(_('function'), 'func'),
'member': ObjType(_('member'), 'member'),
'macro': ObjType(_('macro'), 'macro'),
'type': ObjType(_('type'), 'type'),
'var': ObjType(_('variable'), 'data'),
'enum': ObjType(_('enum'), 'enum'),
'enumerator': ObjType(_('enumerator'), 'enumerator'),
'struct': ObjType(_('struct'), 'struct'),
'union': ObjType(_('union'), 'union'),
# 'identifier' is the one used for xrefs generated in signatures, not in roles
'member': ObjType(_('member'), 'var', 'member', 'data', 'identifier'),
'var': ObjType(_('variable'), 'var', 'member', 'data', 'identifier'),
'function': ObjType(_('function'), 'func', 'identifier', 'type'),
'macro': ObjType(_('macro'), 'macro', 'identifier'),
'struct': ObjType(_('struct'), 'struct', 'identifier', 'type'),
'union': ObjType(_('union'), 'union', 'identifier', 'type'),
'enum': ObjType(_('enum'), 'enum', 'identifier', 'type'),
'enumerator': ObjType(_('enumerator'), 'enumerator', 'identifier'),
'type': ObjType(_('type'), 'identifier', 'type'),
# generated object types
'functionParam': ObjType(_('function parameter'), 'identifier', 'var', 'member', 'data'), # noqa
}
directives = {
@ -3677,14 +3703,10 @@ class CDomain(Domain):
'texpr': CExprRole(asCode=False)
}
initial_data = {
'root_symbol': Symbol(None, None, None, None),
'root_symbol': Symbol(None, None, None, None, None),
'objects': {}, # fullname -> docname, node_id, objtype
} # type: Dict[str, Union[Symbol, Dict[str, Tuple[str, str, str]]]]
@property
def objects(self) -> Dict[str, Tuple[str, str, str]]:
return self.data.setdefault('objects', {}) # fullname -> docname, node_id, objtype
def clear_doc(self, docname: str) -> None:
if Symbol.debug_show_tree:
print("clear_doc:", docname)
@ -3700,9 +3722,6 @@ class CDomain(Domain):
print(self.data['root_symbol'].dump(1))
print("\tafter end")
print("clear_doc end:", docname)
for fullname, (fn, _id, _l) in list(self.objects.items()):
if fn == docname:
del self.objects[fullname]
def process_doc(self, env: BuildEnvironment, docname: str,
document: nodes.document) -> None:
@ -3788,8 +3807,18 @@ class CDomain(Domain):
return []
def get_objects(self) -> Iterator[Tuple[str, str, str, str, str, int]]:
for refname, (docname, node_id, objtype) in list(self.objects.items()):
yield (refname, refname, objtype, docname, node_id, 1)
rootSymbol = self.data['root_symbol']
for symbol in rootSymbol.get_all_symbols():
if symbol.declaration is None:
continue
assert symbol.docname
fullNestedName = symbol.get_full_nested_name()
name = str(fullNestedName).lstrip('.')
dispname = fullNestedName.get_display_string().lstrip('.')
objectType = symbol.declaration.objectType
docname = symbol.docname
newestId = symbol.declaration.get_newest_id()
yield (name, dispname, objectType, docname, newestId, 1)
def setup(app: Sphinx) -> Dict[str, Any]:

View File

@ -4,13 +4,12 @@
The changeset domain.
: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 collections import namedtuple
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 Node
@ -20,7 +19,6 @@ from sphinx.domains import Domain
from sphinx.locale import _
from sphinx.util.docutils import SphinxDirective
if False:
# For type annotation
from sphinx.application import Sphinx

View File

@ -4,12 +4,11 @@
The citation domain.
: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

View File

@ -4,14 +4,13 @@
The C++ language domain.
: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, Callable, Dict, Generator, Iterator, List, Tuple, Type, TypeVar, Union, Optional
)
from typing import (Any, Callable, Dict, Generator, Iterator, List, Optional, Tuple, Type,
TypeVar, Union)
from docutils import nodes
from docutils.nodes import Element, Node, TextElement, system_message
@ -30,20 +29,17 @@ from sphinx.roles import SphinxRole, XRefRole
from sphinx.transforms import SphinxTransform
from sphinx.transforms.post_transforms import ReferencesResolver
from sphinx.util import logging
from sphinx.util.cfamily import (
NoOldIdError, ASTBaseBase, ASTAttribute, ASTBaseParenExprList,
verify_description_mode, StringifyTransform,
BaseParser, DefinitionError, UnsupportedMultiCharacterCharLiteral,
identifier_re, anon_identifier_re, integer_literal_re, octal_literal_re,
hex_literal_re, binary_literal_re, integers_literal_suffix_re,
float_literal_re, float_literal_suffix_re,
char_literal_re
)
from sphinx.util.cfamily import (ASTAttribute, ASTBaseBase, ASTBaseParenExprList, BaseParser,
DefinitionError, NoOldIdError, StringifyTransform,
UnsupportedMultiCharacterCharLiteral, anon_identifier_re,
binary_literal_re, char_literal_re, float_literal_re,
float_literal_suffix_re, hex_literal_re, identifier_re,
integer_literal_re, integers_literal_suffix_re,
octal_literal_re, verify_description_mode)
from sphinx.util.docfields import Field, GroupedField
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import make_refnode
logger = logging.getLogger(__name__)
T = TypeVar('T')
@ -1596,6 +1592,15 @@ class ASTOperator(ASTBase):
identifier = str(self)
if mode == 'lastIsName':
signode += addnodes.desc_name(identifier, identifier)
elif mode == 'markType':
targetText = prefix + identifier + templateArgs
pnode = addnodes.pending_xref('', refdomain='cpp',
reftype='identifier',
reftarget=targetText, modname=None,
classname=None)
pnode['cpp:parent_key'] = symbol.get_lookup_key()
pnode += nodes.Text(identifier)
signode += pnode
else:
signode += addnodes.desc_addname(identifier, identifier)
@ -1836,7 +1841,7 @@ class ASTFunctionParameter(ASTBase):
# this is not part of the normal name mangling in C++
if symbol:
# the anchor will be our parent
return symbol.parent.declaration.get_id(version, prefixed=None)
return symbol.parent.declaration.get_id(version, prefixed=False)
# else, do the usual
if self.ellipsis:
return 'z'
@ -3798,7 +3803,7 @@ class Symbol:
assert False # shouldn't happen
else:
# the domain base class makes a copy of the initial data, which is fine
return Symbol(None, None, None, None, None, None)
return Symbol(None, None, None, None, None, None, None)
@staticmethod
def debug_print(*args: Any) -> None:
@ -3825,7 +3830,8 @@ class Symbol:
def __init__(self, parent: "Symbol", identOrOp: Union[ASTIdentifier, ASTOperator],
templateParams: Union[ASTTemplateParams, ASTTemplateIntroduction],
templateArgs: Any, declaration: ASTDeclaration, docname: str) -> None:
templateArgs: Any, declaration: ASTDeclaration,
docname: str, line: int) -> None:
self.parent = parent
# declarations in a single directive are linked together
self.siblingAbove = None # type: Symbol
@ -3835,6 +3841,7 @@ class Symbol:
self.templateArgs = templateArgs # identifier<templateArgs>
self.declaration = declaration
self.docname = docname
self.line = line
self.isRedeclaration = False
self._assert_invariants()
@ -3850,15 +3857,18 @@ class Symbol:
# Do symbol addition after self._children has been initialised.
self._add_template_and_function_params()
def _fill_empty(self, declaration: ASTDeclaration, docname: str) -> None:
def _fill_empty(self, declaration: ASTDeclaration, docname: str, line: int) -> None:
self._assert_invariants()
assert not self.declaration
assert not self.docname
assert declaration
assert docname
assert self.declaration is None
assert self.docname is None
assert self.line is None
assert declaration is not None
assert docname is not None
assert line is not None
self.declaration = declaration
self.declaration.symbol = self
self.docname = docname
self.line = line
self._assert_invariants()
# and symbol addition should be done as well
self._add_template_and_function_params()
@ -3882,7 +3892,7 @@ class Symbol:
decl = None
nne = ASTNestedNameElement(tp.get_identifier(), None)
nn = ASTNestedName([nne], [False], rooted=False)
self._add_symbols(nn, [], decl, self.docname)
self._add_symbols(nn, [], decl, self.docname, self.line)
# add symbols for function parameters, if any
if self.declaration is not None and self.declaration.function_params is not None:
for fp in self.declaration.function_params:
@ -3895,7 +3905,7 @@ class Symbol:
decl = ASTDeclaration('functionParam', None, None, None, None, fp, None)
assert not nn.rooted
assert len(nn.names) == 1
self._add_symbols(nn, [], decl, self.docname)
self._add_symbols(nn, [], decl, self.docname, self.line)
if Symbol.debug_lookup:
Symbol.debug_indent -= 1
@ -3913,6 +3923,7 @@ class Symbol:
if sChild.declaration and sChild.docname == docname:
sChild.declaration = None
sChild.docname = None
sChild.line = None
if sChild.siblingAbove is not None:
sChild.siblingAbove.siblingBelow = sChild.siblingBelow
if sChild.siblingBelow is not None:
@ -3925,8 +3936,7 @@ class Symbol:
def get_all_symbols(self) -> Iterator[Any]:
yield self
for sChild in self._children:
for s in sChild.get_all_symbols():
yield s
yield from sChild.get_all_symbols()
@property
def children_recurse_anon(self) -> Generator["Symbol", None, None]:
@ -4107,7 +4117,7 @@ class Symbol:
Symbol.debug_print("self:")
print(self.to_string(Symbol.debug_indent + 1), end="")
Symbol.debug_print("nestedName: ", nestedName)
Symbol.debug_print("templateDecls: ", templateDecls)
Symbol.debug_print("templateDecls: ", ",".join(str(t) for t in templateDecls))
Symbol.debug_print("strictTemplateParamArgLists:", strictTemplateParamArgLists)
Symbol.debug_print("ancestorLookupType:", ancestorLookupType)
Symbol.debug_print("templateShorthand: ", templateShorthand)
@ -4223,7 +4233,7 @@ class Symbol:
identOrOp, templateParams, templateArgs)
def _add_symbols(self, nestedName: ASTNestedName, templateDecls: List[Any],
declaration: ASTDeclaration, docname: str) -> "Symbol":
declaration: ASTDeclaration, docname: str, line: int) -> "Symbol":
# Used for adding a whole path of symbols, where the last may or may not
# be an actual declaration.
@ -4231,10 +4241,10 @@ class Symbol:
Symbol.debug_indent += 1
Symbol.debug_print("_add_symbols:")
Symbol.debug_indent += 1
Symbol.debug_print("tdecls:", templateDecls)
Symbol.debug_print("nn: ", nestedName)
Symbol.debug_print("decl: ", declaration)
Symbol.debug_print("doc: ", docname)
Symbol.debug_print("tdecls:", ",".join(str(t) for t in templateDecls))
Symbol.debug_print("nn: ", nestedName)
Symbol.debug_print("decl: ", declaration)
Symbol.debug_print("location: {}:{}".format(docname, line))
def onMissingQualifiedSymbol(parentSymbol: "Symbol",
identOrOp: Union[ASTIdentifier, ASTOperator],
@ -4251,7 +4261,7 @@ class Symbol:
return Symbol(parent=parentSymbol, identOrOp=identOrOp,
templateParams=templateParams,
templateArgs=templateArgs, declaration=None,
docname=None)
docname=None, line=None)
lookupResult = self._symbol_lookup(nestedName, templateDecls,
onMissingQualifiedSymbol,
@ -4272,14 +4282,14 @@ class Symbol:
Symbol.debug_print("identOrOp: ", lookupResult.identOrOp)
Symbol.debug_print("templateArgs: ", lookupResult.templateArgs)
Symbol.debug_print("declaration: ", declaration)
Symbol.debug_print("docname: ", docname)
Symbol.debug_print("location: {}:{}".format(docname, line))
Symbol.debug_indent -= 1
symbol = Symbol(parent=lookupResult.parentSymbol,
identOrOp=lookupResult.identOrOp,
templateParams=lookupResult.templateParams,
templateArgs=lookupResult.templateArgs,
declaration=declaration,
docname=docname)
docname=docname, line=line)
if Symbol.debug_lookup:
Symbol.debug_indent -= 2
return symbol
@ -4328,7 +4338,7 @@ class Symbol:
templateParams=lookupResult.templateParams,
templateArgs=lookupResult.templateArgs,
declaration=declaration,
docname=docname)
docname=docname, line=line)
if Symbol.debug_lookup:
Symbol.debug_print("end: creating candidate symbol")
return symbol
@ -4360,6 +4370,11 @@ class Symbol:
if Symbol.debug_lookup:
Symbol.debug_print("candId:", candId)
for symbol in withDecl:
# but all existing must be functions as well,
# otherwise we declare it to be a duplicate
if symbol.declaration.objectType != 'function':
handleDuplicateDeclaration(symbol, candSymbol)
# (not reachable)
oldId = symbol.declaration.get_newest_id()
if Symbol.debug_lookup:
Symbol.debug_print("oldId: ", oldId)
@ -4370,7 +4385,11 @@ class Symbol:
# if there is an empty symbol, fill that one
if len(noDecl) == 0:
if Symbol.debug_lookup:
Symbol.debug_print("no match, no empty, candSybmol is not None?:", candSymbol is not None) # NOQA
Symbol.debug_print("no match, no empty")
if candSymbol is not None:
Symbol.debug_print("result is already created candSymbol")
else:
Symbol.debug_print("result is makeCandSymbol()")
Symbol.debug_indent -= 2
if candSymbol is not None:
return candSymbol
@ -4391,7 +4410,7 @@ class Symbol:
# .. namespace:: Test
# .. namespace:: nullptr
# .. class:: Test
symbol._fill_empty(declaration, docname)
symbol._fill_empty(declaration, docname, line)
return symbol
def merge_with(self, other: "Symbol", docnames: List[str],
@ -4470,13 +4489,15 @@ class Symbol:
continue
if otherChild.declaration and otherChild.docname in docnames:
if not ourChild.declaration:
ourChild._fill_empty(otherChild.declaration, otherChild.docname)
ourChild._fill_empty(otherChild.declaration,
otherChild.docname, otherChild.line)
elif ourChild.docname != otherChild.docname:
name = str(ourChild.declaration)
msg = __("Duplicate C++ declaration, also defined in '%s'.\n"
"Declaration is '%s'.")
msg = msg % (ourChild.docname, name)
logger.warning(msg, location=otherChild.docname)
msg = __("Duplicate C++ declaration, also defined at %s:%s.\n"
"Declaration is '.. cpp:%s:: %s'.")
msg = msg % (ourChild.docname, ourChild.line,
ourChild.declaration.directiveType, name)
logger.warning(msg, location=(otherChild.docname, otherChild.line))
else:
# Both have declarations, and in the same docname.
# This can apparently happen, it should be safe to
@ -4500,23 +4521,25 @@ class Symbol:
else:
templateDecls = []
res = self._add_symbols(nestedName, templateDecls,
declaration=None, docname=None)
declaration=None, docname=None, line=None)
if Symbol.debug_lookup:
Symbol.debug_indent -= 1
return res
def add_declaration(self, declaration: ASTDeclaration, docname: str) -> "Symbol":
def add_declaration(self, declaration: ASTDeclaration,
docname: str, line: int) -> "Symbol":
if Symbol.debug_lookup:
Symbol.debug_indent += 1
Symbol.debug_print("add_declaration:")
assert declaration
assert docname
assert declaration is not None
assert docname is not None
assert line is not None
nestedName = declaration.name
if declaration.templatePrefix:
templateDecls = declaration.templatePrefix.templates
else:
templateDecls = []
res = self._add_symbols(nestedName, templateDecls, declaration, docname)
res = self._add_symbols(nestedName, templateDecls, declaration, docname, line)
if Symbol.debug_lookup:
Symbol.debug_indent -= 1
return res
@ -4711,7 +4734,8 @@ class Symbol:
templateParams=lookupResult.templateParams,
templateArgs=lookupResult.templateArgs,
declaration=declaration,
docname='fakeDocnameForQuery')
docname='fakeDocnameForQuery',
line=42)
queryId = declaration.get_newest_id()
for symbol in symbols:
if symbol.declaration is None:
@ -6655,7 +6679,7 @@ def _make_phony_error_name() -> ASTNestedName:
return ASTNestedName([nne], [False], rooted=False)
class CPPObject(ObjectDescription):
class CPPObject(ObjectDescription[ASTDeclaration]):
"""Description of a C++ language object."""
doc_field_types = [
@ -6717,7 +6741,7 @@ class CPPObject(ObjectDescription):
Symbol(parent=targetSymbol, identOrOp=symbol.identOrOp,
templateParams=None, templateArgs=None,
declaration=declClone,
docname=self.env.docname)
docname=self.env.docname, line=self.get_source_info()[1])
def add_target_and_index(self, ast: ASTDeclaration, sig: str,
signode: TextElement) -> None:
@ -6814,10 +6838,12 @@ class CPPObject(ObjectDescription):
parentSymbol = env.temp_data['cpp:parent_symbol']
parentDecl = parentSymbol.declaration
if parentDecl is not None and parentDecl.objectType == 'function':
logger.warning("C++ declarations inside functions are not supported." +
" Parent function is " +
str(parentSymbol.get_full_nested_name()),
location=self.get_source_info())
msg = "C++ declarations inside functions are not supported." \
" Parent function: {}\nDirective name: {}\nDirective arg: {}"
logger.warning(msg.format(
str(parentSymbol.get_full_nested_name()),
self.name, self.arguments[0]
), location=self.get_source_info())
name = _make_phony_error_name()
symbol = parentSymbol.add_name(name)
env.temp_data['cpp:last_symbol'] = symbol
@ -6829,7 +6855,7 @@ class CPPObject(ObjectDescription):
return super().run()
def handle_signature(self, sig: str, signode: desc_signature) -> ASTDeclaration:
parentSymbol = self.env.temp_data['cpp:parent_symbol']
parentSymbol = self.env.temp_data['cpp:parent_symbol'] # type: Symbol
parser = DefinitionParser(sig, location=signode, config=self.env.config)
try:
@ -6845,7 +6871,8 @@ class CPPObject(ObjectDescription):
raise ValueError from e
try:
symbol = parentSymbol.add_declaration(ast, docname=self.env.docname)
symbol = parentSymbol.add_declaration(
ast, docname=self.env.docname, line=self.get_source_info()[1])
# append the new declaration to the sibling list
assert symbol.siblingAbove is None
assert symbol.siblingBelow is None
@ -6858,9 +6885,10 @@ class CPPObject(ObjectDescription):
# Assume we are actually in the old symbol,
# instead of the newly created duplicate.
self.env.temp_data['cpp:last_symbol'] = e.symbol
msg = __("Duplicate C++ declaration, also defined in '%s'.\n"
"Declaration is '%s'.")
msg = msg % (e.symbol.docname, sig)
msg = __("Duplicate C++ declaration, also defined at %s:%s.\n"
"Declaration is '.. cpp:%s:: %s'.")
msg = msg % (e.symbol.docname, e.symbol.line,
self.display_object_type, sig)
logger.warning(msg, location=signode)
if ast.objectType == 'enumerator':
@ -7031,8 +7059,8 @@ class AliasNode(nodes.Element):
assert parentKey is not None
self.parentKey = parentKey
def copy(self: T) -> T:
return self.__class__(self.sig, env=None, parentKey=self.parentKey) # type: ignore
def copy(self) -> 'AliasNode':
return self.__class__(self.sig, env=None, parentKey=self.parentKey)
class AliasTransform(SphinxTransform):
@ -7232,14 +7260,18 @@ class CPPDomain(Domain):
name = 'cpp'
label = 'C++'
object_types = {
'class': ObjType(_('class'), 'class', 'type', 'identifier'),
'union': ObjType(_('union'), 'union', 'type', 'identifier'),
'function': ObjType(_('function'), 'function', 'func', 'type', 'identifier'),
'member': ObjType(_('member'), 'member', 'var'),
'type': ObjType(_('type'), 'type', 'identifier'),
'concept': ObjType(_('concept'), 'concept', 'identifier'),
'enum': ObjType(_('enum'), 'enum', 'type', 'identifier'),
'enumerator': ObjType(_('enumerator'), 'enumerator')
'class': ObjType(_('class'), 'class', 'struct', 'identifier', 'type'),
'union': ObjType(_('union'), 'union', 'identifier', 'type'),
'function': ObjType(_('function'), 'func', 'identifier', 'type'),
'member': ObjType(_('member'), 'member', 'var', 'identifier'),
'type': ObjType(_('type'), 'identifier', 'type'),
'concept': ObjType(_('concept'), 'concept', 'identifier'),
'enum': ObjType(_('enum'), 'enum', 'identifier', 'type'),
'enumerator': ObjType(_('enumerator'), 'enumerator', 'identifier'),
# generated object types
'functionParam': ObjType(_('function parameter'), 'identifier', 'member', 'var'), # noqa
'templateParam': ObjType(_('template parameter'),
'identifier', 'class', 'struct', 'union', 'member', 'var', 'type'), # noqa
}
directives = {
@ -7279,7 +7311,7 @@ class CPPDomain(Domain):
'texpr': CPPExprRole(asCode=False)
}
initial_data = {
'root_symbol': Symbol(None, None, None, None, None, None),
'root_symbol': Symbol(None, None, None, None, None, None, None),
'names': {} # full name for indexing -> docname
}
@ -7416,30 +7448,19 @@ class CPPDomain(Domain):
if typ.startswith('cpp:'):
typ = typ[4:]
origTyp = typ
if typ == 'func':
typ = 'function'
if typ == 'struct':
typ = 'class'
declTyp = s.declaration.objectType
def checkType() -> bool:
if typ == 'any' or typ == 'identifier':
if typ == 'any':
return True
if declTyp == 'templateParam':
# TODO: perhaps this should be strengthened one day
return True
if declTyp == 'functionParam':
if typ == 'var' or typ == 'member':
return True
objtypes = self.objtypes_for_role(typ)
if objtypes:
return declTyp in objtypes
print("Type is %s (originally: %s), declType is %s" % (typ, origTyp, declTyp))
print("Type is %s, declaration type is %s" % (typ, declTyp))
assert False
if not checkType():
logger.warning("cpp:%s targets a %s (%s).",
origTyp, s.declaration.objectType,
typ, s.declaration.objectType,
s.get_full_nested_name(),
location=node)
@ -7469,10 +7490,10 @@ class CPPDomain(Domain):
if env.config.add_function_parentheses and typ == 'any':
addParen += 1
# and now this stuff for operator()
if (env.config.add_function_parentheses and typ == 'function' and
if (env.config.add_function_parentheses and typ == 'func' and
title.endswith('operator()')):
addParen += 1
if ((typ == 'any' or typ == 'function') and
if ((typ == 'any' or typ == 'func') and
title.endswith('operator') and
displayName.endswith('operator()')):
addParen += 1
@ -7481,7 +7502,7 @@ class CPPDomain(Domain):
if env.config.add_function_parentheses:
if typ == 'any' and displayName.endswith('()'):
addParen += 1
elif typ == 'function':
elif typ == 'func':
if title.endswith('()') and not displayName.endswith('()'):
title = title[:-2]
else:

View File

@ -4,7 +4,7 @@
The index domain.
: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,8 +17,7 @@ from docutils.parsers.rst import directives
from sphinx import addnodes
from sphinx.domains import Domain
from sphinx.environment import BuildEnvironment
from sphinx.util import logging
from sphinx.util import split_index_msg
from sphinx.util import logging, split_index_msg
from sphinx.util.docutils import ReferenceRole, SphinxDirective
from sphinx.util.nodes import process_index_entry

View File

@ -4,12 +4,11 @@
The JavaScript domain.
: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, Iterator, List, Tuple
from typing import cast
from typing import Any, Dict, Iterator, List, Tuple, cast
from docutils import nodes
from docutils.nodes import Element, Node
@ -30,11 +29,10 @@ from sphinx.util.docfields import Field, GroupedField, TypedField
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import make_id, make_refnode
logger = logging.getLogger(__name__)
class JSObject(ObjectDescription):
class JSObject(ObjectDescription[Tuple[str, str]]):
"""
Description of a JavaScript object.
"""

View File

@ -4,7 +4,7 @@
The math domain.
: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.
"""
@ -12,8 +12,7 @@ import warnings
from typing import Any, Dict, Iterable, List, Tuple
from docutils import nodes
from docutils.nodes import Element, Node, system_message
from docutils.nodes import make_id
from docutils.nodes import Element, Node, make_id, system_message
from sphinx.addnodes import pending_xref
from sphinx.deprecation import RemovedInSphinx40Warning
@ -158,8 +157,11 @@ class MathDomain(Domain):
targets = [eq for eq in self.equations.values() if eq[0] == docname]
return len(targets) + 1
def has_equations(self) -> bool:
return any(self.data['has_equations'].values())
def has_equations(self, docname: str = None) -> bool:
if docname:
return self.data['has_equations'].get(docname, False)
else:
return any(self.data['has_equations'].values())
def setup(app: "Sphinx") -> Dict[str, Any]:

View File

@ -4,7 +4,7 @@
The Python domain.
: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.
"""
@ -15,23 +15,23 @@ import sys
import typing
import warnings
from inspect import Parameter
from typing import Any, Dict, Iterable, Iterator, List, NamedTuple, Tuple
from typing import cast
from typing import Any, Dict, Iterable, Iterator, List, NamedTuple, Tuple, cast
from docutils import nodes
from docutils.nodes import Element, Node
from docutils.parsers.rst import directives
from sphinx import addnodes
from sphinx.addnodes import pending_xref, desc_signature
from sphinx.addnodes import desc_signature, pending_xref
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.deprecation import RemovedInSphinx40Warning, RemovedInSphinx50Warning
from sphinx.directives import ObjectDescription
from sphinx.domains import Domain, ObjType, Index, IndexEntry
from sphinx.domains import Domain, Index, IndexEntry, ObjType
from sphinx.environment import BuildEnvironment
from sphinx.locale import _, __
from sphinx.pycode.ast import ast, parse as ast_parse
from sphinx.pycode.ast import ast
from sphinx.pycode.ast import parse as ast_parse
from sphinx.roles import XRefRole
from sphinx.util import logging
from sphinx.util.docfields import Field, GroupedField, TypedField
@ -272,6 +272,8 @@ class PyXrefMixin:
result = super().make_xref(rolename, domain, target, # type: ignore
innernode, contnode, env)
result['refspecific'] = True
result['py:module'] = env.ref_context.get('py:module')
result['py:class'] = env.ref_context.get('py:class')
if target.startswith(('.', '~')):
prefix, result['reftarget'] = target[0], target[1:]
if prefix == '.':
@ -332,7 +334,7 @@ class PyTypedField(PyXrefMixin, TypedField):
return super().make_xref(rolename, domain, target, innernode, contnode, env)
class PyObject(ObjectDescription):
class PyObject(ObjectDescription[Tuple[str, str]]):
"""
Description of a general Python object.

View File

@ -4,13 +4,12 @@
The reStructuredText domain.
: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, Iterator, List, Tuple
from typing import cast
from typing import Any, Dict, Iterator, List, Tuple, cast
from docutils.nodes import Element
from docutils.parsers.rst import directives
@ -27,13 +26,12 @@ from sphinx.roles import XRefRole
from sphinx.util import logging
from sphinx.util.nodes import make_id, make_refnode
logger = logging.getLogger(__name__)
dir_sig_re = re.compile(r'\.\. (.+?)::(.*)$')
class ReSTMarkup(ObjectDescription):
class ReSTMarkup(ObjectDescription[str]):
"""
Description of generic reST markup.
"""

View File

@ -4,7 +4,7 @@
The standard domain.
: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.
"""
@ -12,8 +12,7 @@ import re
import unicodedata
import warnings
from copy import copy
from typing import Any, Callable, Dict, Iterable, Iterator, List, Optional, Tuple, Union
from typing import cast
from typing import Any, Callable, Dict, Iterable, Iterator, List, Optional, Tuple, Union, cast
from docutils import nodes
from docutils.nodes import Element, Node, system_message
@ -27,7 +26,7 @@ from sphinx.directives import ObjectDescription
from sphinx.domains import Domain, ObjType
from sphinx.locale import _, __
from sphinx.roles import XRefRole
from sphinx.util import ws_re, logging, docname_join
from sphinx.util import docname_join, logging, ws_re
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import clean_astext, make_id, make_refnode
from sphinx.util.typing import RoleFunction
@ -35,6 +34,7 @@ from sphinx.util.typing import RoleFunction
if False:
# For type annotation
from typing import Type # for python3.5.1
from sphinx.application import Sphinx
from sphinx.builders import Builder
from sphinx.environment import BuildEnvironment
@ -43,12 +43,12 @@ logger = logging.getLogger(__name__)
# RE for option descriptions
option_desc_re = re.compile(r'((?:/|--|-|\+)?[^\s=[]+)(=?\s*.*)')
option_desc_re = re.compile(r'((?:/|--|-|\+)?[^\s=]+)(=?\s*.*)')
# RE for grammar tokens
token_re = re.compile(r'`(\w+)`', re.U)
token_re = re.compile(r'`((~?\w*:)?\w+)`', re.U)
class GenericObject(ObjectDescription):
class GenericObject(ObjectDescription[str]):
"""
A generic x-ref directive registered with Sphinx.add_object_type().
"""
@ -178,7 +178,7 @@ class Target(SphinxDirective):
return self.name + '-' + name
class Cmdoption(ObjectDescription):
class Cmdoption(ObjectDescription[str]):
"""
Description of a command-line option (.. option).
"""
@ -197,6 +197,11 @@ class Cmdoption(ObjectDescription):
location=signode)
continue
optname, args = m.groups()
if optname.endswith('[') and args.endswith(']'):
# optional value surrounded by brackets (ex. foo[=bar])
optname = optname[:-1]
args = '[' + args
if count:
signode += addnodes.desc_addname(', ', ', ')
signode += addnodes.desc_name(optname, optname)
@ -318,7 +323,7 @@ def make_glossary_term(env: "BuildEnvironment", textnodes: Iterable[Node], index
term['ids'].append(node_id)
std = cast(StandardDomain, env.get_domain('std'))
std.note_object('term', termtext, node_id, location=term)
std._note_term(termtext, node_id, location=term)
# add an index entry too
indexnode = addnodes.index()
@ -459,9 +464,23 @@ def token_xrefs(text: str, productionGroup: str = '') -> List[Node]:
if m.start() > pos:
txt = text[pos:m.start()]
retnodes.append(nodes.Text(txt, txt))
refnode = pending_xref(m.group(1), reftype='token', refdomain='std',
reftarget=productionGroup + m.group(1))
refnode += nodes.literal(m.group(1), m.group(1), classes=['xref'])
token = m.group(1)
if ':' in token:
if token[0] == '~':
_, title = token.split(':')
target = token[1:]
elif token[0] == ':':
title = token[1:]
target = title
else:
title = token
target = token
else:
title = token
target = productionGroup + token
refnode = pending_xref(title, reftype='token', refdomain='std',
reftarget=target)
refnode += nodes.literal(token, title, classes=['xref'])
retnodes.append(refnode)
pos = m.end()
if pos < len(text):
@ -610,8 +629,6 @@ class StandardDomain(Domain):
dangling_warnings = {
'term': 'term not in glossary: %(target)s',
'ref': 'undefined label: %(target)s (if the link has no caption '
'the label must precede a section header)',
'numref': 'undefined label: %(target)s',
'keyword': 'unknown keyword: %(target)s',
'doc': 'unknown document: %(target)s',
@ -677,6 +694,20 @@ class StandardDomain(Domain):
RemovedInSphinx50Warning, stacklevel=2)
self.objects[objtype, name] = (docname, labelid)
@property
def _terms(self) -> Dict[str, Tuple[str, str]]:
""".. note:: Will be removed soon. internal use only."""
return self.data.setdefault('terms', {}) # (name) -> docname, labelid
def _note_term(self, term: str, labelid: str, location: Any = None) -> None:
"""Note a term for cross reference.
.. note:: Will be removed soon. internal use only.
"""
self.note_object('term', term, labelid, location)
self._terms[term.lower()] = (self.env.docname, labelid)
@property
def progoptions(self) -> Dict[Tuple[str, str], Tuple[str, str]]:
return self.data.setdefault('progoptions', {}) # (program, name) -> docname, labelid
@ -697,6 +728,9 @@ class StandardDomain(Domain):
for key, (fn, _l) in list(self.objects.items()):
if fn == docname:
del self.objects[key]
for key, (fn, _l) in list(self._terms.items()):
if fn == docname:
del self._terms[key]
for key, (fn, _l, _l) in list(self.labels.items()):
if fn == docname:
del self.labels[key]
@ -712,6 +746,9 @@ class StandardDomain(Domain):
for key, data in otherdata['objects'].items():
if data[0] in docnames:
self.objects[key] = data
for key, data in otherdata['terms'].items():
if data[0] in docnames:
self._terms[key] = data
for key, data in otherdata['labels'].items():
if data[0] in docnames:
self.labels[key] = data
@ -742,9 +779,11 @@ class StandardDomain(Domain):
name, env.doc2path(self.labels[name][0]),
location=node)
self.anonlabels[name] = docname, labelid
if node.tagname in ('section', 'rubric'):
if node.tagname == 'section':
title = cast(nodes.title, node[0])
sectname = clean_astext(title)
elif node.tagname == 'rubric':
sectname = clean_astext(node)
elif self.is_enumerable_node(node):
sectname = self.get_numfig_title(node)
if not sectname:
@ -854,8 +893,9 @@ class StandardDomain(Domain):
if fignumber is None:
return contnode
except ValueError:
logger.warning(__("no number is assigned for %s: %s"), figtype, labelid,
location=node)
logger.warning(__("Failed to create a cross reference. Any number is not "
"assigned: %s"),
labelid, location=node)
return contnode
try:
@ -947,19 +987,12 @@ class StandardDomain(Domain):
if result:
return result
else:
for objtype, term in self.objects:
if objtype == 'term' and term.lower() == target.lower():
docname, labelid = self.objects[objtype, term]
logger.warning(__('term %s not found in case sensitive match.'
'made a reference to %s instead.'),
target, term, location=node, type='ref', subtype='term')
break
# fallback to case insentive match
if target.lower() in self._terms:
docname, labelid = self._terms[target.lower()]
return make_refnode(builder, fromdocname, docname, labelid, contnode)
else:
docname, labelid = '', ''
if not docname:
return None
return make_refnode(builder, fromdocname, docname,
labelid, contnode)
def _resolve_obj_xref(self, env: "BuildEnvironment", fromdocname: str,
builder: "Builder", typ: str, target: str,
@ -1107,12 +1140,27 @@ class StandardDomain(Domain):
RemovedInSphinx40Warning, stacklevel=2)
def warn_missing_reference(app: "Sphinx", domain: Domain, node: pending_xref) -> bool:
if (domain and domain.name != 'std') or node['reftype'] != 'ref':
return None
else:
target = node['reftarget']
if target not in domain.anonlabels: # type: ignore
msg = __('undefined label: %s')
else:
msg = __('Failed to create a cross reference. A title or caption not found: %s')
logger.warning(msg % target, location=node, type='ref', subtype=node['reftype'])
return True
def setup(app: "Sphinx") -> Dict[str, Any]:
app.add_domain(StandardDomain)
app.connect('warn-missing-reference', warn_missing_reference)
return {
'version': 'builtin',
'env_version': 1,
'env_version': 2,
'parallel_read_safe': True,
'parallel_write_safe': True,
}

View File

@ -4,18 +4,18 @@
Global creation environment.
: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 os
import pickle
import posixpath
import warnings
from collections import defaultdict
from copy import copy
from os import path
from typing import Any, Callable, Dict, Generator, Iterator, List, Set, Tuple, Union
from typing import cast
from typing import Any, Callable, Dict, Generator, Iterator, List, Set, Tuple, Union, cast
from docutils import nodes
from docutils.nodes import Node
@ -25,13 +25,12 @@ from sphinx.config import Config
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.domains import Domain
from sphinx.environment.adapters.toctree import TocTree
from sphinx.errors import SphinxError, BuildEnvironmentError, DocumentError, ExtensionError
from sphinx.errors import BuildEnvironmentError, DocumentError, ExtensionError, SphinxError
from sphinx.events import EventManager
from sphinx.locale import __
from sphinx.project import Project
from sphinx.transforms import SphinxTransformer
from sphinx.util import DownloadFiles, FilenameUniqDict
from sphinx.util import logging
from sphinx.util import DownloadFiles, FilenameUniqDict, logging
from sphinx.util.docutils import LoggingReporter
from sphinx.util.i18n import CatalogRepository, docname_to_domain
from sphinx.util.nodes import is_translatable
@ -358,9 +357,9 @@ class BuildEnvironment:
docdir = path.dirname(self.doc2path(docname or self.docname,
base=None))
rel_fn = path.join(docdir, filename)
# the path.abspath() might seem redundant, but otherwise artifacts
# such as ".." will remain in the path
return rel_fn, path.abspath(path.join(self.srcdir, rel_fn))
return (posixpath.normpath(rel_fn),
path.normpath(path.join(self.srcdir, rel_fn)))
@property
def found_docs(self) -> Set[str]:

View File

@ -4,6 +4,6 @@
Sphinx environment adapters
: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 @@
Assets adapter for sphinx.environment.
: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,23 +4,21 @@
Index entries adapters for sphinx.environment.
: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
import unicodedata
from itertools import groupby
from typing import Any, Dict, Pattern, List, Tuple
from typing import cast
from typing import Any, Dict, List, Pattern, Tuple, cast
from sphinx.builders import Builder
from sphinx.domains.index import IndexDomain
from sphinx.environment import BuildEnvironment
from sphinx.errors import NoUri
from sphinx.locale import _, __
from sphinx.util import split_into, logging
from sphinx.util import logging, split_into
logger = logging.getLogger(__name__)

View File

@ -4,19 +4,18 @@
Toctree adapter for sphinx.environment.
: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, Iterable, List
from typing import cast
from typing import Any, Iterable, List, cast
from docutils import nodes
from docutils.nodes import Element, Node
from sphinx import addnodes
from sphinx.locale import __
from sphinx.util import url_re, logging
from sphinx.util import logging, url_re
from sphinx.util.matching import Matcher
from sphinx.util.nodes import clean_astext, process_only_nodes
@ -321,8 +320,10 @@ class TocTree:
toctrees = [] # type: List[Element]
if 'includehidden' not in kwargs:
kwargs['includehidden'] = True
if 'maxdepth' not in kwargs:
if 'maxdepth' not in kwargs or not kwargs['maxdepth']:
kwargs['maxdepth'] = 0
else:
kwargs['maxdepth'] = int(kwargs['maxdepth'])
kwargs['collapse'] = collapse
for toctreenode in doctree.traverse(addnodes.toctree):
toctree = self.resolve(docname, builder, toctreenode, prune=True, **kwargs)

View File

@ -4,7 +4,7 @@
The data collector components for sphinx.environment.
: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 @@
The image collector for sphinx.environment.
: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,7 +26,6 @@ from sphinx.util import logging
from sphinx.util.i18n import get_image_filename_for_language, search_image_for_language
from sphinx.util.images import guess_mimetype
logger = logging.getLogger(__name__)

View File

@ -4,7 +4,7 @@
The dependencies collector components for sphinx.environment.
: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 @@
Index entries collector for sphinx.environment.
: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,8 +18,7 @@ from sphinx.application import Sphinx
from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.environment import BuildEnvironment
from sphinx.environment.collectors import EnvironmentCollector
from sphinx.util import split_index_msg, logging
from sphinx.util import logging, split_index_msg
logger = logging.getLogger(__name__)

View File

@ -4,12 +4,11 @@
The metadata collector components for sphinx.environment.
: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
from typing import cast
from typing import Any, Dict, List, Set, cast
from docutils import nodes

View File

@ -4,7 +4,7 @@
The title collector components for sphinx.environment.
: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,12 +4,11 @@
Toctree collector for sphinx.environment.
: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, TypeVar
from typing import cast
from typing import Any, Dict, List, Set, Tuple, TypeVar, cast
from docutils import nodes
from docutils.nodes import Element, Node
@ -21,7 +20,7 @@ from sphinx.environment.adapters.toctree import TocTree
from sphinx.environment.collectors import EnvironmentCollector
from sphinx.locale import __
from sphinx.transforms import SphinxContentsFilter
from sphinx.util import url_re, logging
from sphinx.util import logging, url_re
if False:
# For type annotation

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