mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '5.x' into autodoc_force_undocumented_rtype
This commit is contained in:
commit
f731bf1999
1
.github/workflows/docutils-latest.yml
vendored
1
.github/workflows/docutils-latest.yml
vendored
@ -7,6 +7,7 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
test:
|
test:
|
||||||
|
if: github.repository_owner == 'sphinx-doc'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
1
.github/workflows/lock.yml
vendored
1
.github/workflows/lock.yml
vendored
@ -10,6 +10,7 @@ permissions:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
action:
|
action:
|
||||||
|
if: github.repository_owner == 'sphinx-doc'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: dessant/lock-threads@v2
|
- uses: dessant/lock-threads@v2
|
||||||
|
2
.github/workflows/main.yml
vendored
2
.github/workflows/main.yml
vendored
@ -60,7 +60,7 @@ jobs:
|
|||||||
if: matrix.coverage
|
if: matrix.coverage
|
||||||
|
|
||||||
windows:
|
windows:
|
||||||
runs-on: windows-latest
|
runs-on: windows-2019
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
architecture: [x86, x64]
|
architecture: [x86, x64]
|
||||||
|
5
.github/workflows/nodejs.yml
vendored
5
.github/workflows/nodejs.yml
vendored
@ -6,14 +6,15 @@ jobs:
|
|||||||
build:
|
build:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
node-version: 10.7
|
node-version: 16
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: Use Node.js ${{ env.node-version }}
|
- name: Use Node.js ${{ env.node-version }}
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: ${{ env.node-version }}
|
node-version: ${{ env.node-version }}
|
||||||
|
cache: "npm"
|
||||||
- run: npm install
|
- run: npm install
|
||||||
- name: Run headless test
|
- name: Run headless test
|
||||||
uses: GabrielBB/xvfb-action@v1
|
uses: GabrielBB/xvfb-action@v1
|
||||||
|
6
.github/workflows/transifex.yml
vendored
6
.github/workflows/transifex.yml
vendored
@ -7,12 +7,13 @@ on:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
push:
|
push:
|
||||||
|
if: github.repository_owner == 'sphinx-doc'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
ref: 4.x
|
ref: 5.x
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
@ -27,12 +28,13 @@ jobs:
|
|||||||
TX_TOKEN: ${{ secrets.TX_TOKEN }}
|
TX_TOKEN: ${{ secrets.TX_TOKEN }}
|
||||||
|
|
||||||
pull:
|
pull:
|
||||||
|
if: github.repository_owner == 'sphinx-doc'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
ref: 4.x
|
ref: 5.x
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v2
|
uses: actions/setup-python@v2
|
||||||
with:
|
with:
|
||||||
|
2
AUTHORS
2
AUTHORS
@ -18,6 +18,7 @@ Other co-maintainers:
|
|||||||
|
|
||||||
Other contributors, listed alphabetically, are:
|
Other contributors, listed alphabetically, are:
|
||||||
|
|
||||||
|
* Adam Turner -- JavaScript improvements
|
||||||
* Alastair Houghton -- Apple Help builder
|
* Alastair Houghton -- Apple Help builder
|
||||||
* Alexander Todorov -- inheritance_diagram tests and improvements
|
* Alexander Todorov -- inheritance_diagram tests and improvements
|
||||||
* Andi Albrecht -- agogo theme
|
* Andi Albrecht -- agogo theme
|
||||||
@ -73,6 +74,7 @@ Other contributors, listed alphabetically, are:
|
|||||||
* Pauli Virtanen -- autodoc improvements, autosummary extension
|
* Pauli Virtanen -- autodoc improvements, autosummary extension
|
||||||
* Eric N. Vander Weele -- autodoc improvements
|
* Eric N. Vander Weele -- autodoc improvements
|
||||||
* Stefan van der Walt -- autosummary extension
|
* Stefan van der Walt -- autosummary extension
|
||||||
|
* Hugo van Kemenade -- support FORCE_COLOR and NO_COLOR
|
||||||
* Thomas Waldmann -- apidoc module fixes
|
* Thomas Waldmann -- apidoc module fixes
|
||||||
* John Waltman -- Texinfo builder
|
* John Waltman -- Texinfo builder
|
||||||
* Barry Warsaw -- setup command improvements
|
* Barry Warsaw -- setup command improvements
|
||||||
|
248
CHANGES
248
CHANGES
@ -1,4 +1,94 @@
|
|||||||
Release 4.4.0 (in development)
|
Release 5.0.0 (in development)
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
|
||||||
|
Incompatible changes
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
* #10031: autosummary: ``sphinx.ext.autosummary.import_by_name()`` now raises
|
||||||
|
``ImportExceptionGroup`` instead of ``ImportError`` when it failed to import
|
||||||
|
target object. Please handle the exception if your extension uses the
|
||||||
|
function to import Python object. As a workaround, you can disable the
|
||||||
|
behavior via ``grouped_exception=False`` keyword argument until v7.0.
|
||||||
|
* #9962: texinfo: Customizing styles of emphasized text via ``@definfoenclose``
|
||||||
|
command was not supported because the command was deprecated since texinfo 6.8
|
||||||
|
* #2068: :confval:`intersphinx_disabled_reftypes` has changed default value
|
||||||
|
from an empty list to ``['std:doc']`` as avoid too surprising silent
|
||||||
|
intersphinx resolutions.
|
||||||
|
To migrate: either add an explicit inventory name to the references
|
||||||
|
intersphinx should resolve, or explicitly set the value of this configuration
|
||||||
|
variable to an empty list.
|
||||||
|
* #9999: LaTeX: separate terms from their definitions by a CR (refs: #9985)
|
||||||
|
* #10062: Change the default language to ``'en'`` if any language is not set in
|
||||||
|
``conf.py``
|
||||||
|
|
||||||
|
Deprecated
|
||||||
|
----------
|
||||||
|
|
||||||
|
* #10028: jQuery and underscore.js will no longer be automatically injected into
|
||||||
|
themes from Sphinx 6.0. If you develop a theme or extension that uses the
|
||||||
|
``jQuery``, ``$``, or ``$u`` global objects, you need to update your
|
||||||
|
JavaScript or use the mitigation below.
|
||||||
|
|
||||||
|
To re-add jQuery and underscore.js, you will need to copy ``jquery.js`` and
|
||||||
|
``underscore.js`` from `the Sphinx repository`_ to your ``static`` directory,
|
||||||
|
and add the following to your ``layout.html``:
|
||||||
|
|
||||||
|
.. _the Sphinx repository: https://github.com/sphinx-doc/sphinx/tree/v4.3.2/sphinx/themes/basic/static
|
||||||
|
.. code-block:: html+jinja
|
||||||
|
|
||||||
|
{%- block scripts %}
|
||||||
|
<script src="{{ pathto('_static/jquery.js', resource=True) }}"></script>
|
||||||
|
<script src="{{ pathto('_static/underscore.js', resource=True) }}"></script>
|
||||||
|
{{ super() }}
|
||||||
|
{%- endblock %}
|
||||||
|
* setuptools integration. The ``build_sphinx`` sub-command for setup.py is
|
||||||
|
marked as deprecated to follow the policy of setuptools team.
|
||||||
|
* The ``locale`` argument of ``sphinx.util.i18n:babel_format_date()`` becomes
|
||||||
|
required
|
||||||
|
* The ``language`` argument of ``sphinx.util.i18n:format_date()`` becomes
|
||||||
|
required
|
||||||
|
* ``sphinx.writers.latex.LaTeXWriter.docclasses``
|
||||||
|
|
||||||
|
Features added
|
||||||
|
--------------
|
||||||
|
|
||||||
|
* #9075: autodoc: The default value of :confval:`autodoc_typehints_format` is
|
||||||
|
changed to ``'smart'``. It will suppress the leading module names of
|
||||||
|
typehints (ex. ``io.StringIO`` -> ``StringIO``).
|
||||||
|
* #9792: autodoc: Add new option for ``autodoc_typehints_description_target`` to
|
||||||
|
include undocumented return values but not undocumented parameters.
|
||||||
|
* #10028: Removed internal usages of JavaScript frameworks (jQuery and
|
||||||
|
underscore.js) and modernised ``doctools.js`` and ``searchtools.js`` to
|
||||||
|
EMCAScript 2018.
|
||||||
|
|
||||||
|
Bugs fixed
|
||||||
|
----------
|
||||||
|
|
||||||
|
* #10279: autodoc: Default values for keyword only arguments in overloaded
|
||||||
|
functions are rendered as a string literal
|
||||||
|
* #10280: autodoc: :confval:`autodoc_docstring_signature` unexpectedly generates
|
||||||
|
return value typehint for constructors if docstring has multiple signatures
|
||||||
|
* #10266: autodoc: :confval:`autodoc_preserve_defaults` does not work for
|
||||||
|
mixture of keyword only arguments with/without defaults
|
||||||
|
* #10310: autodoc: class methods are not documented when decorated with mocked
|
||||||
|
function
|
||||||
|
* #10214: html: invalid language tag was generated if :confval:`language`
|
||||||
|
contains a country code (ex. zh_CN)
|
||||||
|
* #10236: html search: objects are duplicated in search result
|
||||||
|
* #9962: texinfo: Deprecation message for ``@definfoenclose`` command on
|
||||||
|
bulding texinfo document
|
||||||
|
* #10000: LaTeX: glossary terms with common definition are rendered with
|
||||||
|
too much vertical whitespace
|
||||||
|
* #10318: ``:prepend:`` option of :rst:dir:`literalinclude` directive does not
|
||||||
|
work with ``:dedent:`` option
|
||||||
|
|
||||||
|
Testing
|
||||||
|
--------
|
||||||
|
|
||||||
|
Release 4.5.1 (in development)
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
Dependencies
|
Dependencies
|
||||||
@ -13,18 +103,118 @@ Deprecated
|
|||||||
Features added
|
Features added
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
Bugs fixed
|
||||||
|
----------
|
||||||
|
|
||||||
|
Testing
|
||||||
|
--------
|
||||||
|
|
||||||
|
Release 4.5.0 (released Mar 28, 2022)
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
Incompatible changes
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
* #10112: extlinks: Disable hardcoded links detector by default
|
||||||
|
* #9993, #10177: std domain: Disallow to refer an inline target via
|
||||||
|
:rst:role:`ref` role
|
||||||
|
|
||||||
|
Deprecated
|
||||||
|
----------
|
||||||
|
|
||||||
|
* ``sphinx.ext.napoleon.docstring.GoogleDocstring._qualify_name()``
|
||||||
|
|
||||||
|
Features added
|
||||||
|
--------------
|
||||||
|
|
||||||
|
* #10260: Enable ``FORCE_COLOR`` and ``NO_COLOR`` for terminal colouring
|
||||||
|
* #10234: autosummary: Add "autosummary" CSS class to summary tables
|
||||||
|
* #10125: extlinks: Improve suggestion message for a reference having title
|
||||||
|
* #10112: extlinks: Add :confval:`extlinks_detect_hardcoded_links` to enable
|
||||||
|
hardcoded links detector feature
|
||||||
|
* #9494, #9456: html search: Add a config variable
|
||||||
|
:confval:`html_show_search_summary` to enable/disable the search summaries
|
||||||
|
* #9337: HTML theme, add option ``enable_search_shortcuts`` that enables :kbd:'/' as
|
||||||
|
a Quick search shortcut and :kbd:`Esc` shortcut that
|
||||||
|
removes search highlighting.
|
||||||
|
* #10107: i18n: Allow to suppress translation warnings by adding ``#noqa``
|
||||||
|
comment to the tail of each translation message
|
||||||
|
* #10252: C++, support attributes on classes, unions, and enums.
|
||||||
|
* #10253: :rst:dir:`pep` role now generates URLs based on peps.python.org
|
||||||
|
|
||||||
|
Bugs fixed
|
||||||
|
----------
|
||||||
|
|
||||||
|
* #9876: autodoc: Failed to document an imported class that is built from native
|
||||||
|
binary module
|
||||||
|
* #10133: autodoc: Crashed when mocked module is used for type annotation
|
||||||
|
* #10146: autodoc: :confval:`autodoc_default_options` does not support
|
||||||
|
``no-value`` option
|
||||||
|
* #9971: autodoc: TypeError is raised when the target object is annotated by
|
||||||
|
unhashable object
|
||||||
|
* #10205: extlinks: Failed to compile regexp on checking hardcoded links
|
||||||
|
* #10277: html search: Could not search short words (ex. "use")
|
||||||
|
* #9529: LaTeX: named auto numbered footnote (ex. ``[#named]``) that is referred
|
||||||
|
multiple times was rendered to a question mark
|
||||||
|
* #9924: LaTeX: multi-line :rst:dir:`cpp:function` directive has big vertical
|
||||||
|
spacing in Latexpdf
|
||||||
|
* #10158: LaTeX: excessive whitespace since v4.4.0 for undocumented
|
||||||
|
variables/structure members
|
||||||
|
* #10175: LaTeX: named footnote reference is linked to an incorrect footnote if
|
||||||
|
the name is also used in the different document
|
||||||
|
* #10269: manpage: Failed to resolve the title of :ref: cross references
|
||||||
|
* #10179: i18n: suppress "rST localization" warning
|
||||||
|
* #10118: imgconverter: Unnecessary availablity check is called for remote URIs
|
||||||
|
* #10181: napoleon: attributes are displayed like class attributes for google
|
||||||
|
style docstrings when :confval:`napoleon_use_ivar` is enabled
|
||||||
|
* #10122: sphinx-build: make.bat does not check the installation of sphinx-build
|
||||||
|
command before showing help
|
||||||
|
|
||||||
|
Release 4.4.0 (released Jan 17, 2022)
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
|
||||||
|
* #10007: Use ``importlib_metadata`` for python-3.9 or older
|
||||||
|
* #10007: Drop ``setuptools``
|
||||||
|
|
||||||
|
Features added
|
||||||
|
--------------
|
||||||
|
|
||||||
|
* #9075: autodoc: Add a config variable :confval:`autodoc_typehints_format`
|
||||||
|
to suppress the leading module names of typehints of function signatures (ex.
|
||||||
|
``io.StringIO`` -> ``StringIO``)
|
||||||
* #9831: Autosummary now documents only the members specified in a module's
|
* #9831: Autosummary now documents only the members specified in a module's
|
||||||
``__all__`` attribute if :confval:`autosummary_ignore_module_all` is set to
|
``__all__`` attribute if :confval:`autosummary_ignore_module_all` is set to
|
||||||
``False``. The default behaviour is unchanged. Autogen also now supports
|
``False``. The default behaviour is unchanged. Autogen also now supports
|
||||||
this behavior with the ``--respect-module-all`` switch.
|
this behavior with the ``--respect-module-all`` switch.
|
||||||
|
* #9555: autosummary: Improve error messages on failure to load target object
|
||||||
* #9800: extlinks: Emit warning if a hardcoded link is replaceable
|
* #9800: extlinks: Emit warning if a hardcoded link is replaceable
|
||||||
by an extlink, suggesting a replacement.
|
by an extlink, suggesting a replacement.
|
||||||
|
* #9961: html: Support nested <kbd> HTML elements in other HTML builders
|
||||||
|
* #10013: html: Allow to change the loading method of JS via ``loading_method``
|
||||||
|
parameter for :meth:`Sphinx.add_js_file()`
|
||||||
|
* #9551: html search: "Hide Search Matches" link removes "highlight" parameter
|
||||||
|
from URL
|
||||||
* #9815: html theme: Wrap sidebar components in div to allow customizing their
|
* #9815: html theme: Wrap sidebar components in div to allow customizing their
|
||||||
layout via CSS
|
layout via CSS
|
||||||
|
* #9827: i18n: Sort items in glossary by translated terms
|
||||||
* #9899: py domain: Allows to specify cross-reference specifier (``.`` and
|
* #9899: py domain: Allows to specify cross-reference specifier (``.`` and
|
||||||
``~``) as ``:type:`` option
|
``~``) as ``:type:`` option
|
||||||
* #9792: autodoc: Add new option for ``autodoc_typehints_description_target`` to
|
* #9894: linkcheck: add option ``linkcheck_exclude_documents`` to disable link
|
||||||
include undocumented return values but not undocumented parameters.
|
checking in matched documents.
|
||||||
|
* #9793: sphinx-build: Allow to use the parallel build feature in macOS on macOS
|
||||||
|
and Python3.8+
|
||||||
|
* #10055: sphinx-build: Create directories when ``-w`` option given
|
||||||
|
* #9993: std domain: Allow to refer an inline target (ex. ``_`target name```)
|
||||||
|
via :rst:role:`ref` role
|
||||||
|
* #9981: std domain: Strip value part of the option directive from general index
|
||||||
|
* #9391: texinfo: improve variable in ``samp`` role
|
||||||
|
* #9578: texinfo: Add :confval:`texinfo_cross_references` to disable cross
|
||||||
|
references for readability with standalone readers
|
||||||
|
* #9822 (and #9062), add new Intersphinx role :rst:role:`external` for explict
|
||||||
|
lookup in the external projects, without resolving to the local project.
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
@ -33,32 +223,42 @@ Bugs fixed
|
|||||||
* #9883: autodoc: doccomment for the alias to mocked object was ignored
|
* #9883: autodoc: doccomment for the alias to mocked object was ignored
|
||||||
* #9908: autodoc: debug message is shown on building document using NewTypes
|
* #9908: autodoc: debug message is shown on building document using NewTypes
|
||||||
with Python 3.10
|
with Python 3.10
|
||||||
|
* #9968: autodoc: instance variables are not shown if __init__ method has
|
||||||
|
position-only-arguments
|
||||||
|
* #9194: autodoc: types under the "typing" module are not hyperlinked
|
||||||
|
* #10009: autodoc: Crashes if target object raises an error on getting docstring
|
||||||
|
* #10058: autosummary: Imported members are not shown when
|
||||||
|
``autodoc_class_signature = 'separated'``
|
||||||
|
* #9947: i18n: topic directive having a bullet list can't be translatable
|
||||||
* #9878: mathjax: MathJax configuration is placed after loading MathJax itself
|
* #9878: mathjax: MathJax configuration is placed after loading MathJax itself
|
||||||
|
* #9932: napoleon: empty "returns" section is generated even if no description
|
||||||
* #9857: Generated RFC links use outdated base url
|
* #9857: Generated RFC links use outdated base url
|
||||||
|
* #9909: HTML, prevent line-wrapping in literal text.
|
||||||
|
* #10061: html theme: Configuration values added by themes are not be able to
|
||||||
|
override from conf.py
|
||||||
|
* #10073: imgconverter: Unnecessary availablity check is called for "data" URIs
|
||||||
|
* #9925: LaTeX: prohibit also with ``'xelatex'`` line splitting at dashes of
|
||||||
|
inline and parsed literals
|
||||||
|
* #9944: LaTeX: extra vertical whitespace for some nested declarations
|
||||||
|
* #9940: LaTeX: Multi-function declaration in Python domain has cramped
|
||||||
|
vertical spacing in latexpdf output
|
||||||
|
* #10015: py domain: types under the "typing" module are not hyperlinked defined
|
||||||
|
at info-field-list
|
||||||
|
* #9390: texinfo: Do not emit labels inside footnotes
|
||||||
|
* #9413: xml: Invalid XML was generated when cross referencing python objects
|
||||||
|
* #9979: Error level messages were displayed as warning messages
|
||||||
|
* #10057: Failed to scan documents if the project is placed onto the root
|
||||||
|
directory
|
||||||
|
* #9636: code-block: ``:dedent:`` without argument did strip newlines
|
||||||
|
|
||||||
Testing
|
Release 4.3.2 (released Dec 19, 2021)
|
||||||
--------
|
=====================================
|
||||||
|
|
||||||
Release 4.3.2 (in development)
|
|
||||||
==============================
|
|
||||||
|
|
||||||
Dependencies
|
|
||||||
------------
|
|
||||||
|
|
||||||
Incompatible changes
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Deprecated
|
|
||||||
----------
|
|
||||||
|
|
||||||
Features added
|
|
||||||
--------------
|
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Testing
|
* #9917: C and C++, parse fundamental types no matter the order of simple type
|
||||||
--------
|
specifiers.
|
||||||
|
|
||||||
Release 4.3.1 (released Nov 28, 2021)
|
Release 4.3.1 (released Nov 28, 2021)
|
||||||
=====================================
|
=====================================
|
||||||
@ -75,7 +275,7 @@ Bugs fixed
|
|||||||
* #9838: autodoc: AttributeError is raised on building document for functions
|
* #9838: autodoc: AttributeError is raised on building document for functions
|
||||||
decorated by functools.lru_cache
|
decorated by functools.lru_cache
|
||||||
* #9879: autodoc: AttributeError is raised on building document for an object
|
* #9879: autodoc: AttributeError is raised on building document for an object
|
||||||
having invalid __doc__ atribute
|
having invalid __doc__ attribute
|
||||||
* #9844: autodoc: Failed to process a function wrapped with functools.partial if
|
* #9844: autodoc: Failed to process a function wrapped with functools.partial if
|
||||||
:confval:`autodoc_preserve_defaults` enabled
|
:confval:`autodoc_preserve_defaults` enabled
|
||||||
* #9872: html: Class namespace collision between autodoc signatures and
|
* #9872: html: Class namespace collision between autodoc signatures and
|
||||||
@ -160,7 +360,7 @@ Bugs fixed
|
|||||||
* #9752: autodoc: Failed to detect type annotation for slots attribute
|
* #9752: autodoc: Failed to detect type annotation for slots attribute
|
||||||
* #9756: autodoc: Crashed if classmethod does not have __func__ attribute
|
* #9756: autodoc: Crashed if classmethod does not have __func__ attribute
|
||||||
* #9757: autodoc: :confval:`autodoc_inherit_docstrings` does not effect to
|
* #9757: autodoc: :confval:`autodoc_inherit_docstrings` does not effect to
|
||||||
overriden classmethods
|
overridden classmethods
|
||||||
* #9781: autodoc: :confval:`autodoc_preserve_defaults` does not support
|
* #9781: autodoc: :confval:`autodoc_preserve_defaults` does not support
|
||||||
hexadecimal numeric
|
hexadecimal numeric
|
||||||
* #9630: autosummary: Failed to build summary table if :confval:`primary_domain`
|
* #9630: autosummary: Failed to build summary table if :confval:`primary_domain`
|
||||||
|
90
EXAMPLES
90
EXAMPLES
@ -15,9 +15,11 @@ Documentation using the alabaster theme
|
|||||||
* `Alabaster <https://alabaster.readthedocs.io/>`__
|
* `Alabaster <https://alabaster.readthedocs.io/>`__
|
||||||
* `Blinker <https://pythonhosted.org/blinker/>`__
|
* `Blinker <https://pythonhosted.org/blinker/>`__
|
||||||
* `Calibre <https://manual.calibre-ebook.com/>`__
|
* `Calibre <https://manual.calibre-ebook.com/>`__
|
||||||
|
* `CherryPy <https://cherrypy.readthedocs.io/>`__
|
||||||
* `Click <https://click.palletsprojects.com/>`__ (customized)
|
* `Click <https://click.palletsprojects.com/>`__ (customized)
|
||||||
* `coala <https://docs.coala.io/>`__ (customized)
|
* `coala <https://docs.coala.io/>`__ (customized)
|
||||||
* `CodePy <https://documen.tician.de/codepy/>`__
|
* `CodePy <https://documen.tician.de/codepy/>`__
|
||||||
|
* `Django Q <https://django-q.readthedocs.io/>`__
|
||||||
* `Eve <https://docs.python-eve.org/>`__ (Python REST API framework)
|
* `Eve <https://docs.python-eve.org/>`__ (Python REST API framework)
|
||||||
* `Fabric <https://docs.fabfile.org/>`__
|
* `Fabric <https://docs.fabfile.org/>`__
|
||||||
* `Fityk <https://fityk.nieto.pl/>`__
|
* `Fityk <https://fityk.nieto.pl/>`__
|
||||||
@ -30,19 +32,21 @@ Documentation using the alabaster theme
|
|||||||
* `MDAnalysis <https://www.mdanalysis.org/docs/>`__ (customized)
|
* `MDAnalysis <https://www.mdanalysis.org/docs/>`__ (customized)
|
||||||
* `MeshPy <https://documen.tician.de/meshpy/>`__
|
* `MeshPy <https://documen.tician.de/meshpy/>`__
|
||||||
* `Molecule <https://molecule.readthedocs.io/>`__
|
* `Molecule <https://molecule.readthedocs.io/>`__
|
||||||
|
* `Momotor LTI <https://momotor.org/doc/lti/canvas/>`__
|
||||||
|
* `Podman <https://docs.podman.io/>`__
|
||||||
* `PyCUDA <https://documen.tician.de/pycuda/>`__
|
* `PyCUDA <https://documen.tician.de/pycuda/>`__
|
||||||
* `PyOpenCL <https://documen.tician.de/pyopencl/>`__
|
* `PyOpenCL <https://documen.tician.de/pyopencl/>`__
|
||||||
* `PyLangAcq <https://pylangacq.org/>`__
|
* `PyLangAcq <https://pylangacq.org/>`__
|
||||||
* `pytest <https://docs.pytest.org/>`__ (customized)
|
* `pytest <https://docs.pytest.org/>`__ (customized)
|
||||||
* `python-apt <https://apt.alioth.debian.org/python-apt-doc/>`__
|
* `python-apt <https://apt-team.pages.debian.net/python-apt/>`__
|
||||||
* `PyVisfile <https://documen.tician.de/pyvisfile/>`__
|
* `PyVisfile <https://documen.tician.de/pyvisfile/>`__
|
||||||
* `Requests <http://www.python-requests.org/>`__
|
* `Requests <https://docs.python-requests.org/>`__
|
||||||
* `searx <https://asciimoo.github.io/searx/>`__
|
* `searx <https://asciimoo.github.io/searx/>`__
|
||||||
* `Spyder <https://docs.spyder-ide.org/>`__ (customized)
|
* `Spyder <https://docs.spyder-ide.org/>`__ (customized)
|
||||||
* `Tablib <http://docs.python-tablib.org/>`__
|
* `Tablib <http://docs.python-tablib.org/>`__
|
||||||
* `urllib3 <https://urllib3.readthedocs.io/>`__ (customized)
|
* `urllib3 <https://urllib3.readthedocs.io/>`__ (customized)
|
||||||
* `Werkzeug <https://werkzeug.palletsprojects.com/>`__
|
* `Werkzeug <https://werkzeug.palletsprojects.com/>`__
|
||||||
* `Write the Docs <https://writethedocs-www.readthedocs.io/>`__
|
* `Write the Docs <https://www.writethedocs.org/>`__
|
||||||
|
|
||||||
Documentation using the classic theme
|
Documentation using the classic theme
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
@ -58,8 +62,6 @@ Documentation using the classic theme
|
|||||||
* `Buildbot <https://docs.buildbot.net/latest/>`__
|
* `Buildbot <https://docs.buildbot.net/latest/>`__
|
||||||
* `CMake <https://cmake.org/documentation/>`__ (customized)
|
* `CMake <https://cmake.org/documentation/>`__ (customized)
|
||||||
* `Chaco <https://docs.enthought.com/chaco/>`__ (customized)
|
* `Chaco <https://docs.enthought.com/chaco/>`__ (customized)
|
||||||
* `CORE <https://downloads.pf.itd.nrl.navy.mil/docs/core/core-html/>`__
|
|
||||||
* `CORE Python modules <https://downloads.pf.itd.nrl.navy.mil/docs/core/core-python-html/>`__
|
|
||||||
* `Cormoran <http://cormoran.nhopkg.org/docs/>`__
|
* `Cormoran <http://cormoran.nhopkg.org/docs/>`__
|
||||||
* `DEAP <https://deap.readthedocs.io/>`__ (customized)
|
* `DEAP <https://deap.readthedocs.io/>`__ (customized)
|
||||||
* `Director <https://pythonhosted.org/director/>`__
|
* `Director <https://pythonhosted.org/director/>`__
|
||||||
@ -67,27 +69,26 @@ Documentation using the classic theme
|
|||||||
* `F2py <http://f2py.sourceforge.net/docs/>`__
|
* `F2py <http://f2py.sourceforge.net/docs/>`__
|
||||||
* `Generic Mapping Tools (GMT) <https://gmt.soest.hawaii.edu/doc/latest/>`__ (customized)
|
* `Generic Mapping Tools (GMT) <https://gmt.soest.hawaii.edu/doc/latest/>`__ (customized)
|
||||||
* `Genomedata <https://noble.gs.washington.edu/proj/genomedata/doc/1.3.3/>`__
|
* `Genomedata <https://noble.gs.washington.edu/proj/genomedata/doc/1.3.3/>`__
|
||||||
* `GetFEM++ <http://getfem.org/>`__ (customized)
|
* `GetFEM++ <https://getfem.org/>`__ (customized)
|
||||||
* `Glasgow Haskell Compiler <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/>`__ (customized)
|
* `Glasgow Haskell Compiler <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/>`__ (customized)
|
||||||
* `Grok <http://grok.zope.org/doc/current/>`__ (customized)
|
* `Grok <http://grok.zope.org/doc/current/>`__ (customized)
|
||||||
* `GROMACS <https://manual.gromacs.org/documentation/>`__
|
* `GROMACS <https://manual.gromacs.org/documentation/>`__
|
||||||
* `GSL Shell <https://www.nongnu.org/gsl-shell/>`__
|
* `GSL Shell <https://www.nongnu.org/gsl-shell/>`__
|
||||||
* `Hands-on Python Tutorial <https://anh.cs.luc.edu/python/hands-on/3.1/handsonHtml/>`__
|
* `Hands-on Python Tutorial <http://anh.cs.luc.edu/python/hands-on/3.1/handsonHtml/>`__
|
||||||
* `Kaa <https://api.freevo.org/kaa-base/>`__ (customized)
|
* `Kaa <https://freevo.github.io/kaa-base/>`__ (customized)
|
||||||
* `Leo <https://leoeditor.com/>`__
|
* `Leo <https://leoeditor.com/>`__ (customized)
|
||||||
* `LEPL <http://www.acooke.org/lepl/>`__ (customized)
|
|
||||||
* `Mayavi <https://docs.enthought.com/mayavi/mayavi/>`__ (customized)
|
* `Mayavi <https://docs.enthought.com/mayavi/mayavi/>`__ (customized)
|
||||||
* `MediaGoblin <https://mediagoblin.readthedocs.io/>`__ (customized)
|
* `MediaGoblin <https://mediagoblin.readthedocs.io/>`__ (customized)
|
||||||
* `mpmath <https://mpmath.org/doc/current/>`__
|
* `mpmath <https://mpmath.org/doc/current/>`__
|
||||||
* `OpenCV <https://docs.opencv.org/>`__ (customized)
|
* `OpenCV <https://docs.opencv.org/>`__ (customized)
|
||||||
* `OpenEXR <https://excamera.com/articles/26/doc/index.html>`__
|
* `OpenEXR <https://excamera.com/articles/26/doc/index.html>`__
|
||||||
* `OpenGDA <http://www.opengda.org/gdadoc/html/>`__
|
* `OpenGDA <http://www.opengda.org/documentation/>`__
|
||||||
* `Peach^3 <https://peach3.nl/doc/latest/userdoc/>`__ (customized)
|
* `phpDocumentor <https://docs.phpdoc.org/>`__ (customized)
|
||||||
* `Plone <https://docs.plone.org/>`__ (customized)
|
* `Plone <https://docs.plone.org/>`__ (customized)
|
||||||
* `PyEMD <https://pyemd.readthedocs.io/>`__
|
* `PyEMD <https://pyemd.readthedocs.io/>`__
|
||||||
* `Pyevolve <http://pyevolve.sourceforge.net/>`__
|
* `Pyevolve <http://pyevolve.sourceforge.net/>`__
|
||||||
* `Pygame <https://www.pygame.org/docs/>`__ (customized)
|
* `Pygame <https://www.pygame.org/docs/>`__ (customized)
|
||||||
* `PyMQI <https://pythonhosted.org/pymqi/>`__
|
* `PyMQI <https://dsuch.github.io/pymqi/>`__
|
||||||
* `PyQt4 <http://pyqt.sourceforge.net/Docs/PyQt4/>`__ (customized)
|
* `PyQt4 <http://pyqt.sourceforge.net/Docs/PyQt4/>`__ (customized)
|
||||||
* `PyQt5 <http://pyqt.sourceforge.net/Docs/PyQt5/>`__ (customized)
|
* `PyQt5 <http://pyqt.sourceforge.net/Docs/PyQt5/>`__ (customized)
|
||||||
* `Python 2 <https://docs.python.org/2/>`__
|
* `Python 2 <https://docs.python.org/2/>`__
|
||||||
@ -120,7 +121,8 @@ Documentation using the sphinxdoc theme
|
|||||||
* `MDAnalysis Tutorial <https://www.mdanalysis.org/MDAnalysisTutorial/>`__
|
* `MDAnalysis Tutorial <https://www.mdanalysis.org/MDAnalysisTutorial/>`__
|
||||||
* `NetworkX <https://networkx.github.io/>`__
|
* `NetworkX <https://networkx.github.io/>`__
|
||||||
* `PyCantonese <https://pycantonese.org/>`__
|
* `PyCantonese <https://pycantonese.org/>`__
|
||||||
* `Pyre <https://docs.danse.us/pyre/sphinx/>`__
|
* `PyRe <https://hackl.science/pyre/>`__
|
||||||
|
* `Pyre <https://pyre.readthedocs.io/>`__
|
||||||
* `pySPACE <https://pyspace.github.io/pyspace/>`__
|
* `pySPACE <https://pyspace.github.io/pyspace/>`__
|
||||||
* `Pysparse <http://pysparse.sourceforge.net/>`__
|
* `Pysparse <http://pysparse.sourceforge.net/>`__
|
||||||
* `PyTango <https://www.esrf.eu/computing/cs/tango/tango_doc/kernel_doc/pytango/latest/>`__
|
* `PyTango <https://www.esrf.eu/computing/cs/tango/tango_doc/kernel_doc/pytango/latest/>`__
|
||||||
@ -136,8 +138,7 @@ Documentation using the nature theme
|
|||||||
* `Alembic <https://alembic.sqlalchemy.org/>`__
|
* `Alembic <https://alembic.sqlalchemy.org/>`__
|
||||||
* `Cython <https://docs.cython.org/>`__
|
* `Cython <https://docs.cython.org/>`__
|
||||||
* `easybuild <https://easybuild.readthedocs.io/>`__
|
* `easybuild <https://easybuild.readthedocs.io/>`__
|
||||||
* `jsFiddle <http://doc.jsfiddle.net/>`__
|
* `libLAS <https://liblas.org/>`__ (customized)
|
||||||
* `libLAS <https://www.liblas.org/>`__ (customized)
|
|
||||||
* `Lmod <https://lmod.readthedocs.io/>`__
|
* `Lmod <https://lmod.readthedocs.io/>`__
|
||||||
* `MapServer <https://mapserver.org/>`__ (customized)
|
* `MapServer <https://mapserver.org/>`__ (customized)
|
||||||
* `Pandas <https://pandas.pydata.org/pandas-docs/stable/>`__
|
* `Pandas <https://pandas.pydata.org/pandas-docs/stable/>`__
|
||||||
@ -154,11 +155,10 @@ Documentation using another builtin theme
|
|||||||
* `Breathe <https://breathe.readthedocs.io/>`__ (haiku)
|
* `Breathe <https://breathe.readthedocs.io/>`__ (haiku)
|
||||||
* `MPipe <https://vmlaker.github.io/mpipe/>`__ (sphinx13)
|
* `MPipe <https://vmlaker.github.io/mpipe/>`__ (sphinx13)
|
||||||
* `NLTK <https://www.nltk.org/>`__ (agogo)
|
* `NLTK <https://www.nltk.org/>`__ (agogo)
|
||||||
* `Programmieren mit PyGTK und Glade (German) <https://www.florian-diesch.de/doc/python-und-glade/online/>`__ (agogo, customized)
|
|
||||||
* `PyPubSub <https://pypubsub.readthedocs.io/>`__ (bizstyle)
|
* `PyPubSub <https://pypubsub.readthedocs.io/>`__ (bizstyle)
|
||||||
* `Pylons <https://docs.pylonsproject.org/projects/pylons-webframework/>`__ (pyramid)
|
* `Pylons <https://docs.pylonsproject.org/projects/pylons-webframework/>`__ (pyramid)
|
||||||
* `Pyramid web framework <https://docs.pylonsproject.org/projects/pyramid/>`__ (pyramid)
|
* `Pyramid web framework <https://docs.pylonsproject.org/projects/pyramid/>`__ (pyramid)
|
||||||
* `RxDock <https://www.rxdock.org/documentation/html/devel/>`__
|
* `RxDock <https://www.rxdock.org/documentation/devel/html/>`__
|
||||||
* `Sphinx <https://www.sphinx-doc.org/>`__ (sphinx13) :-)
|
* `Sphinx <https://www.sphinx-doc.org/>`__ (sphinx13) :-)
|
||||||
* `Valence <https://docs.valence.desire2learn.com/>`__ (haiku, customized)
|
* `Valence <https://docs.valence.desire2learn.com/>`__ (haiku, customized)
|
||||||
|
|
||||||
@ -176,9 +176,12 @@ Documentation using sphinx_rtd_theme
|
|||||||
* `Blender Reference Manual <https://docs.blender.org/manual/>`__
|
* `Blender Reference Manual <https://docs.blender.org/manual/>`__
|
||||||
* `Blocks <https://blocks.readthedocs.io/>`__
|
* `Blocks <https://blocks.readthedocs.io/>`__
|
||||||
* `bootstrap-datepicker <https://bootstrap-datepicker.readthedocs.io/>`__
|
* `bootstrap-datepicker <https://bootstrap-datepicker.readthedocs.io/>`__
|
||||||
* `Certbot <https://letsencrypt.readthedocs.io/>`__
|
* `Certbot <https://certbot.eff.org/docs/>`__
|
||||||
|
* `CKAN <https://docs.ckan.org/>`__
|
||||||
|
* `Copr Buildsystem <https://docs.pagure.org/copr.copr/>`__ (customized)
|
||||||
|
* `Coreboot <https://doc.coreboot.org/>`__
|
||||||
* `Chainer <https://docs.chainer.org/>`__ (customized)
|
* `Chainer <https://docs.chainer.org/>`__ (customized)
|
||||||
* `CherryPy <https://docs.cherrypy.org/>`__
|
* `citeproc-js <https://citeproc-js.readthedocs.io/>`__
|
||||||
* `cloud-init <https://cloudinit.readthedocs.io/>`__
|
* `cloud-init <https://cloudinit.readthedocs.io/>`__
|
||||||
* `CodeIgniter <https://www.codeigniter.com/user_guide/>`__
|
* `CodeIgniter <https://www.codeigniter.com/user_guide/>`__
|
||||||
* `Conda <https://conda.io/docs/>`__
|
* `Conda <https://conda.io/docs/>`__
|
||||||
@ -187,7 +190,9 @@ Documentation using sphinx_rtd_theme
|
|||||||
* `Databricks <https://docs.databricks.com/>`__ (customized)
|
* `Databricks <https://docs.databricks.com/>`__ (customized)
|
||||||
* `Dataiku DSS <https://doc.dataiku.com/>`__
|
* `Dataiku DSS <https://doc.dataiku.com/>`__
|
||||||
* `DNF <https://dnf.readthedocs.io/>`__
|
* `DNF <https://dnf.readthedocs.io/>`__
|
||||||
|
* `Distro Tracker <https://qa.pages.debian.net/distro-tracker/>`__
|
||||||
* `Django-cas-ng <https://djangocas.dev/docs/>`__
|
* `Django-cas-ng <https://djangocas.dev/docs/>`__
|
||||||
|
* `dj-stripe <https://dj-stripe.readthedocs.io/>`__
|
||||||
* `edX <https://docs.edx.org/>`__
|
* `edX <https://docs.edx.org/>`__
|
||||||
* `Electrum <https://docs.electrum.org/>`__
|
* `Electrum <https://docs.electrum.org/>`__
|
||||||
* `Elemental <https://libelemental.org/documentation/dev/>`__
|
* `Elemental <https://libelemental.org/documentation/dev/>`__
|
||||||
@ -207,13 +212,15 @@ Documentation using sphinx_rtd_theme
|
|||||||
* `Graylog <https://docs.graylog.org/>`__
|
* `Graylog <https://docs.graylog.org/>`__
|
||||||
* `GPAW <https://wiki.fysik.dtu.dk/gpaw/>`__ (customized)
|
* `GPAW <https://wiki.fysik.dtu.dk/gpaw/>`__ (customized)
|
||||||
* `HDF5 for Python (h5py) <https://docs.h5py.org/>`__
|
* `HDF5 for Python (h5py) <https://docs.h5py.org/>`__
|
||||||
|
* `HyperKitty <https://hyperkitty.readthedocs.io/>`__
|
||||||
* `Hyperledger Fabric <https://hyperledger-fabric.readthedocs.io/>`__
|
* `Hyperledger Fabric <https://hyperledger-fabric.readthedocs.io/>`__
|
||||||
* `Hyperledger Sawtooth <https://intelledger.github.io/>`__
|
* `Hyperledger Sawtooth <https://sawtooth.hyperledger.org/docs/>`__
|
||||||
* `IdentityServer <https://docs.identityserver.io/>`__
|
* `IdentityServer <https://docs.identityserver.io/>`__
|
||||||
* `Idris <https://docs.idris-lang.org/>`__
|
* `Idris <https://docs.idris-lang.org/>`__
|
||||||
|
* `Inkscape <https://inkscape-manuals.readthedocs.io/>`__ (customized)
|
||||||
* `javasphinx <https://bronto-javasphinx.readthedocs.io/>`__
|
* `javasphinx <https://bronto-javasphinx.readthedocs.io/>`__
|
||||||
* `Julia <https://julia.readthedocs.io/>`__
|
|
||||||
* `Jupyter Notebook <https://jupyter-notebook.readthedocs.io/>`__
|
* `Jupyter Notebook <https://jupyter-notebook.readthedocs.io/>`__
|
||||||
|
* `Kanboard <https://docs.kanboard.org/>`__
|
||||||
* `Lasagne <https://lasagne.readthedocs.io/>`__
|
* `Lasagne <https://lasagne.readthedocs.io/>`__
|
||||||
* `latexindent.pl <https://latexindentpl.readthedocs.io/>`__
|
* `latexindent.pl <https://latexindentpl.readthedocs.io/>`__
|
||||||
* `Learning Apache Spark with Python <https://runawayhorse001.github.io/LearningApacheSpark>`__
|
* `Learning Apache Spark with Python <https://runawayhorse001.github.io/LearningApacheSpark>`__
|
||||||
@ -226,7 +233,6 @@ Documentation using sphinx_rtd_theme
|
|||||||
* `Mesa 3D <https://docs.mesa3d.org/>`__
|
* `Mesa 3D <https://docs.mesa3d.org/>`__
|
||||||
* `micca - MICrobial Community Analysis <https://micca.readthedocs.io/>`__
|
* `micca - MICrobial Community Analysis <https://micca.readthedocs.io/>`__
|
||||||
* `MicroPython <https://docs.micropython.org/>`__
|
* `MicroPython <https://docs.micropython.org/>`__
|
||||||
* `Minds <https://www.minds.org/docs/>`__ (customized)
|
|
||||||
* `Mink <https://mink.behat.org/>`__
|
* `Mink <https://mink.behat.org/>`__
|
||||||
* `Mockery <https://docs.mockery.io/>`__
|
* `Mockery <https://docs.mockery.io/>`__
|
||||||
* `mod_wsgi <https://modwsgi.readthedocs.io/>`__
|
* `mod_wsgi <https://modwsgi.readthedocs.io/>`__
|
||||||
@ -234,9 +240,14 @@ Documentation using sphinx_rtd_theme
|
|||||||
* `Mopidy <https://docs.mopidy.com/>`__
|
* `Mopidy <https://docs.mopidy.com/>`__
|
||||||
* `mpi4py <https://mpi4py.readthedocs.io/>`__
|
* `mpi4py <https://mpi4py.readthedocs.io/>`__
|
||||||
* `MyHDL <https://docs.myhdl.org/>`__
|
* `MyHDL <https://docs.myhdl.org/>`__
|
||||||
|
* `Mypy <https://mypy.readthedocs.io/>`__
|
||||||
|
* `Netgate Docs <https://docs.netgate.com/>`__
|
||||||
|
* `Nextcloud Server <https://docs.nextcloud.com/#server>`__
|
||||||
* `Nextflow <https://www.nextflow.io/docs/latest/index.html>`__
|
* `Nextflow <https://www.nextflow.io/docs/latest/index.html>`__
|
||||||
|
* `nghttp2 <https://nghttp2.org/documentation/>`__
|
||||||
* `NICOS <https://forge.frm2.tum.de/nicos/doc/nicos-master/>`__ (customized)
|
* `NICOS <https://forge.frm2.tum.de/nicos/doc/nicos-master/>`__ (customized)
|
||||||
* `OpenFAST <https://openfast.readthedocs.io/>`__
|
* `OpenFAST <https://openfast.readthedocs.io/>`__
|
||||||
|
* `Panda3D <https://docs.panda3d.org/>`__ (customized)
|
||||||
* `Pelican <https://docs.getpelican.com/>`__
|
* `Pelican <https://docs.getpelican.com/>`__
|
||||||
* `picamera <https://picamera.readthedocs.io/>`__
|
* `picamera <https://picamera.readthedocs.io/>`__
|
||||||
* `Pillow <https://pillow.readthedocs.io/>`__
|
* `Pillow <https://pillow.readthedocs.io/>`__
|
||||||
@ -245,15 +256,21 @@ Documentation using sphinx_rtd_theme
|
|||||||
* `peewee <https://docs.peewee-orm.com/>`__
|
* `peewee <https://docs.peewee-orm.com/>`__
|
||||||
* `Phinx <https://docs.phinx.org/>`__
|
* `Phinx <https://docs.phinx.org/>`__
|
||||||
* `phpMyAdmin <https://docs.phpmyadmin.net/>`__
|
* `phpMyAdmin <https://docs.phpmyadmin.net/>`__
|
||||||
|
* `PHPUnit <https://phpunit.readthedocs.io/>`__
|
||||||
|
* `PHPWord <https://phpword.readthedocs.io/>`__
|
||||||
* `PROS <https://pros.cs.purdue.edu/v5/>`__ (customized)
|
* `PROS <https://pros.cs.purdue.edu/v5/>`__ (customized)
|
||||||
* `Pushkin <http://docs.pushkin.io/>`__
|
* `Pushkin <http://docs.pushkin.io/>`__
|
||||||
* `Pweave <https://mpastell.com/pweave/>`__
|
* `Pweave <https://mpastell.com/pweave/>`__
|
||||||
|
* `pyca/cryptograhpy <https://cryptography.io/>`__
|
||||||
|
* `PyNaCl <https://pynacl.readthedocs.io/>`__
|
||||||
|
* `pyOpenSSL <https://www.pyopenssl.org/>`__
|
||||||
* `PyPy <https://doc.pypy.org/>`__
|
* `PyPy <https://doc.pypy.org/>`__
|
||||||
* `python-sqlparse <https://sqlparse.readthedocs.io/>`__
|
* `python-sqlparse <https://sqlparse.readthedocs.io/>`__
|
||||||
* `PyVISA <https://pyvisa.readthedocs.io/>`__
|
* `PyVISA <https://pyvisa.readthedocs.io/>`__
|
||||||
* `pyvista <https://docs.pyvista.org/>`__
|
* `pyvista <https://docs.pyvista.org/>`__
|
||||||
* `Read The Docs <https://docs.readthedocs.io/>`__
|
* `Read The Docs <https://docs.readthedocs.io/>`__
|
||||||
* `ROCm Platform <https://rocm-documentation.readthedocs.io/>`__
|
* `RenderDoc <https://renderdoc.org/docs/>`__
|
||||||
|
* `ROCm Platform <https://rocmdocs.amd.com/>`__
|
||||||
* `Free your information from their silos (French) <https://redaction-technique.org/>`__ (customized)
|
* `Free your information from their silos (French) <https://redaction-technique.org/>`__ (customized)
|
||||||
* `Releases Sphinx extension <https://releases.readthedocs.io/>`__
|
* `Releases Sphinx extension <https://releases.readthedocs.io/>`__
|
||||||
* `Qtile <https://docs.qtile.org/>`__
|
* `Qtile <https://docs.qtile.org/>`__
|
||||||
@ -269,6 +286,7 @@ Documentation using sphinx_rtd_theme
|
|||||||
* `Sonos Controller (SoCo) <https://docs.python-soco.com/>`__
|
* `Sonos Controller (SoCo) <https://docs.python-soco.com/>`__
|
||||||
* `Sphinx AutoAPI <https://sphinx-autoapi.readthedocs.io/>`__
|
* `Sphinx AutoAPI <https://sphinx-autoapi.readthedocs.io/>`__
|
||||||
* `sphinx-argparse <https://sphinx-argparse.readthedocs.io/>`__
|
* `sphinx-argparse <https://sphinx-argparse.readthedocs.io/>`__
|
||||||
|
* `sphinx-tabs <https://sphinx-tabs.readthedocs.io/>`__
|
||||||
* `Sphinx-Gallery <https://sphinx-gallery.readthedocs.io/>`__ (customized)
|
* `Sphinx-Gallery <https://sphinx-gallery.readthedocs.io/>`__ (customized)
|
||||||
* `Sphinx with Github Webpages <https://runawayhorse001.github.io/SphinxGithub>`__
|
* `Sphinx with Github Webpages <https://runawayhorse001.github.io/SphinxGithub>`__
|
||||||
* `SpotBugs <https://spotbugs.readthedocs.io/>`__
|
* `SpotBugs <https://spotbugs.readthedocs.io/>`__
|
||||||
@ -281,15 +299,18 @@ Documentation using sphinx_rtd_theme
|
|||||||
* `Topshelf <https://docs.topshelf-project.com/>`__
|
* `Topshelf <https://docs.topshelf-project.com/>`__
|
||||||
* `Theano <http://www.deeplearning.net/software/theano/>`__
|
* `Theano <http://www.deeplearning.net/software/theano/>`__
|
||||||
* `ThreatConnect <https://docs.threatconnect.com/>`__
|
* `ThreatConnect <https://docs.threatconnect.com/>`__
|
||||||
|
* `TrueNAS <https://www.ixsystems.com/documentation/truenas/>`__ (customized)
|
||||||
* `Tuleap <https://tuleap.net/doc/en/>`__
|
* `Tuleap <https://tuleap.net/doc/en/>`__
|
||||||
* `TYPO3 <https://docs.typo3.org/>`__ (customized)
|
* `TYPO3 <https://docs.typo3.org/>`__ (customized)
|
||||||
* `Veyon <https://docs.veyon.io/>`__
|
* `Veyon <https://docs.veyon.io/>`__
|
||||||
|
* `Ubiquity <https://micro-framework.readthedocs.io/>`__
|
||||||
* `uWSGI <https://uwsgi-docs.readthedocs.io/>`__
|
* `uWSGI <https://uwsgi-docs.readthedocs.io/>`__
|
||||||
* `virtualenv <https://virtualenv.readthedocs.io/>`__
|
* `virtualenv <https://virtualenv.readthedocs.io/>`__
|
||||||
* `Wagtail <https://docs.wagtail.io/>`__
|
* `Wagtail <https://docs.wagtail.io/>`__
|
||||||
* `Web Application Attack and Audit Framework (w3af) <https://docs.w3af.org/>`__
|
* `Web Application Attack and Audit Framework (w3af) <https://docs.w3af.org/>`__
|
||||||
* `Weblate <https://docs.weblate.org/>`__
|
* `Weblate <https://docs.weblate.org/>`__
|
||||||
* `x265 <https://x265.readthedocs.io/>`__
|
* `x265 <https://x265.readthedocs.io/>`__
|
||||||
|
* `Zeek <https://docs.zeek.org/>`__
|
||||||
* `Zulip <https://zulip.readthedocs.io/>`__
|
* `Zulip <https://zulip.readthedocs.io/>`__
|
||||||
|
|
||||||
Documentation using sphinx_bootstrap_theme
|
Documentation using sphinx_bootstrap_theme
|
||||||
@ -317,12 +338,12 @@ Documentation using a custom theme or integrated in a website
|
|||||||
* `Bokeh <https://bokeh.pydata.org/>`__
|
* `Bokeh <https://bokeh.pydata.org/>`__
|
||||||
* `Boto 3 <https://boto3.readthedocs.io/>`__
|
* `Boto 3 <https://boto3.readthedocs.io/>`__
|
||||||
* `CakePHP <https://book.cakephp.org/>`__
|
* `CakePHP <https://book.cakephp.org/>`__
|
||||||
* `CasperJS <http://docs.casperjs.org/>`__
|
|
||||||
* `Ceph <https://docs.ceph.com/docs/master/>`__
|
* `Ceph <https://docs.ceph.com/docs/master/>`__
|
||||||
* `Chef <https://docs.chef.io/>`__
|
* `Chef <https://docs.chef.io/>`__
|
||||||
* `CKAN <https://docs.ckan.org/>`__
|
* `CKAN <https://docs.ckan.org/>`__
|
||||||
* `Confluent Platform <https://docs.confluent.io/>`__
|
* `Confluent Platform <https://docs.confluent.io/>`__
|
||||||
* `Django <https://docs.djangoproject.com/>`__
|
* `Django <https://docs.djangoproject.com/>`__
|
||||||
|
* `django CMS <https://docs.django-cms.org/>`__
|
||||||
* `Doctrine <https://www.doctrine-project.org/>`__
|
* `Doctrine <https://www.doctrine-project.org/>`__
|
||||||
* `Enterprise Toolkit for Acrobat products <https://www.adobe.com/devnet-docs/acrobatetk/>`__
|
* `Enterprise Toolkit for Acrobat products <https://www.adobe.com/devnet-docs/acrobatetk/>`__
|
||||||
* `FreeFEM <https://doc.freefem.org/introduction/>`__
|
* `FreeFEM <https://doc.freefem.org/introduction/>`__
|
||||||
@ -335,7 +356,7 @@ Documentation using a custom theme or integrated in a website
|
|||||||
* `Guzzle <https://docs.guzzlephp.org/>`__
|
* `Guzzle <https://docs.guzzlephp.org/>`__
|
||||||
* `H2O.ai <https://docs.h2o.ai/>`__
|
* `H2O.ai <https://docs.h2o.ai/>`__
|
||||||
* `Heka <https://hekad.readthedocs.io/>`__
|
* `Heka <https://hekad.readthedocs.io/>`__
|
||||||
* `Istihza (Turkish Python documentation project) <https://belgeler.yazbel.com/python-istihza/>`__
|
* `Istihza (Turkish Python documentation project) <https://python-istihza.yazbel.com/>`__
|
||||||
* `JupyterHub <https://jupyterhub.readthedocs.io/>`__
|
* `JupyterHub <https://jupyterhub.readthedocs.io/>`__
|
||||||
* `Kombu <http://docs.kombu.me/>`__
|
* `Kombu <http://docs.kombu.me/>`__
|
||||||
* `Lasso <https://lassoguide.com/>`__
|
* `Lasso <https://lassoguide.com/>`__
|
||||||
@ -356,6 +377,7 @@ Documentation using a custom theme or integrated in a website
|
|||||||
* `OpenTURNS <https://openturns.github.io/openturns/master/>`__
|
* `OpenTURNS <https://openturns.github.io/openturns/master/>`__
|
||||||
* `Open vSwitch <https://docs.openvswitch.org/>`__
|
* `Open vSwitch <https://docs.openvswitch.org/>`__
|
||||||
* `PlatformIO <https://docs.platformio.org/>`__
|
* `PlatformIO <https://docs.platformio.org/>`__
|
||||||
|
* `Psycopg <https://www.psycopg.org/docs/>`__
|
||||||
* `PyEphem <https://rhodesmill.org/pyephem/>`__
|
* `PyEphem <https://rhodesmill.org/pyephem/>`__
|
||||||
* `Pygments <https://pygments.org/docs/>`__
|
* `Pygments <https://pygments.org/docs/>`__
|
||||||
* `Plone User Manual (German) <https://www.hasecke.com/plone-benutzerhandbuch/4.0/>`__
|
* `Plone User Manual (German) <https://www.hasecke.com/plone-benutzerhandbuch/4.0/>`__
|
||||||
@ -384,14 +406,16 @@ Documentation using a custom theme or integrated in a website
|
|||||||
Homepages and other non-documentation sites
|
Homepages and other non-documentation sites
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
||||||
|
* `Alan Crosswell's Using the Django REST Framework and DRF-JSONAPI <http://www.columbia.edu/~alan/django-jsonapi-training/>`__
|
||||||
* `Arizona State University PHY494/PHY598/CHM598 Simulation approaches to Bio-and Nanophysics <https://becksteinlab.physics.asu.edu/pages/courses/2013/SimBioNano/>`__ (classic)
|
* `Arizona State University PHY494/PHY598/CHM598 Simulation approaches to Bio-and Nanophysics <https://becksteinlab.physics.asu.edu/pages/courses/2013/SimBioNano/>`__ (classic)
|
||||||
* `Benoit Boissinot <https://bboissin.appspot.com/>`__ (classic, customized)
|
* `Benoit Boissinot <https://bboissin.appspot.com/>`__ (classic, customized)
|
||||||
* `Computer Networks, Parallelization, and Simulation Laboratory (CNPSLab) <https://lab.miletic.net/>`__ (sphinx_rtd_theme)
|
* `EBI Cloud Consultancy Team <https://tsi-ccdoc.readthedocs.io/>`__ (sphinx_rtd_theme)
|
||||||
* `Deep Learning Tutorials <http://www.deeplearning.net/tutorial/>`__ (sphinxdoc)
|
|
||||||
* `Eric Holscher <https://ericholscher.com/>`__ (alabaster)
|
* `Eric Holscher <https://ericholscher.com/>`__ (alabaster)
|
||||||
|
* `Florian Diesch <https://www.florian-diesch.de/>`__
|
||||||
|
* `Institute for the Design of Advanced Energy Systems (IDAES) <https://idaes-pse.readthedocs.io/>`__ (sphinx_rtd_theme)
|
||||||
|
* `IDAES Examples <https://idaes.github.io/examples-pse/>`__ (sphinx_rtd_theme)
|
||||||
* `Lei Ma's Statistical Mechanics lecture notes <http://statisticalphysics.openmetric.org/>`__ (sphinx_bootstrap_theme)
|
* `Lei Ma's Statistical Mechanics lecture notes <http://statisticalphysics.openmetric.org/>`__ (sphinx_bootstrap_theme)
|
||||||
* `Loyola University Chicago COMP 339-439 Distributed Systems course <https://books.cs.luc.edu/distributedsystems/>`__ (sphinx_bootstrap_theme)
|
* `Loyola University Chicago CS Academic Programs <https://academics.cs.luc.edu/index.html>`__ (sphinx_rtd_theme, customized)
|
||||||
* `Pylearn2 <http://www.deeplearning.net/software/pylearn2/>`__ (sphinxdoc, customized)
|
|
||||||
* `PyXLL <https://www.pyxll.com/>`__ (sphinx_bootstrap_theme, customized)
|
* `PyXLL <https://www.pyxll.com/>`__ (sphinx_bootstrap_theme, customized)
|
||||||
* `SciPy Cookbook <https://scipy-cookbook.readthedocs.io/>`__ (sphinx_rtd_theme)
|
* `SciPy Cookbook <https://scipy-cookbook.readthedocs.io/>`__ (sphinx_rtd_theme)
|
||||||
* `Tech writer at work blog <https://blog.documatt.com/>`__ (custom theme)
|
* `Tech writer at work blog <https://blog.documatt.com/>`__ (custom theme)
|
||||||
@ -444,6 +468,6 @@ Projects integrating Sphinx functionality
|
|||||||
* `Read the Docs <https://readthedocs.org/>`__, a software-as-a-service documentation hosting platform, uses
|
* `Read the Docs <https://readthedocs.org/>`__, a software-as-a-service documentation hosting platform, uses
|
||||||
Sphinx to automatically build documentation updates that are pushed to GitHub.
|
Sphinx to automatically build documentation updates that are pushed to GitHub.
|
||||||
|
|
||||||
* `Spyder <https://docs.spyder-ide.org/help.html>`__, the Scientific Python Development Environment, uses Sphinx in its
|
* `Spyder <https://docs.spyder-ide.org/current/panes/help.html>`__, the Scientific Python Development
|
||||||
help pane to render rich documentation for functions, classes and methods
|
Environment, uses Sphinx in its help pane to render rich documentation for functions, classes and methods
|
||||||
automatically or on-demand.
|
automatically or on-demand.
|
||||||
|
5
LICENSE
5
LICENSE
@ -1,7 +1,10 @@
|
|||||||
License for Sphinx
|
License for Sphinx
|
||||||
==================
|
==================
|
||||||
|
|
||||||
Copyright (c) 2007-2021 by the Sphinx team (see AUTHORS file).
|
Unless otherwise indicated, all code in the Sphinx project is licenced under the
|
||||||
|
two clause BSD licence below.
|
||||||
|
|
||||||
|
Copyright (c) 2007-2022 by the Sphinx team (see AUTHORS file).
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
4
doc/_static/conf.py.txt
vendored
4
doc/_static/conf.py.txt
vendored
@ -319,6 +319,10 @@ texinfo_documents = [
|
|||||||
#
|
#
|
||||||
# texinfo_no_detailmenu = False
|
# texinfo_no_detailmenu = False
|
||||||
|
|
||||||
|
# If false, do not generate in manual @ref nodes.
|
||||||
|
#
|
||||||
|
# texinfo_cross_references = False
|
||||||
|
|
||||||
# -- A random example -----------------------------------------------------
|
# -- A random example -----------------------------------------------------
|
||||||
|
|
||||||
import sys, os
|
import sys, os
|
||||||
|
4
doc/_templates/indexsidebar.html
vendored
4
doc/_templates/indexsidebar.html
vendored
@ -14,10 +14,10 @@
|
|||||||
<form action="https://groups.google.com/group/sphinx-users/boxsubscribe"
|
<form action="https://groups.google.com/group/sphinx-users/boxsubscribe"
|
||||||
class="subscribeform">
|
class="subscribeform">
|
||||||
<input type="text" name="email" value="your@email"
|
<input type="text" name="email" value="your@email"
|
||||||
onfocus="$(this).val('');" />
|
onfocus="this.value = ''" />
|
||||||
<input type="submit" name="sub" value="Subscribe" />
|
<input type="submit" name="sub" value="Subscribe" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<p>{%trans%}or come to the <tt>#sphinx-doc</tt> channel on FreeNode.{%endtrans%}</p>
|
<p>{%trans%}or come to the <tt>#sphinx-doc</tt> channel on <a href="https://web.libera.chat/?channel=#sphinx-doc">libera.chat</a>.{%endtrans%}</p>
|
||||||
<p>{%trans%}You can also open an issue at the
|
<p>{%trans%}You can also open an issue at the
|
||||||
<a href="https://github.com/sphinx-doc/sphinx/issues">tracker</a>.{%endtrans%}</p>
|
<a href="https://github.com/sphinx-doc/sphinx/issues">tracker</a>.{%endtrans%}</p>
|
||||||
|
29
doc/_themes/sphinx13/layout.html
vendored
29
doc/_themes/sphinx13/layout.html
vendored
@ -27,31 +27,28 @@
|
|||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
// intelligent scrolling of the sidebar content
|
// intelligent scrolling of the sidebar content
|
||||||
$(window).scroll(function() {
|
window.onscroll = () => {
|
||||||
var sb = $('.sphinxsidebarwrapper');
|
const sb = document.getElementsByClassName('sphinxsidebarwrapper')[0]
|
||||||
var win = $(window);
|
const sbh = sb.offsetHeight
|
||||||
var sbh = sb.height();
|
const offset = document.getElementsByClassName('sphinxsidebar')[0].offsetTop;
|
||||||
var offset = $('.sphinxsidebar').position()['top'];
|
const wintop = window.scrollTop;
|
||||||
var wintop = win.scrollTop();
|
const winbot = wintop + window.offsetHeight
|
||||||
var winbot = wintop + win.innerHeight();
|
const curtop = sb.offsetTop;
|
||||||
var curtop = sb.position()['top'];
|
const curbot = curtop + sbh;
|
||||||
var curbot = curtop + sbh;
|
|
||||||
// does sidebar fit in window?
|
// does sidebar fit in window?
|
||||||
if (sbh < win.innerHeight()) {
|
if (sbh < window.offsetHeight) {
|
||||||
// yes: easy case -- always keep at the top
|
// yes: easy case -- always keep at the top
|
||||||
sb.css('top', $u.min([$u.max([0, wintop - offset - 10]),
|
sb.style.top = Math.min(Math.max(0, wintop - offset - 10), window.innerHeight - sbh - 200)
|
||||||
$(document).height() - sbh - 200]));
|
|
||||||
} else {
|
} else {
|
||||||
// no: only scroll if top/bottom edge of sidebar is at
|
// no: only scroll if top/bottom edge of sidebar is at
|
||||||
// top/bottom edge of window
|
// top/bottom edge of window
|
||||||
if (curtop > wintop && curbot > winbot) {
|
if (curtop > wintop && curbot > winbot) {
|
||||||
sb.css('top', $u.max([wintop - offset - 10, 0]));
|
sb.style.top = Math.max(wintop - offset - 10, 0)
|
||||||
} else if (curtop < wintop && curbot < winbot) {
|
} else if (curtop < wintop && curbot < winbot) {
|
||||||
sb.css('top', $u.min([winbot - sbh - offset - 20,
|
sb.style.top = Math.min(winbot - sbh - offset - 20, window.innerHeight - sbh - 200)
|
||||||
$(document).height() - sbh - 200]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
</script>
|
</script>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
2
doc/_themes/sphinx13/theme.conf
vendored
2
doc/_themes/sphinx13/theme.conf
vendored
@ -1,4 +1,4 @@
|
|||||||
[theme]
|
[theme]
|
||||||
inherit = basic
|
inherit = basic
|
||||||
stylesheet = sphinx13.css
|
stylesheet = sphinx13.css
|
||||||
pygments_style = trac
|
pygments_style = default
|
||||||
|
35
doc/conf.py
35
doc/conf.py
@ -1,5 +1,6 @@
|
|||||||
# Sphinx documentation build configuration file
|
# Sphinx documentation build configuration file
|
||||||
|
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import sphinx
|
import sphinx
|
||||||
@ -14,7 +15,7 @@ templates_path = ['_templates']
|
|||||||
exclude_patterns = ['_build']
|
exclude_patterns = ['_build']
|
||||||
|
|
||||||
project = 'Sphinx'
|
project = 'Sphinx'
|
||||||
copyright = '2007-2021, Georg Brandl and the Sphinx team'
|
copyright = '2007-2022, Georg Brandl and the Sphinx team'
|
||||||
version = sphinx.__display_version__
|
version = sphinx.__display_version__
|
||||||
release = version
|
release = version
|
||||||
show_authors = True
|
show_authors = True
|
||||||
@ -81,11 +82,11 @@ autodoc_member_order = 'groupwise'
|
|||||||
autosummary_generate = False
|
autosummary_generate = False
|
||||||
todo_include_todos = True
|
todo_include_todos = True
|
||||||
extlinks = {'duref': ('https://docutils.sourceforge.io/docs/ref/rst/'
|
extlinks = {'duref': ('https://docutils.sourceforge.io/docs/ref/rst/'
|
||||||
'restructuredtext.html#%s', ''),
|
'restructuredtext.html#%s', '%s'),
|
||||||
'durole': ('https://docutils.sourceforge.io/docs/ref/rst/'
|
'durole': ('https://docutils.sourceforge.io/docs/ref/rst/'
|
||||||
'roles.html#%s', ''),
|
'roles.html#%s', '%s'),
|
||||||
'dudir': ('https://docutils.sourceforge.io/docs/ref/rst/'
|
'dudir': ('https://docutils.sourceforge.io/docs/ref/rst/'
|
||||||
'directives.html#%s', '')}
|
'directives.html#%s', '%s')}
|
||||||
|
|
||||||
man_pages = [
|
man_pages = [
|
||||||
('contents', 'sphinx-all', 'Sphinx documentation generator system manual',
|
('contents', 'sphinx-all', 'Sphinx documentation generator system manual',
|
||||||
@ -108,7 +109,8 @@ texinfo_documents = [
|
|||||||
|
|
||||||
intersphinx_mapping = {
|
intersphinx_mapping = {
|
||||||
'python': ('https://docs.python.org/3/', None),
|
'python': ('https://docs.python.org/3/', None),
|
||||||
'requests': ('https://requests.readthedocs.io/en/master', None),
|
'requests': ('https://docs.python-requests.org/en/latest/', None),
|
||||||
|
'readthedocs': ('https://docs.readthedocs.io/en/stable', None),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Sphinx document translation with sphinx gettext feature uses these settings:
|
# Sphinx document translation with sphinx gettext feature uses these settings:
|
||||||
@ -138,10 +140,33 @@ def parse_event(env, sig, signode):
|
|||||||
return name
|
return name
|
||||||
|
|
||||||
|
|
||||||
|
def linkify_issues_in_changelog(app, docname, source):
|
||||||
|
""" Linkify issue references like #123 in changelog to GitHub. """
|
||||||
|
|
||||||
|
if docname == 'changes':
|
||||||
|
changelog_path = os.path.join(os.path.dirname(__file__), "../CHANGES")
|
||||||
|
# this path trickery is needed because this script can
|
||||||
|
# be invoked with different working directories:
|
||||||
|
# * running make in docs/
|
||||||
|
# * running python setup.py build_sphinx in the repo root dir
|
||||||
|
|
||||||
|
with open(changelog_path) as f:
|
||||||
|
changelog = f.read()
|
||||||
|
|
||||||
|
def linkify(match):
|
||||||
|
url = 'https://github.com/sphinx-doc/sphinx/issues/' + match[1]
|
||||||
|
return '`{} <{}>`_'.format(match[0], url)
|
||||||
|
|
||||||
|
linkified_changelog = re.sub(r'(?:PR)?#([0-9]+)\b', linkify, changelog)
|
||||||
|
|
||||||
|
source[0] = source[0].replace('.. include:: ../CHANGES', linkified_changelog)
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
from sphinx.ext.autodoc import cut_lines
|
from sphinx.ext.autodoc import cut_lines
|
||||||
from sphinx.util.docfields import GroupedField
|
from sphinx.util.docfields import GroupedField
|
||||||
app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
|
app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
|
||||||
|
app.connect('source-read', linkify_issues_in_changelog)
|
||||||
app.add_object_type('confval', 'confval',
|
app.add_object_type('confval', 'confval',
|
||||||
objname='configuration value',
|
objname='configuration value',
|
||||||
indextemplate='pair: %s; configuration value')
|
indextemplate='pair: %s; configuration value')
|
||||||
|
@ -88,8 +88,8 @@ Python :mod:`ConfigParser` module) and has the following structure:
|
|||||||
Distribute your theme as a Python package
|
Distribute your theme as a Python package
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
As a way to distribute your theme, you can use Python package. Python package
|
As a way to distribute your theme, you can use a Python package. This makes it
|
||||||
brings to users easy setting up ways.
|
easier for users to set up your theme.
|
||||||
|
|
||||||
To distribute your theme as a Python package, please define an entry point
|
To distribute your theme as a Python package, please define an entry point
|
||||||
called ``sphinx.html_themes`` in your ``setup.py`` file, and write a ``setup()``
|
called ``sphinx.html_themes`` in your ``setup.py`` file, and write a ``setup()``
|
||||||
@ -285,7 +285,7 @@ engine, allowing you to embed variables and control behavior.
|
|||||||
|
|
||||||
For example, the following JavaScript structure:
|
For example, the following JavaScript structure:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: none
|
||||||
|
|
||||||
mymodule/
|
mymodule/
|
||||||
├── _static
|
├── _static
|
||||||
@ -294,7 +294,7 @@ For example, the following JavaScript structure:
|
|||||||
|
|
||||||
Will result in the following static file placed in your HTML's build output:
|
Will result in the following static file placed in your HTML's build output:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: none
|
||||||
|
|
||||||
_build/
|
_build/
|
||||||
└── html
|
└── html
|
||||||
|
@ -9,7 +9,7 @@ from sphinx.ext.autodoc import ClassDocumenter, bool_option
|
|||||||
|
|
||||||
class IntEnumDocumenter(ClassDocumenter):
|
class IntEnumDocumenter(ClassDocumenter):
|
||||||
objtype = 'intenum'
|
objtype = 'intenum'
|
||||||
directivetype = 'class'
|
directivetype = ClassDocumenter.objtype
|
||||||
priority = 10 + ClassDocumenter.priority
|
priority = 10 + ClassDocumenter.priority
|
||||||
option_spec = dict(ClassDocumenter.option_spec)
|
option_spec = dict(ClassDocumenter.option_spec)
|
||||||
option_spec['hex'] = bool_option
|
option_spec['hex'] = bool_option
|
||||||
@ -18,7 +18,10 @@ class IntEnumDocumenter(ClassDocumenter):
|
|||||||
def can_document_member(cls,
|
def can_document_member(cls,
|
||||||
member: Any, membername: str,
|
member: Any, membername: str,
|
||||||
isattr: bool, parent: Any) -> bool:
|
isattr: bool, parent: Any) -> bool:
|
||||||
return isinstance(member, IntEnum)
|
try:
|
||||||
|
return issubclass(member, IntEnum)
|
||||||
|
except TypeError:
|
||||||
|
return False
|
||||||
|
|
||||||
def add_directive_header(self, sig: str) -> None:
|
def add_directive_header(self, sig: str) -> None:
|
||||||
super().add_directive_header(sig)
|
super().add_directive_header(sig)
|
||||||
@ -36,14 +39,13 @@ class IntEnumDocumenter(ClassDocumenter):
|
|||||||
use_hex = self.options.hex
|
use_hex = self.options.hex
|
||||||
self.add_line('', source_name)
|
self.add_line('', source_name)
|
||||||
|
|
||||||
for enum_value in enum_object:
|
for the_member_name, enum_member in enum_object.__members__.items():
|
||||||
the_value_name = enum_value.name
|
the_member_value = enum_member.value
|
||||||
the_value_value = enum_value.value
|
|
||||||
if use_hex:
|
if use_hex:
|
||||||
the_value_value = hex(the_value_value)
|
the_member_value = hex(the_member_value)
|
||||||
|
|
||||||
self.add_line(
|
self.add_line(
|
||||||
f"**{the_value_name}**: {the_value_value}", source_name)
|
f"**{the_member_name}**: {the_member_value}", source_name)
|
||||||
self.add_line('', source_name)
|
self.add_line('', source_name)
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ class RecipeIndex(Index):
|
|||||||
# first letter of the recipe as a key to group thing
|
# first letter of the recipe as a key to group thing
|
||||||
#
|
#
|
||||||
# name, subtype, docname, anchor, extra, qualifier, description
|
# name, subtype, docname, anchor, extra, qualifier, description
|
||||||
for name, dispname, typ, docname, anchor, _ in recipes:
|
for _name, dispname, typ, docname, anchor, _priority in recipes:
|
||||||
content[dispname[0].lower()].append(
|
content[dispname[0].lower()].append(
|
||||||
(dispname, 0, docname, anchor, docname, '', typ))
|
(dispname, 0, docname, anchor, docname, '', typ))
|
||||||
|
|
||||||
|
@ -298,7 +298,9 @@ Here is a more detailed list of these events.
|
|||||||
|
|
||||||
Emitted when a cross-reference to an object cannot be resolved even after
|
Emitted when a cross-reference to an object cannot be resolved even after
|
||||||
:event:`missing-reference`. If the event handler can emit warnings for
|
:event:`missing-reference`. If the event handler can emit warnings for
|
||||||
the missing reference, it should return ``True``.
|
the missing reference, it should return ``True``. The configuration variables
|
||||||
|
:confval:`nitpick_ignore` and :confval:`nitpick_ignore_regex` prevent the
|
||||||
|
event from being emitted for the corresponding nodes.
|
||||||
|
|
||||||
.. versionadded:: 3.4
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
|
@ -22,6 +22,31 @@ The following is a list of deprecated interfaces.
|
|||||||
- (will be) Removed
|
- (will be) Removed
|
||||||
- Alternatives
|
- Alternatives
|
||||||
|
|
||||||
|
* - :doc:`Setuptools integration </usage/advanced/setuptools>`
|
||||||
|
- 5.0
|
||||||
|
- 7.0
|
||||||
|
- N/A
|
||||||
|
|
||||||
|
* - The ``locale`` argument of ``sphinx.util.i18n:babel_format_date()``
|
||||||
|
- 5.0
|
||||||
|
- 7.0
|
||||||
|
- N/A
|
||||||
|
|
||||||
|
* - The ``language`` argument of ``sphinx.util.i18n:format_date()``
|
||||||
|
- 5.0
|
||||||
|
- 7.0
|
||||||
|
- N/A
|
||||||
|
|
||||||
|
* - ``sphinx.writers.latex.LaTeXWriter.docclasses``
|
||||||
|
- 5.0
|
||||||
|
- 7.0
|
||||||
|
- N/A
|
||||||
|
|
||||||
|
* - ``sphinx.ext.napoleon.docstring.GoogleDocstring._qualify_name()``
|
||||||
|
- 4.5
|
||||||
|
- 6.0
|
||||||
|
- N/A
|
||||||
|
|
||||||
* - ``sphinx.ext.autodoc.AttributeDocumenter._datadescriptor``
|
* - ``sphinx.ext.autodoc.AttributeDocumenter._datadescriptor``
|
||||||
- 4.3
|
- 4.3
|
||||||
- 6.0
|
- 6.0
|
||||||
|
@ -35,3 +35,4 @@ to configure their settings appropriately.
|
|||||||
.. module:: sphinx.parsers
|
.. module:: sphinx.parsers
|
||||||
|
|
||||||
.. autoclass:: Parser
|
.. autoclass:: Parser
|
||||||
|
:members:
|
||||||
|
20
doc/faq.rst
20
doc/faq.rst
@ -299,6 +299,10 @@ appear in the source. Emacs, on the other-hand, will by default replace
|
|||||||
|
|
||||||
:ref:`texinfo-links`
|
:ref:`texinfo-links`
|
||||||
|
|
||||||
|
One can disable generation of the inline references in a document
|
||||||
|
with :confval:`texinfo_cross_references`. That makes
|
||||||
|
an info file more readable with stand-alone reader (``info``).
|
||||||
|
|
||||||
The exact behavior of how Emacs displays references is dependent on the variable
|
The exact behavior of how Emacs displays references is dependent on the variable
|
||||||
``Info-hide-note-references``. If set to the value of ``hide``, Emacs will hide
|
``Info-hide-note-references``. If set to the value of ``hide``, Emacs will hide
|
||||||
both the ``*note:`` part and the ``target-id``. This is generally the best way
|
both the ``*note:`` part and the ``target-id``. This is generally the best way
|
||||||
@ -346,19 +350,3 @@ The following notes may be helpful if you want to create Texinfo files:
|
|||||||
scheme ``info``. For example::
|
scheme ``info``. For example::
|
||||||
|
|
||||||
info:Texinfo#makeinfo_options
|
info:Texinfo#makeinfo_options
|
||||||
|
|
||||||
- Inline markup
|
|
||||||
|
|
||||||
The standard formatting for ``*strong*`` and ``_emphasis_`` can
|
|
||||||
result in ambiguous output when used to markup parameter names and
|
|
||||||
other values. Since this is a fairly common practice, the default
|
|
||||||
formatting has been changed so that ``emphasis`` and ``strong`` are
|
|
||||||
now displayed like ```literal'``\s.
|
|
||||||
|
|
||||||
The standard formatting can be re-enabled by adding the following to
|
|
||||||
your :file:`conf.py`::
|
|
||||||
|
|
||||||
texinfo_elements = {'preamble': """
|
|
||||||
@definfoenclose strong,*,*
|
|
||||||
@definfoenclose emph,_,_
|
|
||||||
"""}
|
|
||||||
|
@ -21,7 +21,7 @@ sphinx-users <sphinx-users@googlegroups.com>
|
|||||||
sphinx-dev <sphinx-dev@googlegroups.com>
|
sphinx-dev <sphinx-dev@googlegroups.com>
|
||||||
Mailing list for development related discussions.
|
Mailing list for development related discussions.
|
||||||
|
|
||||||
#sphinx-doc on irc.freenode.net
|
#sphinx-doc on irc.libera.chat
|
||||||
IRC channel for development questions and user support.
|
IRC channel for development questions and user support.
|
||||||
|
|
||||||
.. _python-sphinx: https://stackoverflow.com/questions/tagged/python-sphinx
|
.. _python-sphinx: https://stackoverflow.com/questions/tagged/python-sphinx
|
||||||
|
@ -100,6 +100,27 @@ But you can also explicitly enable the pending ones using e.g.
|
|||||||
``PYTHONWARNINGS=default`` (see the :ref:`Python docs on configuring warnings
|
``PYTHONWARNINGS=default`` (see the :ref:`Python docs on configuring warnings
|
||||||
<python:describing-warning-filters>`) for more details.
|
<python:describing-warning-filters>`) for more details.
|
||||||
|
|
||||||
|
Python version support policy
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
The minimum Python version Sphinx supports is the default Python version
|
||||||
|
installed in the oldest `Long Term Support version of
|
||||||
|
Ubuntu <https://ubuntu.com/about/release-cycle>`_ that has standard support.
|
||||||
|
For example, as of July 2021, Ubuntu 16.04 has just entered extended
|
||||||
|
security maintenance (therefore, it doesn't count as standard support) and
|
||||||
|
the oldest LTS release to consider is Ubuntu 18.04 LTS, supported until
|
||||||
|
April 2023 and shipping Python 3.6.
|
||||||
|
|
||||||
|
This is a summary table with the current policy:
|
||||||
|
|
||||||
|
========== ========= ======
|
||||||
|
Date Ubuntu Python
|
||||||
|
========== ========= ======
|
||||||
|
April 2021 18.04 LTS 3.6+
|
||||||
|
---------- --------- ------
|
||||||
|
April 2023 20.04 LTS 3.8+
|
||||||
|
========== ========= ======
|
||||||
|
|
||||||
Release procedures
|
Release procedures
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ and assuming ``docs/index.rst`` contained the following:
|
|||||||
|
|
||||||
If you run the following:
|
If you run the following:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: console
|
||||||
|
|
||||||
$ PYTHONPATH=. sphinx-autogen docs/index.rst
|
$ PYTHONPATH=. sphinx-autogen docs/index.rst
|
||||||
|
|
||||||
|
@ -304,6 +304,22 @@ variables to customize behavior:
|
|||||||
Additional options for :program:`sphinx-build`. These options can
|
Additional options for :program:`sphinx-build`. These options can
|
||||||
also be set via the shortcut variable **O** (capital 'o').
|
also be set via the shortcut variable **O** (capital 'o').
|
||||||
|
|
||||||
|
.. describe:: NO_COLOR
|
||||||
|
|
||||||
|
When set (regardless of value), :program:`sphinx-build` will not use color
|
||||||
|
in terminal output. ``NO_COLOR`` takes precedence over ``FORCE_COLOR``. See
|
||||||
|
`no-color.org <https://no-color.org/>`__ for other libraries supporting this
|
||||||
|
community standard.
|
||||||
|
|
||||||
|
.. versionadded:: 4.5.0
|
||||||
|
|
||||||
|
.. describe:: FORCE_COLOR
|
||||||
|
|
||||||
|
When set (regardless of value), :program:`sphinx-build` will use color in
|
||||||
|
terminal output. ``NO_COLOR`` takes precedence over ``FORCE_COLOR``.
|
||||||
|
|
||||||
|
.. versionadded:: 4.5.0
|
||||||
|
|
||||||
.. _when-deprecation-warnings-are-displayed:
|
.. _when-deprecation-warnings-are-displayed:
|
||||||
|
|
||||||
Deprecation Warnings
|
Deprecation Warnings
|
||||||
|
@ -4,10 +4,9 @@ Automatic documentation generation from code
|
|||||||
In the :ref:`previous section <tutorial-describing-objects>` of the tutorial
|
In the :ref:`previous section <tutorial-describing-objects>` of the tutorial
|
||||||
you manually documented a Python function in Sphinx. However, the description
|
you manually documented a Python function in Sphinx. However, the description
|
||||||
was out of sync with the code itself, since the function signature was not
|
was out of sync with the code itself, since the function signature was not
|
||||||
the same. Besides, it would be nice to reuse `Python
|
the same. Besides, it would be nice to reuse :pep:`Python docstrings
|
||||||
docstrings <https://www.python.org/dev/peps/pep-0257/#what-is-a-docstring>`_
|
<257#what-is-a-docstring>` in the documentation, rather than having to write
|
||||||
in the documentation, rather than having to write the information in two
|
the information in two places.
|
||||||
places.
|
|
||||||
|
|
||||||
Fortunately, :doc:`the autodoc extension </usage/extensions/autodoc>` provides this
|
Fortunately, :doc:`the autodoc extension </usage/extensions/autodoc>` provides this
|
||||||
functionality.
|
functionality.
|
||||||
|
279
doc/tutorial/deploying.rst
Normal file
279
doc/tutorial/deploying.rst
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
Appendix: Deploying a Sphinx project online
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
When you are ready to show your documentation project to the world, there are
|
||||||
|
many options available to do so. Since the HTML generated by Sphinx is static,
|
||||||
|
you can decouple the process of building your HTML documentation from hosting
|
||||||
|
such files in the platform of your choice. You will not need a sophisticated
|
||||||
|
server running Python: virtually every web hosting service will suffice.
|
||||||
|
|
||||||
|
Therefore, the challenge is less how or where to serve the static HTML, but
|
||||||
|
rather how to pick a workflow that automatically updates the deployed
|
||||||
|
documentation every time there is a change in the source files.
|
||||||
|
|
||||||
|
The following sections describe some of the available options to deploy
|
||||||
|
your online documentation, and give some background information. If you want
|
||||||
|
to go directly to the practical part, you can skip to :ref:`publishing-sources`.
|
||||||
|
|
||||||
|
Sphinx-friendly deployment options
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
There are several possible options you have to host your Sphinx documentation.
|
||||||
|
Some of them are:
|
||||||
|
|
||||||
|
**Read the Docs**
|
||||||
|
`Read the Docs`_ is an online service specialized in hosting technical
|
||||||
|
documentation written in Sphinx, as well as MkDocs. They have a
|
||||||
|
number of extra features, such as versioned documentation, traffic and
|
||||||
|
search analytics, custom domains, user-defined redirects, and more.
|
||||||
|
|
||||||
|
**GitHub Pages**
|
||||||
|
`GitHub Pages`_ is a simple static web hosting tightly integrated with
|
||||||
|
`GitHub`_: static HTML is served from one of the branches of a project,
|
||||||
|
and usually sources are stored in another branch so that the output
|
||||||
|
can be updated every time the sources change (for example using `GitHub
|
||||||
|
Actions`_). It is free to use and supports custom domains.
|
||||||
|
|
||||||
|
**GitLab Pages**
|
||||||
|
`GitLab Pages`_ is a similar concept to GitHub Pages, integrated with
|
||||||
|
`GitLab`_ and usually automated with `GitLab CI`_ instead.
|
||||||
|
|
||||||
|
**Netlify**
|
||||||
|
`Netlify`_ is a sophisticated hosting for static sites enhanced by
|
||||||
|
client-side web technologies like JavaScript (so-called `"Jamstack"`_).
|
||||||
|
They offer support for headless content management systems and
|
||||||
|
serverless computing.
|
||||||
|
|
||||||
|
**Your own server**
|
||||||
|
You can always use your own web server to host Sphinx HTML documentation.
|
||||||
|
It is the option that gives more flexibility, but also more complexity.
|
||||||
|
|
||||||
|
All these options have zero cost, with the option of paying for extra features.
|
||||||
|
|
||||||
|
.. _Read the Docs: https://readthedocs.org/
|
||||||
|
.. _GitHub Pages: https://pages.github.com/
|
||||||
|
.. _GitHub: https://github.com/
|
||||||
|
.. _GitHub Actions: https://github.com/features/actions
|
||||||
|
.. _GitLab Pages: https://about.gitlab.com/stages-devops-lifecycle/pages/
|
||||||
|
.. _GitLab: https://gitlab.com/
|
||||||
|
.. _GitLab CI: https://about.gitlab.com/stages-devops-lifecycle/continuous-integration/
|
||||||
|
.. _Netlify: https://www.netlify.com/
|
||||||
|
.. _"Jamstack": https://jamstack.org/
|
||||||
|
|
||||||
|
Embracing the "Docs as Code" philosophy
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
The free offerings of most of the options listed above require your
|
||||||
|
documentation sources to be publicly available. Moreover, these services
|
||||||
|
expect you to use a `Version Control System`_, a technology that tracks the
|
||||||
|
evolution of a collection of files as a series of snapshots ("commits").
|
||||||
|
The practice of writing documentation in plain text files with the same tools
|
||||||
|
as the ones used for software development is commonly known as `"Docs as Code"`_.
|
||||||
|
|
||||||
|
The most popular Version Control System nowadays is Git_, a free and open
|
||||||
|
source tool that is the backbone of services like GitHub and GitLab.
|
||||||
|
Since both Read the Docs and Netlify have integrations with GitHub and GitLab,
|
||||||
|
and both GitHub and GitLab have an integrated Pages product, the most effective
|
||||||
|
way of automatically build your documentation online is to upload your sources
|
||||||
|
to either of these Git hosting services.
|
||||||
|
|
||||||
|
.. _Version Control System: https://en.wikipedia.org/wiki/Version_control
|
||||||
|
.. _"Docs as Code": https://www.writethedocs.org/guide/docs-as-code/
|
||||||
|
.. _Git: https://git-scm.com/
|
||||||
|
|
||||||
|
.. _publishing-sources:
|
||||||
|
|
||||||
|
Publishing your documentation sources
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
GitHub
|
||||||
|
~~~~~~
|
||||||
|
|
||||||
|
The quickest way to upload an existing project to GitHub is to:
|
||||||
|
|
||||||
|
1. `Sign up for a GitHub account <https://github.com/signup>`_.
|
||||||
|
2. `Create a new repository <https://github.com/new>`_.
|
||||||
|
3. Open `the "Upload files" page`_ of your new repository.
|
||||||
|
4. Select the files on your operating system file browser (in your case
|
||||||
|
``README.rst``, ``lumache.py``, the makefiles under the ``docs`` directory,
|
||||||
|
and everything under ``docs/source``) and drag them to the GitHub interface
|
||||||
|
to upload them all.
|
||||||
|
5. Click on the :guilabel:`Commit changes` button.
|
||||||
|
|
||||||
|
.. _the "Upload files" page: https://docs.github.com/en/repositories/working-with-files/managing-files/adding-a-file-to-a-repository
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Make sure you don't upload the ``docs/build`` directory, as it contains the
|
||||||
|
output generated by Sphinx and it will change every time you change the
|
||||||
|
sources, complicating your workflow.
|
||||||
|
|
||||||
|
These steps do not require access to the command line or installing any
|
||||||
|
additional software. To learn more, you can:
|
||||||
|
|
||||||
|
- Follow `this interactive GitHub course`_ to learn more about how the GitHub
|
||||||
|
interface works.
|
||||||
|
- Read `this quickstart tutorial`_ to install extra software on your machine
|
||||||
|
and have more flexibility. You can either use the Git command line, or the
|
||||||
|
GitHub Desktop application.
|
||||||
|
|
||||||
|
.. _this interactive GitHub course: https://lab.github.com/githubtraining/introduction-to-github
|
||||||
|
.. _this quickstart tutorial: https://docs.github.com/en/get-started/quickstart
|
||||||
|
|
||||||
|
GitLab
|
||||||
|
~~~~~~
|
||||||
|
|
||||||
|
Similarly to GitHub, the fastest way to upload your project to GitLab is
|
||||||
|
using the web interface:
|
||||||
|
|
||||||
|
1. `Sign up for a GitLab account <https://gitlab.com/users/sign_up>`_.
|
||||||
|
2. `Create a new blank project <https://gitlab.com/projects/new>`_.
|
||||||
|
3. Upload the project files (in your case ``README.rst``, ``lumache.py``, the
|
||||||
|
makefiles under the ``docs`` directory, and everything under
|
||||||
|
``docs/source``) one by one using the :guilabel:`Upload File` button [#f1]_.
|
||||||
|
|
||||||
|
Again, these steps do not require additional software on your computer. To
|
||||||
|
learn more, you can:
|
||||||
|
|
||||||
|
- Follow `this tutorial`_ to install Git on your machine.
|
||||||
|
- Browse the `GitLab User documentation`_ to understand the possibilities of
|
||||||
|
the platform.
|
||||||
|
|
||||||
|
.. _this tutorial: https://docs.gitlab.com/ee/gitlab-basics/start-using-git.html
|
||||||
|
.. _GitLab User documentation: https://docs.gitlab.com/ee/user/index.html
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Make sure you don't upload the ``docs/build`` directory, as it contains the
|
||||||
|
output generated by Sphinx and it will change every time you change the
|
||||||
|
sources, complicating your workflow.
|
||||||
|
|
||||||
|
.. [#f1] At the time of writing, `uploading whole directories to GitLab using
|
||||||
|
only the web
|
||||||
|
interface <https://gitlab.com/gitlab-org/gitlab/-/issues/228490>`_ is
|
||||||
|
not yet implemented.
|
||||||
|
|
||||||
|
Publishing your HTML documentation
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
Read the Docs
|
||||||
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
`Read the Docs`_ offers integration with both GitHub and GitLab. The quickest
|
||||||
|
way of getting started is to follow :doc:`the RTD
|
||||||
|
tutorial <readthedocs:tutorial/index>`, which is loosely based on this one.
|
||||||
|
You can publish your sources on GitHub as explained :ref:`in the previous
|
||||||
|
section <publishing-sources>`, then skip directly to
|
||||||
|
:ref:`readthedocs:tutorial/index:Sign up for Read the Docs`.
|
||||||
|
If you choose GitLab instead, the process is similar.
|
||||||
|
|
||||||
|
GitHub Pages
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
`GitHub Pages`_ requires you to :ref:`publish your
|
||||||
|
sources <publishing-sources>` on `GitHub`_. After that, you will need an
|
||||||
|
automated process that performs the ``make html`` step every time the sources
|
||||||
|
change. That can be achieved using `GitHub Actions`_.
|
||||||
|
|
||||||
|
After you have published your sources on GitHub, create a file named
|
||||||
|
``.github/workflows/sphinx.yml`` in your repository with the following
|
||||||
|
contents:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
:caption: .github/workflows/
|
||||||
|
|
||||||
|
name: Sphinx build
|
||||||
|
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Build HTML
|
||||||
|
uses: ammaraskar/sphinx-action@0.4
|
||||||
|
- name: Upload artifacts
|
||||||
|
uses: actions/upload-artifact@v1
|
||||||
|
with:
|
||||||
|
name: html-docs
|
||||||
|
path: docs/build/html/
|
||||||
|
- name: Deploy
|
||||||
|
uses: peaceiris/actions-gh-pages@v3
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
publish_dir: docs/build/html
|
||||||
|
|
||||||
|
This contains a GitHub Actions workflow with a single job of four steps:
|
||||||
|
|
||||||
|
1. Checkout the code.
|
||||||
|
2. Build the HTML documentation using Sphinx.
|
||||||
|
3. Attach the HTML output the artifacts to the GitHub Actions job, for easier
|
||||||
|
inspection.
|
||||||
|
4. If the change happens on the default branch, take the contents of
|
||||||
|
``docs/build/html`` and push it to the ``gh-pages`` branch.
|
||||||
|
|
||||||
|
Next, you need to specify the dependencies for the ``make html`` step to be
|
||||||
|
successful. For that, create a file ``docs/requirements.txt`` and add the
|
||||||
|
following contents:
|
||||||
|
|
||||||
|
.. code-block::
|
||||||
|
:caption: docs/requirements.txt
|
||||||
|
|
||||||
|
furo==2021.11.16
|
||||||
|
|
||||||
|
And finally, you are ready to `enable GitHub Pages on your repository`_. For
|
||||||
|
that, go to :guilabel:`Settings`, then :guilabel:`Pages` on the left sidebar,
|
||||||
|
select the ``gh-pages`` branch in the "Source" dropdown menu, and click
|
||||||
|
:guilabel:`Save`. After a few minutes, you should be able to see your HTML at
|
||||||
|
the designated URL.
|
||||||
|
|
||||||
|
.. _enable GitHub Pages on your repository: https://docs.github.com/en/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site
|
||||||
|
|
||||||
|
GitLab Pages
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
|
||||||
|
`GitLab Pages`_, on the other hand, requires you to :ref:`publish your
|
||||||
|
sources <publishing-sources>` on `GitLab`_. When you are ready, you can
|
||||||
|
automate the process of running ``make html`` using `GitLab CI`_.
|
||||||
|
|
||||||
|
After you have published your sources on GitLab, create a file named
|
||||||
|
``.gitlab-ci.yml`` in your repository with these contents:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
:caption: .gitlab-ci.yml
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- deploy
|
||||||
|
|
||||||
|
pages:
|
||||||
|
stage: deploy
|
||||||
|
image: python:3.9-slim
|
||||||
|
before_script:
|
||||||
|
- apt-get update && apt-get install make --no-install-recommends -y
|
||||||
|
- python -m pip install sphinx furo
|
||||||
|
script:
|
||||||
|
- cd docs && make html
|
||||||
|
after_script:
|
||||||
|
- mv docs/build/html/ ./public/
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- public
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
|
||||||
|
|
||||||
|
This contains a GitLab CI workflow with one job of several steps:
|
||||||
|
|
||||||
|
1. Install the necessary dependencies.
|
||||||
|
2. Build the HTML documentation using Sphinx.
|
||||||
|
3. Move the output to a known artifacts location.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
You will need to `validate your account`_ by entering a payment method
|
||||||
|
(you will be charged a small amount that will then be reimbursed).
|
||||||
|
|
||||||
|
.. _validate your account: https://about.gitlab.com/blog/2021/05/17/prevent-crypto-mining-abuse/#validating-an-account
|
||||||
|
|
||||||
|
After that, if the pipeline is successful, you should be able to see your HTML
|
||||||
|
at the designated URL.
|
@ -57,7 +57,7 @@ Notice several things:
|
|||||||
- Sphinx parsed the argument of the ``.. py:function`` directive and
|
- Sphinx parsed the argument of the ``.. py:function`` directive and
|
||||||
highlighted the module, the function name, and the parameters appropriately.
|
highlighted the module, the function name, and the parameters appropriately.
|
||||||
- The directive content includes a one-line description of the function,
|
- The directive content includes a one-line description of the function,
|
||||||
as well as a :ref:`info field list <info-field-lists>` containing the function
|
as well as an :ref:`info field list <info-field-lists>` containing the function
|
||||||
parameter, its expected type, the return value, and the return type.
|
parameter, its expected type, the return value, and the return type.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
@ -35,4 +35,5 @@ project.
|
|||||||
narrative-documentation
|
narrative-documentation
|
||||||
describing-code
|
describing-code
|
||||||
automatic-doc-generation
|
automatic-doc-generation
|
||||||
|
deploying
|
||||||
end
|
end
|
||||||
|
@ -68,6 +68,24 @@ be translated you need to follow these instructions:
|
|||||||
* Run your desired build.
|
* Run your desired build.
|
||||||
|
|
||||||
|
|
||||||
|
In order to protect against mistakes, a warning is emitted if
|
||||||
|
cross-references in the translated paragraph do not match those from the
|
||||||
|
original. This can be turned off globally using the
|
||||||
|
:confval:`suppress_warnings` configuration variable. Alternatively, to
|
||||||
|
turn it off for one message only, end the message with ``#noqa`` like
|
||||||
|
this::
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
|
||||||
|
risus tortor, luctus id ultrices at. #noqa
|
||||||
|
|
||||||
|
(Write ``\#noqa`` in case you want to have "#noqa" literally in the
|
||||||
|
text. This does not apply to code blocks, where ``#noqa`` is ignored
|
||||||
|
because code blocks do not contain references anyway.)
|
||||||
|
|
||||||
|
.. versionadded:: 4.5
|
||||||
|
The ``#noqa`` mechanism.
|
||||||
|
|
||||||
|
|
||||||
Translating with sphinx-intl
|
Translating with sphinx-intl
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
|
@ -6,6 +6,10 @@ Setuptools integration
|
|||||||
Sphinx supports integration with setuptools and distutils through a custom
|
Sphinx supports integration with setuptools and distutils through a custom
|
||||||
command - :class:`~sphinx.setup_command.BuildDoc`.
|
command - :class:`~sphinx.setup_command.BuildDoc`.
|
||||||
|
|
||||||
|
.. deprecated:: 5.0
|
||||||
|
|
||||||
|
This feature will be removed in v7.0.
|
||||||
|
|
||||||
Using setuptools integration
|
Using setuptools integration
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
@ -64,7 +68,7 @@ Options for setuptools integration
|
|||||||
|
|
||||||
This can also be set by passing the `-E` flag to ``setup.py``:
|
This can also be set by passing the `-E` flag to ``setup.py``:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: console
|
||||||
|
|
||||||
$ python setup.py build_sphinx -E
|
$ python setup.py build_sphinx -E
|
||||||
|
|
||||||
@ -75,7 +79,7 @@ Options for setuptools integration
|
|||||||
|
|
||||||
This can also be set by passing the `-a` flag to ``setup.py``:
|
This can also be set by passing the `-a` flag to ``setup.py``:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: console
|
||||||
|
|
||||||
$ python setup.py build_sphinx -a
|
$ python setup.py build_sphinx -a
|
||||||
|
|
||||||
@ -88,7 +92,7 @@ Options for setuptools integration
|
|||||||
|
|
||||||
This can also be set by passing the `-s` flag to ``setup.py``:
|
This can also be set by passing the `-s` flag to ``setup.py``:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: console
|
||||||
|
|
||||||
$ python setup.py build_sphinx -s $SOURCE_DIR
|
$ python setup.py build_sphinx -s $SOURCE_DIR
|
||||||
|
|
||||||
@ -105,7 +109,7 @@ Options for setuptools integration
|
|||||||
|
|
||||||
This can also be set by passing the `-c` flag to ``setup.py``:
|
This can also be set by passing the `-c` flag to ``setup.py``:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: console
|
||||||
|
|
||||||
$ python setup.py build_sphinx -c $CONFIG_DIR
|
$ python setup.py build_sphinx -c $CONFIG_DIR
|
||||||
|
|
||||||
@ -117,7 +121,7 @@ Options for setuptools integration
|
|||||||
|
|
||||||
This can also be set by passing the `-b` flag to ``setup.py``:
|
This can also be set by passing the `-b` flag to ``setup.py``:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: console
|
||||||
|
|
||||||
$ python setup.py build_sphinx -b $BUILDER
|
$ python setup.py build_sphinx -b $BUILDER
|
||||||
|
|
||||||
@ -131,7 +135,7 @@ Options for setuptools integration
|
|||||||
|
|
||||||
This can also be set by passing the `-W` flag to ``setup.py``:
|
This can also be set by passing the `-W` flag to ``setup.py``:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: console
|
||||||
|
|
||||||
$ python setup.py build_sphinx -W
|
$ python setup.py build_sphinx -W
|
||||||
|
|
||||||
@ -169,7 +173,7 @@ Options for setuptools integration
|
|||||||
|
|
||||||
This can also be set by passing the `-i` flag to ``setup.py``:
|
This can also be set by passing the `-i` flag to ``setup.py``:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: console
|
||||||
|
|
||||||
$ python setup.py build_sphinx -i
|
$ python setup.py build_sphinx -i
|
||||||
|
|
||||||
|
@ -316,7 +316,11 @@ General configuration
|
|||||||
* ``app.add_role``
|
* ``app.add_role``
|
||||||
* ``app.add_generic_role``
|
* ``app.add_generic_role``
|
||||||
* ``app.add_source_parser``
|
* ``app.add_source_parser``
|
||||||
|
* ``autosectionlabel.*``
|
||||||
* ``download.not_readable``
|
* ``download.not_readable``
|
||||||
|
* ``epub.unknown_project_files``
|
||||||
|
* ``epub.duplicated_toc_entry``
|
||||||
|
* ``i18n.inconsistent_references``
|
||||||
* ``image.not_readable``
|
* ``image.not_readable``
|
||||||
* ``ref.term``
|
* ``ref.term``
|
||||||
* ``ref.ref``
|
* ``ref.ref``
|
||||||
@ -332,11 +336,9 @@ General configuration
|
|||||||
* ``toc.excluded``
|
* ``toc.excluded``
|
||||||
* ``toc.not_readable``
|
* ``toc.not_readable``
|
||||||
* ``toc.secnum``
|
* ``toc.secnum``
|
||||||
* ``epub.unknown_project_files``
|
|
||||||
* ``epub.duplicated_toc_entry``
|
|
||||||
* ``autosectionlabel.*``
|
|
||||||
|
|
||||||
You can choose from these types.
|
You can choose from these types. You can also give only the first
|
||||||
|
component to exclude all warnings attached to it.
|
||||||
|
|
||||||
Now, this option should be considered *experimental*.
|
Now, this option should be considered *experimental*.
|
||||||
|
|
||||||
@ -366,6 +368,10 @@ General configuration
|
|||||||
|
|
||||||
Added ``toc.excluded`` and ``toc.not_readable``
|
Added ``toc.excluded`` and ``toc.not_readable``
|
||||||
|
|
||||||
|
.. versionadded:: 4.5
|
||||||
|
|
||||||
|
Added ``i18n.inconsistent_references``
|
||||||
|
|
||||||
.. confval:: needs_sphinx
|
.. confval:: needs_sphinx
|
||||||
|
|
||||||
If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will
|
If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will
|
||||||
@ -392,7 +398,7 @@ General configuration
|
|||||||
|
|
||||||
.. confval:: manpages_url
|
.. confval:: manpages_url
|
||||||
|
|
||||||
A URL to cross-reference :rst:role:`manpage` directives. If this is
|
A URL to cross-reference :rst:role:`manpage` roles. If this is
|
||||||
defined to ``https://manpages.debian.org/{path}``, the
|
defined to ``https://manpages.debian.org/{path}``, the
|
||||||
:literal:`:manpage:`man(1)`` role will link to
|
:literal:`:manpage:`man(1)`` role will link to
|
||||||
<https://manpages.debian.org/man(1)>. The patterns available are:
|
<https://manpages.debian.org/man(1)>. The patterns available are:
|
||||||
@ -1351,6 +1357,13 @@ that use Sphinx's HTMLWriter class.
|
|||||||
|
|
||||||
.. versionadded:: 1.0
|
.. versionadded:: 1.0
|
||||||
|
|
||||||
|
.. confval:: html_show_search_summary
|
||||||
|
|
||||||
|
If true, the text around the keyword is shown as summary of each search result.
|
||||||
|
Default is ``True``.
|
||||||
|
|
||||||
|
.. versionadded:: 4.5
|
||||||
|
|
||||||
.. confval:: html_show_sphinx
|
.. confval:: html_show_sphinx
|
||||||
|
|
||||||
If true, "Created using Sphinx" is shown in the HTML footer. Default is
|
If true, "Created using Sphinx" is shown in the HTML footer. Default is
|
||||||
@ -2499,6 +2512,13 @@ These options influence Texinfo output.
|
|||||||
|
|
||||||
.. versionadded:: 1.1
|
.. versionadded:: 1.1
|
||||||
|
|
||||||
|
.. confval:: texinfo_cross_references
|
||||||
|
|
||||||
|
If false, do not generate inline references in a document. That makes
|
||||||
|
an info file more readable with stand-alone reader (``info``).
|
||||||
|
Default is ``True``.
|
||||||
|
|
||||||
|
.. versionadded:: 4.4
|
||||||
|
|
||||||
.. _qthelp-options:
|
.. _qthelp-options:
|
||||||
|
|
||||||
@ -2683,6 +2703,19 @@ Options for the linkcheck builder
|
|||||||
|
|
||||||
.. versionadded:: 3.4
|
.. versionadded:: 3.4
|
||||||
|
|
||||||
|
.. confval:: linkcheck_exclude_documents
|
||||||
|
|
||||||
|
A list of regular expressions that match documents in which Sphinx should
|
||||||
|
not check the validity of links. This can be used for permitting link decay
|
||||||
|
in legacy or historical sections of the documentation.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
# ignore all links in documents located in a subfolder named 'legacy'
|
||||||
|
linkcheck_exclude_documents = [r'.*/legacy/.*']
|
||||||
|
|
||||||
|
.. versionadded:: 4.4
|
||||||
|
|
||||||
|
|
||||||
Options for the XML builder
|
Options for the XML builder
|
||||||
---------------------------
|
---------------------------
|
||||||
|
@ -41,7 +41,7 @@ you can also enable the :mod:`napoleon <sphinx.ext.napoleon>` extension.
|
|||||||
docstrings to correct reStructuredText before :mod:`autodoc` processes them.
|
docstrings to correct reStructuredText before :mod:`autodoc` processes them.
|
||||||
|
|
||||||
.. _Google: https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings
|
.. _Google: https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings
|
||||||
.. _NumPy: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
|
.. _NumPy: https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard
|
||||||
|
|
||||||
|
|
||||||
Directives
|
Directives
|
||||||
@ -468,7 +468,7 @@ There are also config values that you can set:
|
|||||||
|
|
||||||
.. confval:: autodoc_class_signature
|
.. confval:: autodoc_class_signature
|
||||||
|
|
||||||
This value selects how the signautre will be displayed for the class defined
|
This value selects how the signature will be displayed for the class defined
|
||||||
by :rst:dir:`autoclass` directive. The possible values are:
|
by :rst:dir:`autoclass` directive. The possible values are:
|
||||||
|
|
||||||
``"mixed"``
|
``"mixed"``
|
||||||
@ -528,7 +528,8 @@ There are also config values that you can set:
|
|||||||
The supported options are ``'members'``, ``'member-order'``,
|
The supported options are ``'members'``, ``'member-order'``,
|
||||||
``'undoc-members'``, ``'private-members'``, ``'special-members'``,
|
``'undoc-members'``, ``'private-members'``, ``'special-members'``,
|
||||||
``'inherited-members'``, ``'show-inheritance'``, ``'ignore-module-all'``,
|
``'inherited-members'``, ``'show-inheritance'``, ``'ignore-module-all'``,
|
||||||
``'imported-members'``, ``'exclude-members'`` and ``'class-doc-from'``.
|
``'imported-members'``, ``'exclude-members'``, ``'class-doc-from'`` and
|
||||||
|
``'no-value'``.
|
||||||
|
|
||||||
.. versionadded:: 1.8
|
.. versionadded:: 1.8
|
||||||
|
|
||||||
@ -541,6 +542,9 @@ There are also config values that you can set:
|
|||||||
.. versionchanged:: 4.1
|
.. versionchanged:: 4.1
|
||||||
Added ``'class-doc-from'``.
|
Added ``'class-doc-from'``.
|
||||||
|
|
||||||
|
.. versionchanged:: 4.5
|
||||||
|
Added ``'no-value'``.
|
||||||
|
|
||||||
.. confval:: autodoc_docstring_signature
|
.. confval:: autodoc_docstring_signature
|
||||||
|
|
||||||
Functions imported from C modules cannot be introspected, and therefore the
|
Functions imported from C modules cannot be introspected, and therefore the
|
||||||
@ -638,8 +642,8 @@ There are also config values that you can set:
|
|||||||
full-qualified object name. It is used to keep type aliases not evaluated in
|
full-qualified object name. It is used to keep type aliases not evaluated in
|
||||||
the document. Defaults to empty (``{}``).
|
the document. Defaults to empty (``{}``).
|
||||||
|
|
||||||
The type aliases are only available if your program enables `Postponed
|
The type aliases are only available if your program enables :pep:`Postponed
|
||||||
Evaluation of Annotations (PEP 563)`__ feature via ``from __future__ import
|
Evaluation of Annotations (PEP 563) <563>` feature via ``from __future__ import
|
||||||
annotations``.
|
annotations``.
|
||||||
|
|
||||||
For example, there is code using a type alias::
|
For example, there is code using a type alias::
|
||||||
@ -666,10 +670,24 @@ There are also config values that you can set:
|
|||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
.. __: https://www.python.org/dev/peps/pep-0563/
|
|
||||||
.. __: https://mypy.readthedocs.io/en/latest/kinds_of_types.html#type-aliases
|
.. __: https://mypy.readthedocs.io/en/latest/kinds_of_types.html#type-aliases
|
||||||
.. versionadded:: 3.3
|
.. versionadded:: 3.3
|
||||||
|
|
||||||
|
.. confval:: autodoc_typehints_format
|
||||||
|
|
||||||
|
This value controls the format of typehints. The setting takes the
|
||||||
|
following values:
|
||||||
|
|
||||||
|
* ``'fully-qualified'`` -- Show the module name and its name of typehints
|
||||||
|
* ``'short'`` -- Suppress the leading module names of the typehints
|
||||||
|
(ex. ``io.StringIO`` -> ``StringIO``) (default)
|
||||||
|
|
||||||
|
.. versionadded:: 4.4
|
||||||
|
|
||||||
|
.. versionchanged:: 5.0
|
||||||
|
|
||||||
|
The default setting was changed to ``'short'``
|
||||||
|
|
||||||
.. confval:: autodoc_preserve_defaults
|
.. confval:: autodoc_preserve_defaults
|
||||||
|
|
||||||
If True, the default argument values of functions will be not evaluated on
|
If True, the default argument values of functions will be not evaluated on
|
||||||
|
@ -255,7 +255,7 @@ Autosummary uses the following Jinja template files:
|
|||||||
- :file:`autosummary/attribute.rst` -- template for class attributes
|
- :file:`autosummary/attribute.rst` -- template for class attributes
|
||||||
- :file:`autosummary/method.rst` -- template for class methods
|
- :file:`autosummary/method.rst` -- template for class methods
|
||||||
|
|
||||||
The following variables available in the templates:
|
The following variables are available in the templates:
|
||||||
|
|
||||||
.. currentmodule:: None
|
.. currentmodule:: None
|
||||||
|
|
||||||
@ -300,7 +300,7 @@ The following variables available in the templates:
|
|||||||
.. data:: functions
|
.. data:: functions
|
||||||
|
|
||||||
List containing names of "public" functions in the module. Here, "public"
|
List containing names of "public" functions in the module. Here, "public"
|
||||||
here means that the name does not start with an underscore. Only available
|
means that the name does not start with an underscore. Only available
|
||||||
for modules.
|
for modules.
|
||||||
|
|
||||||
.. data:: classes
|
.. data:: classes
|
||||||
|
@ -93,8 +93,8 @@ a comma-separated list of group names.
|
|||||||
* ``<``, ``>``: Exclusive ordered comparison clause
|
* ``<``, ``>``: Exclusive ordered comparison clause
|
||||||
* ``===``: Arbitrary equality clause.
|
* ``===``: Arbitrary equality clause.
|
||||||
|
|
||||||
``pyversion`` option is followed `PEP-440: Version Specifiers
|
``pyversion`` option is followed :pep:`PEP-440: Version Specifiers
|
||||||
<https://www.python.org/dev/peps/pep-0440/#version-specifiers>`__.
|
<440#version-specifiers>`.
|
||||||
|
|
||||||
.. versionadded:: 1.6
|
.. versionadded:: 1.6
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ on the first line, separated by a colon.
|
|||||||
def function_with_types_in_docstring(param1, param2):
|
def function_with_types_in_docstring(param1, param2):
|
||||||
"""Example function with types documented in the docstring.
|
"""Example function with types documented in the docstring.
|
||||||
|
|
||||||
`PEP 484`_ type annotations are supported. If attribute, parameter, and
|
:pep:`484` type annotations are supported. If attribute, parameter, and
|
||||||
return types are annotated according to `PEP 484`_, they do not need to be
|
return types are annotated according to `PEP 484`_, they do not need to be
|
||||||
included in the docstring:
|
included in the docstring:
|
||||||
|
|
||||||
@ -55,10 +55,6 @@ def function_with_types_in_docstring(param1, param2):
|
|||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
bool: The return value. True for success, False otherwise.
|
bool: The return value. True for success, False otherwise.
|
||||||
|
|
||||||
.. _PEP 484:
|
|
||||||
https://www.python.org/dev/peps/pep-0484/
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
@ -311,4 +307,4 @@ class ExamplePEP526Class:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
attr1: str
|
attr1: str
|
||||||
attr2: int
|
attr2: int
|
||||||
|
@ -37,8 +37,8 @@ module_level_variable1 : int
|
|||||||
with it.
|
with it.
|
||||||
|
|
||||||
|
|
||||||
.. _NumPy Documentation HOWTO:
|
.. _NumPy docstring standard:
|
||||||
https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
|
https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ on the first line, separated by a colon.
|
|||||||
def function_with_types_in_docstring(param1, param2):
|
def function_with_types_in_docstring(param1, param2):
|
||||||
"""Example function with types documented in the docstring.
|
"""Example function with types documented in the docstring.
|
||||||
|
|
||||||
`PEP 484`_ type annotations are supported. If attribute, parameter, and
|
:pep:`484` type annotations are supported. If attribute, parameter, and
|
||||||
return types are annotated according to `PEP 484`_, they do not need to be
|
return types are annotated according to `PEP 484`_, they do not need to be
|
||||||
included in the docstring:
|
included in the docstring:
|
||||||
|
|
||||||
@ -70,10 +70,6 @@ def function_with_types_in_docstring(param1, param2):
|
|||||||
-------
|
-------
|
||||||
bool
|
bool
|
||||||
True if successful, False otherwise.
|
True if successful, False otherwise.
|
||||||
|
|
||||||
.. _PEP 484:
|
|
||||||
https://www.python.org/dev/peps/pep-0484/
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,3 +59,11 @@ The extension adds a config value:
|
|||||||
|
|
||||||
Since links are generated from the role in the reading stage, they appear as
|
Since links are generated from the role in the reading stage, they appear as
|
||||||
ordinary links to e.g. the ``linkcheck`` builder.
|
ordinary links to e.g. the ``linkcheck`` builder.
|
||||||
|
|
||||||
|
.. confval:: extlinks_detect_hardcoded_links
|
||||||
|
|
||||||
|
If enabled, extlinks emits a warning if a hardcoded link is replaceable
|
||||||
|
by an extlink, and suggests a replacement via warning. It defaults to
|
||||||
|
``False``.
|
||||||
|
|
||||||
|
.. versionadded:: 4.5
|
||||||
|
@ -8,20 +8,25 @@
|
|||||||
|
|
||||||
.. versionadded:: 0.5
|
.. versionadded:: 0.5
|
||||||
|
|
||||||
This extension can generate automatic links to the documentation of objects in
|
This extension can generate links to the documentation of objects in external
|
||||||
other projects.
|
projects, either explicitly through the :rst:role:`external` role, or as a
|
||||||
|
fallback resolution for any other cross-reference.
|
||||||
|
|
||||||
Usage is simple: whenever Sphinx encounters a cross-reference that has no
|
Usage for fallback resolution is simple: whenever Sphinx encounters a
|
||||||
matching target in the current documentation set, it looks for targets in the
|
cross-reference that has no matching target in the current documentation set,
|
||||||
documentation sets configured in :confval:`intersphinx_mapping`. A reference
|
it looks for targets in the external documentation sets configured in
|
||||||
like ``:py:class:`zipfile.ZipFile``` can then link to the Python documentation
|
:confval:`intersphinx_mapping`. A reference like
|
||||||
|
``:py:class:`zipfile.ZipFile``` can then link to the Python documentation
|
||||||
for the ZipFile class, without you having to specify where it is located
|
for the ZipFile class, without you having to specify where it is located
|
||||||
exactly.
|
exactly.
|
||||||
|
|
||||||
When using the "new" format (see below), you can even force lookup in a foreign
|
When using the :rst:role:`external` role, you can force lookup to any external
|
||||||
set by prefixing the link target appropriately. A link like ``:ref:`comparison
|
projects, and optionally to a specific external project.
|
||||||
manual <python:comparisons>``` will then link to the label "comparisons" in the
|
A link like ``:external:ref:`comparison manual <comparisons>``` will then link
|
||||||
doc set "python", if it exists.
|
to the label "comparisons" in whichever configured external project, if it
|
||||||
|
exists,
|
||||||
|
and a link like ``:external+python:ref:`comparison manual <comparisons>``` will
|
||||||
|
link to the label "comparisons" only in the doc set "python", if it exists.
|
||||||
|
|
||||||
Behind the scenes, this works as follows:
|
Behind the scenes, this works as follows:
|
||||||
|
|
||||||
@ -30,8 +35,8 @@ Behind the scenes, this works as follows:
|
|||||||
|
|
||||||
* Projects using the Intersphinx extension can specify the location of such
|
* Projects using the Intersphinx extension can specify the location of such
|
||||||
mapping files in the :confval:`intersphinx_mapping` config value. The mapping
|
mapping files in the :confval:`intersphinx_mapping` config value. The mapping
|
||||||
will then be used to resolve otherwise missing references to objects into
|
will then be used to resolve both :rst:role:`external` references, and also
|
||||||
links to the other documentation.
|
otherwise missing references to objects into links to the other documentation.
|
||||||
|
|
||||||
* By default, the mapping file is assumed to be at the same location as the rest
|
* By default, the mapping file is assumed to be at the same location as the rest
|
||||||
of the documentation; however, the location of the mapping file can also be
|
of the documentation; however, the location of the mapping file can also be
|
||||||
@ -79,10 +84,10 @@ linking:
|
|||||||
at the same location as the base URI) or another local file path or a full
|
at the same location as the base URI) or another local file path or a full
|
||||||
HTTP URI to an inventory file.
|
HTTP URI to an inventory file.
|
||||||
|
|
||||||
The unique identifier can be used to prefix cross-reference targets, so that
|
The unique identifier can be used in the :rst:role:`external` role, so that
|
||||||
it is clear which intersphinx set the target belongs to. A link like
|
it is clear which intersphinx set the target belongs to. A link like
|
||||||
``:ref:`comparison manual <python:comparisons>``` will link to the label
|
``external:python+ref:`comparison manual <comparisons>``` will link to the
|
||||||
"comparisons" in the doc set "python", if it exists.
|
label "comparisons" in the doc set "python", if it exists.
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
|
|
||||||
@ -152,6 +157,10 @@ linking:
|
|||||||
|
|
||||||
.. versionadded:: 4.3
|
.. versionadded:: 4.3
|
||||||
|
|
||||||
|
.. versionchanged:: 5.0
|
||||||
|
|
||||||
|
Changed default value from an empty list to ``['std:doc']``.
|
||||||
|
|
||||||
A list of strings being either:
|
A list of strings being either:
|
||||||
|
|
||||||
- the name of a specific reference type in a domain,
|
- the name of a specific reference type in a domain,
|
||||||
@ -160,23 +169,52 @@ linking:
|
|||||||
``std:*``, ``py:*``, or ``cpp:*``, or
|
``std:*``, ``py:*``, or ``cpp:*``, or
|
||||||
- simply a wildcard ``*``.
|
- simply a wildcard ``*``.
|
||||||
|
|
||||||
The default value is an empty list.
|
The default value is ``['std:doc']``.
|
||||||
|
|
||||||
When a cross-reference without an explicit inventory specification is being
|
When a non-:rst:role:`external` cross-reference is being resolved by
|
||||||
resolved by intersphinx, skip resolution if it matches one of the
|
intersphinx, skip resolution if it matches one of the specifications in this
|
||||||
specifications in this list.
|
list.
|
||||||
|
|
||||||
For example, with ``intersphinx_disabled_reftypes = ['std:doc']``
|
For example, with ``intersphinx_disabled_reftypes = ['std:doc']``
|
||||||
a cross-reference ``:doc:`installation``` will not be attempted to be
|
a cross-reference ``:doc:`installation``` will not be attempted to be
|
||||||
resolved by intersphinx, but ``:doc:`otherbook:installation``` will be
|
resolved by intersphinx, but ``:external+otherbook:doc:`installation``` will
|
||||||
attempted to be resolved in the inventory named ``otherbook`` in
|
be attempted to be resolved in the inventory named ``otherbook`` in
|
||||||
:confval:`intersphinx_mapping`.
|
:confval:`intersphinx_mapping`.
|
||||||
At the same time, all cross-references generated in, e.g., Python,
|
At the same time, all cross-references generated in, e.g., Python,
|
||||||
declarations will still be attempted to be resolved by intersphinx.
|
declarations will still be attempted to be resolved by intersphinx.
|
||||||
|
|
||||||
If ``*`` is in the list of domains, then no references without an explicit
|
If ``*`` is in the list of domains, then no non-:rst:role:`external`
|
||||||
inventory will be resolved by intersphinx.
|
references will be resolved by intersphinx.
|
||||||
|
|
||||||
|
Explicitly Reference External Objects
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
The Intersphinx extension provides the following role.
|
||||||
|
|
||||||
|
.. rst:role:: external
|
||||||
|
|
||||||
|
.. versionadded:: 4.4
|
||||||
|
|
||||||
|
Use Intersphinx to perform lookup only in external projects, and not the
|
||||||
|
current project. Intersphinx still needs to know the type of object you
|
||||||
|
would like to find, so the general form of this role is to write the
|
||||||
|
cross-refererence as if the object is in the current project, but then prefix
|
||||||
|
it with ``:external``.
|
||||||
|
The two forms are then
|
||||||
|
|
||||||
|
- ``:external:domain:reftype:`target```,
|
||||||
|
e.g., ``:external:py:class:`zipfile.ZipFile```, or
|
||||||
|
- ``:external:reftype:`target```,
|
||||||
|
e.g., ``:external:doc:`installation```.
|
||||||
|
|
||||||
|
If you would like to constrain the lookup to a specific external project,
|
||||||
|
then the key of the project, as specified in :confval:`intersphinx_mapping`,
|
||||||
|
is added as well to get the two forms
|
||||||
|
|
||||||
|
- ``:external+invname:domain:reftype:`target```,
|
||||||
|
e.g., ``:external+python:py:class:`zipfile.ZipFile```, or
|
||||||
|
- ``:external+invname:reftype:`target```,
|
||||||
|
e.g., ``:external+python:doc:`installation```.
|
||||||
|
|
||||||
Showing all links of an Intersphinx mapping file
|
Showing all links of an Intersphinx mapping file
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
@ -26,7 +26,7 @@ Are you tired of writing docstrings that look like this::
|
|||||||
:rtype: BufferedFileStorage
|
:rtype: BufferedFileStorage
|
||||||
|
|
||||||
`reStructuredText`_ is great, but it creates visually dense, hard to read
|
`reStructuredText`_ is great, but it creates visually dense, hard to read
|
||||||
`docstrings`_. Compare the jumble above to the same thing rewritten
|
:pep:`docstrings <287>`. Compare the jumble above to the same thing rewritten
|
||||||
according to the `Google Python Style Guide`_::
|
according to the `Google Python Style Guide`_::
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@ -50,7 +50,6 @@ the documentation, so it doesn't modify any of the docstrings in your actual
|
|||||||
source code files.
|
source code files.
|
||||||
|
|
||||||
.. _ReStructuredText: https://docutils.sourceforge.io/rst.html
|
.. _ReStructuredText: https://docutils.sourceforge.io/rst.html
|
||||||
.. _docstrings: https://www.python.org/dev/peps/pep-0287/
|
|
||||||
.. _Google Python Style Guide:
|
.. _Google Python Style Guide:
|
||||||
https://google.github.io/styleguide/pyguide.html
|
https://google.github.io/styleguide/pyguide.html
|
||||||
.. _Google:
|
.. _Google:
|
||||||
@ -199,11 +198,11 @@ not be mixed. Choose one style for your project and be consistent with it.
|
|||||||
Type Annotations
|
Type Annotations
|
||||||
~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
`PEP 484`_ introduced a standard way to express types in Python code.
|
:pep:`484` introduced a standard way to express types in Python code.
|
||||||
This is an alternative to expressing types directly in docstrings.
|
This is an alternative to expressing types directly in docstrings.
|
||||||
One benefit of expressing types according to `PEP 484`_ is that
|
One benefit of expressing types according to :pep:`484` is that
|
||||||
type checkers and IDEs can take advantage of them for static code
|
type checkers and IDEs can take advantage of them for static code
|
||||||
analysis. `PEP 484`_ was then extended by `PEP 526`_ which introduced
|
analysis. :pep:`484` was then extended by :pep:`526` which introduced
|
||||||
a similar way to annotate variables (and attributes).
|
a similar way to annotate variables (and attributes).
|
||||||
|
|
||||||
Google style with Python 3 type annotations::
|
Google style with Python 3 type annotations::
|
||||||
@ -267,9 +266,7 @@ Google style with types in docstrings::
|
|||||||
`Python 2/3 compatible annotations`_ aren't currently
|
`Python 2/3 compatible annotations`_ aren't currently
|
||||||
supported by Sphinx and won't show up in the docs.
|
supported by Sphinx and won't show up in the docs.
|
||||||
|
|
||||||
.. _PEP 484: https://www.python.org/dev/peps/pep-0484/
|
.. _Python 2/3 compatible annotations: https://peps.python.org/pep-0484/#suggested-syntax-for-python-2-7-and-straddling-code
|
||||||
.. _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
|
|
||||||
|
|
||||||
|
|
||||||
Configuration
|
Configuration
|
||||||
@ -548,7 +545,7 @@ sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
|
|||||||
|
|
||||||
.. confval:: napoleon_attr_annotations
|
.. confval:: napoleon_attr_annotations
|
||||||
|
|
||||||
True to allow using `PEP 526`_ attributes annotations in classes.
|
True to allow using :pep:`526` attributes annotations in classes.
|
||||||
If an attribute is documented in the docstring without a type and
|
If an attribute is documented in the docstring without a type and
|
||||||
has an annotation in the class body, that type is used.
|
has an annotation in the class body, that type is used.
|
||||||
|
|
||||||
|
@ -222,8 +222,8 @@ of images:
|
|||||||
- `sphinxdoc/sphinx-latexpdf`_
|
- `sphinxdoc/sphinx-latexpdf`_
|
||||||
|
|
||||||
.. _Docker Hub: https://hub.docker.com/
|
.. _Docker Hub: https://hub.docker.com/
|
||||||
.. _sphinxdoc/sphinx: https://hub.docker.com/repository/docker/sphinxdoc/sphinx
|
.. _sphinxdoc/sphinx: https://hub.docker.com/r/sphinxdoc/sphinx
|
||||||
.. _sphinxdoc/sphinx-latexpdf: https://hub.docker.com/repository/docker/sphinxdoc/sphinx-latexpdf
|
.. _sphinxdoc/sphinx-latexpdf: https://hub.docker.com/r/sphinxdoc/sphinx-latexpdf
|
||||||
|
|
||||||
Former one is used for standard usage of Sphinx, and latter one is mainly used for
|
Former one is used for standard usage of Sphinx, and latter one is mainly used for
|
||||||
PDF builds using LaTeX. Please choose one for your purpose.
|
PDF builds using LaTeX. Please choose one for your purpose.
|
||||||
@ -239,19 +239,19 @@ PDF builds using LaTeX. Please choose one for your purpose.
|
|||||||
commands. For example, you can use following command to create a Sphinx
|
commands. For example, you can use following command to create a Sphinx
|
||||||
project:
|
project:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: console
|
||||||
|
|
||||||
$ docker run -it --rm -v /path/to/document:/docs sphinxdoc/sphinx sphinx-quickstart
|
$ docker run -it --rm -v /path/to/document:/docs sphinxdoc/sphinx sphinx-quickstart
|
||||||
|
|
||||||
And you can following command this to build HTML document:
|
And you can use the following command to build HTML document:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: console
|
||||||
|
|
||||||
$ docker run --rm -v /path/to/document:/docs sphinxdoc/sphinx make html
|
$ docker run --rm -v /path/to/document:/docs sphinxdoc/sphinx make html
|
||||||
|
|
||||||
For more details, please read `README file`__ of docker images.
|
For more details, please read `README file`__ of docker images.
|
||||||
|
|
||||||
.. __: https://hub.docker.com/repository/docker/sphinxdoc/sphinx
|
.. __: https://hub.docker.com/r/sphinxdoc/sphinx
|
||||||
|
|
||||||
|
|
||||||
Installation from source
|
Installation from source
|
||||||
|
@ -39,7 +39,7 @@ Sphinx comes with a script called :program:`sphinx-quickstart` that sets up a
|
|||||||
source directory and creates a default :file:`conf.py` with the most useful
|
source directory and creates a default :file:`conf.py` with the most useful
|
||||||
configuration values from a few questions it asks you. To use this, run:
|
configuration values from a few questions it asks you. To use this, run:
|
||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: console
|
||||||
|
|
||||||
$ sphinx-quickstart
|
$ sphinx-quickstart
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ Running the build
|
|||||||
Now that you have added some files and content, let's make a first build of the
|
Now that you have added some files and content, let's make a first build of the
|
||||||
docs. A build is started with the :program:`sphinx-build` program:
|
docs. A build is started with the :program:`sphinx-build` program:
|
||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: console
|
||||||
|
|
||||||
$ sphinx-build -b html sourcedir builddir
|
$ sphinx-build -b html sourcedir builddir
|
||||||
|
|
||||||
@ -144,7 +144,7 @@ However, :program:`sphinx-quickstart` script creates a :file:`Makefile` and a
|
|||||||
:file:`make.bat` which make life even easier for you. These can be executed by
|
:file:`make.bat` which make life even easier for you. These can be executed by
|
||||||
running :command:`make` with the name of the builder. For example.
|
running :command:`make` with the name of the builder. For example.
|
||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: console
|
||||||
|
|
||||||
$ make html
|
$ make html
|
||||||
|
|
||||||
|
@ -245,10 +245,10 @@ follow:
|
|||||||
|
|
||||||
* ``#`` with overline, for parts
|
* ``#`` with overline, for parts
|
||||||
* ``*`` with overline, for chapters
|
* ``*`` with overline, for chapters
|
||||||
* ``=``, for sections
|
* ``=`` for sections
|
||||||
* ``-``, for subsections
|
* ``-`` for subsections
|
||||||
* ``^``, for subsubsections
|
* ``^`` for subsubsections
|
||||||
* ``"``, for paragraphs
|
* ``"`` for paragraphs
|
||||||
|
|
||||||
Of course, you are free to use your own marker characters (see the reST
|
Of course, you are free to use your own marker characters (see the reST
|
||||||
documentation), and use a deeper nesting level, but keep in mind that most
|
documentation), and use a deeper nesting level, but keep in mind that most
|
||||||
|
@ -598,6 +598,7 @@ __ https://pygments.org/docs/lexers
|
|||||||
are removed via :func:`textwrap.dedent()`. For example::
|
are removed via :func:`textwrap.dedent()`. For example::
|
||||||
|
|
||||||
.. code-block:: ruby
|
.. code-block:: ruby
|
||||||
|
:linenos:
|
||||||
:dedent: 4
|
:dedent: 4
|
||||||
|
|
||||||
some ruby code
|
some ruby code
|
||||||
@ -831,6 +832,9 @@ Glossary
|
|||||||
.. versionchanged:: 1.4
|
.. versionchanged:: 1.4
|
||||||
Index key for glossary term should be considered *experimental*.
|
Index key for glossary term should be considered *experimental*.
|
||||||
|
|
||||||
|
.. versionchanged:: 4.4
|
||||||
|
In internationalized documentation, the ``:sorted:`` flag sorts
|
||||||
|
according to translated terms.
|
||||||
|
|
||||||
Meta-information markup
|
Meta-information markup
|
||||||
-----------------------
|
-----------------------
|
||||||
|
@ -211,6 +211,12 @@ The following directives are provided for module and class contents:
|
|||||||
|
|
||||||
.. versionadded:: 4.0
|
.. versionadded:: 4.0
|
||||||
|
|
||||||
|
.. rst::directive:option:: module
|
||||||
|
:type: text
|
||||||
|
|
||||||
|
Describe the location where the object is defined. The default value is
|
||||||
|
the module specified by :rst:dir:`py:currentmodule`.
|
||||||
|
|
||||||
.. rst:directive:: .. py:data:: name
|
.. rst:directive:: .. py:data:: name
|
||||||
|
|
||||||
Describes global data in a module, including both variables and values used
|
Describes global data in a module, including both variables and values used
|
||||||
@ -237,6 +243,12 @@ The following directives are provided for module and class contents:
|
|||||||
|
|
||||||
.. versionadded:: 4.0
|
.. versionadded:: 4.0
|
||||||
|
|
||||||
|
.. rst::directive:option:: module
|
||||||
|
:type: text
|
||||||
|
|
||||||
|
Describe the location where the object is defined. The default value is
|
||||||
|
the module specified by :rst:dir:`py:currentmodule`.
|
||||||
|
|
||||||
.. rst:directive:: .. py:exception:: name
|
.. rst:directive:: .. py:exception:: name
|
||||||
|
|
||||||
Describes an exception class. The signature can, but need not include
|
Describes an exception class. The signature can, but need not include
|
||||||
@ -251,6 +263,12 @@ The following directives are provided for module and class contents:
|
|||||||
|
|
||||||
.. versionadded:: 3.1
|
.. versionadded:: 3.1
|
||||||
|
|
||||||
|
.. rst::directive:option:: module
|
||||||
|
:type: text
|
||||||
|
|
||||||
|
Describe the location where the object is defined. The default value is
|
||||||
|
the module specified by :rst:dir:`py:currentmodule`.
|
||||||
|
|
||||||
.. rst:directive:: .. py:class:: name
|
.. rst:directive:: .. py:class:: name
|
||||||
.. py:class:: name(parameters)
|
.. py:class:: name(parameters)
|
||||||
|
|
||||||
@ -291,6 +309,12 @@ The following directives are provided for module and class contents:
|
|||||||
|
|
||||||
.. versionadded:: 3.1
|
.. versionadded:: 3.1
|
||||||
|
|
||||||
|
.. rst::directive:option:: module
|
||||||
|
:type: text
|
||||||
|
|
||||||
|
Describe the location where the object is defined. The default value is
|
||||||
|
the module specified by :rst:dir:`py:currentmodule`.
|
||||||
|
|
||||||
.. rst:directive:: .. py:attribute:: name
|
.. rst:directive:: .. py:attribute:: name
|
||||||
|
|
||||||
Describes an object data attribute. The description should include
|
Describes an object data attribute. The description should include
|
||||||
@ -317,6 +341,12 @@ The following directives are provided for module and class contents:
|
|||||||
|
|
||||||
.. versionadded:: 4.0
|
.. versionadded:: 4.0
|
||||||
|
|
||||||
|
.. rst::directive:option:: module
|
||||||
|
:type: text
|
||||||
|
|
||||||
|
Describe the location where the object is defined. The default value is
|
||||||
|
the module specified by :rst:dir:`py:currentmodule`.
|
||||||
|
|
||||||
.. rst:directive:: .. py:property:: name
|
.. rst:directive:: .. py:property:: name
|
||||||
|
|
||||||
Describes an object property.
|
Describes an object property.
|
||||||
@ -340,6 +370,12 @@ The following directives are provided for module and class contents:
|
|||||||
.. rst:directive:option:: type: type of the property
|
.. rst:directive:option:: type: type of the property
|
||||||
:type: text
|
:type: text
|
||||||
|
|
||||||
|
.. rst::directive:option:: module
|
||||||
|
:type: text
|
||||||
|
|
||||||
|
Describe the location where the object is defined. The default value is
|
||||||
|
the module specified by :rst:dir:`py:currentmodule`.
|
||||||
|
|
||||||
.. rst:directive:: .. py:method:: name(parameters)
|
.. rst:directive:: .. py:method:: name(parameters)
|
||||||
|
|
||||||
Describes an object method. The parameters should not include the ``self``
|
Describes an object method. The parameters should not include the ``self``
|
||||||
@ -385,6 +421,12 @@ The following directives are provided for module and class contents:
|
|||||||
|
|
||||||
.. versionadded:: 3.1
|
.. versionadded:: 3.1
|
||||||
|
|
||||||
|
.. rst::directive:option:: module
|
||||||
|
:type: text
|
||||||
|
|
||||||
|
Describe the location where the object is defined. The default value is
|
||||||
|
the module specified by :rst:dir:`py:currentmodule`.
|
||||||
|
|
||||||
.. rst:directive:option:: property
|
.. rst:directive:option:: property
|
||||||
:type: no value
|
:type: no value
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ directory containing :file:`conf.py` and use this configuration::
|
|||||||
The third form is a Python package. If a theme you want to use is distributed
|
The third form is a Python package. If a theme you want to use is distributed
|
||||||
as a Python package, you can use it after installing
|
as a Python package, you can use it after installing
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: console
|
||||||
|
|
||||||
# installing theme package
|
# installing theme package
|
||||||
$ pip install sphinxjp.themes.dotted
|
$ pip install sphinxjp.themes.dotted
|
||||||
@ -158,9 +158,18 @@ These themes are:
|
|||||||
dimension string such as '70em' or '50%'. Use 'none' if you don't
|
dimension string such as '70em' or '50%'. Use 'none' if you don't
|
||||||
want a width limit. Defaults may depend on the theme (often 800px).
|
want a width limit. Defaults may depend on the theme (often 800px).
|
||||||
|
|
||||||
- **navigation_with_keys** (true or false): Allow navigating to the
|
- **navigation_with_keys** (true or false): Allow navigating
|
||||||
previous/next page using the keyboard's left and right arrows. Defaults to
|
with the following keyboard shortcuts:
|
||||||
``False``.
|
|
||||||
|
- :kbd:`Left arrow`: previous page
|
||||||
|
- :kbd:`Right arrow`: next page
|
||||||
|
|
||||||
|
Defaults to ``False``.
|
||||||
|
|
||||||
|
- **enable_search_shortcuts** (true or false): Allow jumping to the search box
|
||||||
|
with :kbd:`/` and allow removal of search highlighting with :kbd:`Esc`.
|
||||||
|
|
||||||
|
Defaults to ``True``.
|
||||||
|
|
||||||
- **globaltoc_collapse** (true or false): Only expand subsections
|
- **globaltoc_collapse** (true or false): Only expand subsections
|
||||||
of the current document in ``globaltoc.html``
|
of the current document in ``globaltoc.html``
|
||||||
|
@ -15,8 +15,6 @@ module.exports = function(config) {
|
|||||||
|
|
||||||
// list of files / patterns to load in the browser
|
// list of files / patterns to load in the browser
|
||||||
files: [
|
files: [
|
||||||
'sphinx/themes/basic/static/underscore.js',
|
|
||||||
'sphinx/themes/basic/static/jquery.js',
|
|
||||||
'sphinx/themes/basic/static/doctools.js',
|
'sphinx/themes/basic/static/doctools.js',
|
||||||
'sphinx/themes/basic/static/searchtools.js',
|
'sphinx/themes/basic/static/searchtools.js',
|
||||||
'tests/js/*.js'
|
'tests/js/*.js'
|
||||||
@ -59,7 +57,7 @@ module.exports = function(config) {
|
|||||||
|
|
||||||
// start these browsers
|
// start these browsers
|
||||||
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
||||||
browsers: ['Chrome', 'Firefox'],
|
browsers: ["Firefox"],
|
||||||
|
|
||||||
|
|
||||||
// Continuous Integration mode
|
// Continuous Integration mode
|
||||||
|
2573
package-lock.json
generated
2573
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -12,9 +12,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"jasmine-core": "^3.4.0",
|
"jasmine-core": "^3.4.0",
|
||||||
"karma": "^4.0.0",
|
"karma": "^6.3.16",
|
||||||
"karma-chrome-launcher": "^3.0.0",
|
"karma-firefox-launcher": "^2.0.0",
|
||||||
"karma-firefox-launcher": "^1.1.0",
|
"karma-jasmine": "^4.0.0"
|
||||||
"karma-jasmine": "^2.0.0"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
license_file = LICENSE
|
license_files = LICENSE
|
||||||
|
|
||||||
[egg_info]
|
[egg_info]
|
||||||
tag_build = .dev
|
tag_build = .dev
|
||||||
@ -35,12 +35,6 @@ import-order-style = smarkets
|
|||||||
per-file-ignores =
|
per-file-ignores =
|
||||||
tests/*: E501
|
tests/*: E501
|
||||||
|
|
||||||
[flake8:local-plugins]
|
|
||||||
extension =
|
|
||||||
X101 = utils.checks:sphinx_has_header
|
|
||||||
paths =
|
|
||||||
.
|
|
||||||
|
|
||||||
[isort]
|
[isort]
|
||||||
line_length = 95
|
line_length = 95
|
||||||
|
|
||||||
|
10
setup.py
10
setup.py
@ -1,6 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
from distutils import log
|
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
from setuptools import find_packages, setup
|
from setuptools import find_packages, setup
|
||||||
@ -29,8 +28,8 @@ install_requires = [
|
|||||||
'alabaster>=0.7,<0.8',
|
'alabaster>=0.7,<0.8',
|
||||||
'imagesize',
|
'imagesize',
|
||||||
'requests>=2.5.0',
|
'requests>=2.5.0',
|
||||||
'setuptools',
|
|
||||||
'packaging',
|
'packaging',
|
||||||
|
"importlib-metadata>=4.4; python_version < '3.10'",
|
||||||
]
|
]
|
||||||
|
|
||||||
extras_require = {
|
extras_require = {
|
||||||
@ -44,10 +43,9 @@ extras_require = {
|
|||||||
'lint': [
|
'lint': [
|
||||||
'flake8>=3.5.0',
|
'flake8>=3.5.0',
|
||||||
'isort',
|
'isort',
|
||||||
'mypy>=0.900',
|
'mypy>=0.931',
|
||||||
'docutils-stubs',
|
'docutils-stubs',
|
||||||
"types-typed-ast",
|
"types-typed-ast",
|
||||||
"types-pkg_resources",
|
|
||||||
"types-requests",
|
"types-requests",
|
||||||
],
|
],
|
||||||
'test': [
|
'test': [
|
||||||
@ -149,8 +147,8 @@ else:
|
|||||||
if catalog.fuzzy and not self.use_fuzzy:
|
if catalog.fuzzy and not self.use_fuzzy:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
log.info('writing JavaScript strings in catalog %r to %r',
|
self.log.info('writing JavaScript strings in catalog %r to %r',
|
||||||
po_file, js_file)
|
po_file, js_file)
|
||||||
|
|
||||||
jscatalog = {}
|
jscatalog = {}
|
||||||
for message in catalog:
|
for message in catalog:
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""The Sphinx documentation toolchain."""
|
||||||
Sphinx
|
|
||||||
~~~~~~
|
|
||||||
|
|
||||||
The Sphinx documentation toolchain.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Keep this file executable as-is in Python 3!
|
# Keep this file executable as-is in Python 3!
|
||||||
# (Otherwise getting the version out of it from setup.py is impossible.)
|
# (Otherwise getting the version out of it from setup.py is impossible.)
|
||||||
@ -27,8 +19,8 @@ if 'PYTHONWARNINGS' not in os.environ:
|
|||||||
warnings.filterwarnings('ignore', "'U' mode is deprecated",
|
warnings.filterwarnings('ignore', "'U' mode is deprecated",
|
||||||
DeprecationWarning, module='docutils.io')
|
DeprecationWarning, module='docutils.io')
|
||||||
|
|
||||||
__version__ = '4.4.0+'
|
__version__ = '5.0.0+'
|
||||||
__released__ = '4.4.0' # used when Sphinx builds its own docs
|
__released__ = '5.0.0' # used when Sphinx builds its own docs
|
||||||
|
|
||||||
#: Version info for better programmatic use.
|
#: Version info for better programmatic use.
|
||||||
#:
|
#:
|
||||||
@ -38,7 +30,7 @@ __released__ = '4.4.0' # used when Sphinx builds its own docs
|
|||||||
#:
|
#:
|
||||||
#: .. versionadded:: 1.2
|
#: .. versionadded:: 1.2
|
||||||
#: Before version 1.2, check the string ``sphinx.__version__``.
|
#: Before version 1.2, check the string ``sphinx.__version__``.
|
||||||
version_info = (4, 4, 0, 'beta', 0)
|
version_info = (5, 0, 0, 'final', 0)
|
||||||
|
|
||||||
package_dir = path.abspath(path.dirname(__file__))
|
package_dir = path.abspath(path.dirname(__file__))
|
||||||
|
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""The Sphinx documentation toolchain."""
|
||||||
sphinx.__main__
|
|
||||||
~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The Sphinx documentation toolchain.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Additional docutils nodes."""
|
||||||
sphinx.addnodes
|
|
||||||
~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Additional docutils nodes.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Any, Dict, List, Sequence
|
from typing import TYPE_CHECKING, Any, Dict, List, Sequence
|
||||||
|
|
||||||
@ -16,6 +8,13 @@ from docutils.nodes import Element
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from sphinx.application import Sphinx
|
from sphinx.application import Sphinx
|
||||||
|
|
||||||
|
try:
|
||||||
|
from docutils.nodes import meta as docutils_meta # type: ignore
|
||||||
|
except ImportError:
|
||||||
|
# docutils-0.17 or older
|
||||||
|
from docutils.parsers.rst.directives.html import MetaBody
|
||||||
|
docutils_meta = MetaBody.meta
|
||||||
|
|
||||||
|
|
||||||
class document(nodes.document):
|
class document(nodes.document):
|
||||||
"""The document root element patched by Sphinx.
|
"""The document root element patched by Sphinx.
|
||||||
@ -85,7 +84,7 @@ class toctree(nodes.General, nodes.Element, translatable):
|
|||||||
def preserve_original_messages(self) -> None:
|
def preserve_original_messages(self) -> None:
|
||||||
# toctree entries
|
# toctree entries
|
||||||
rawentries = self.setdefault('rawentries', [])
|
rawentries = self.setdefault('rawentries', [])
|
||||||
for title, docname in self['entries']:
|
for title, _docname in self['entries']:
|
||||||
if title:
|
if title:
|
||||||
rawentries.append(title)
|
rawentries.append(title)
|
||||||
|
|
||||||
|
@ -1,18 +1,10 @@
|
|||||||
"""
|
"""Sphinx application class and extensibility interface.
|
||||||
sphinx.application
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Sphinx application class and extensibility interface.
|
Gracefully adapted from the TextPress system by Armin.
|
||||||
|
|
||||||
Gracefully adapted from the TextPress system by Armin.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import pickle
|
import pickle
|
||||||
import platform
|
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
from collections import deque
|
from collections import deque
|
||||||
@ -195,12 +187,6 @@ class Sphinx:
|
|||||||
# say hello to the world
|
# say hello to the world
|
||||||
logger.info(bold(__('Running Sphinx v%s') % sphinx.__display_version__))
|
logger.info(bold(__('Running Sphinx v%s') % sphinx.__display_version__))
|
||||||
|
|
||||||
# notice for parallel build on macOS and py38+
|
|
||||||
if sys.version_info > (3, 8) and platform.system() == 'Darwin' and parallel > 1:
|
|
||||||
logger.info(bold(__("For security reasons, parallel mode is disabled on macOS and "
|
|
||||||
"python3.8 and above. For more details, please read "
|
|
||||||
"https://github.com/sphinx-doc/sphinx/issues/6803")))
|
|
||||||
|
|
||||||
# status code for command-line application
|
# status code for command-line application
|
||||||
self.statuscode = 0
|
self.statuscode = 0
|
||||||
|
|
||||||
@ -273,7 +259,7 @@ class Sphinx:
|
|||||||
"""Load translated strings from the configured localedirs if enabled in
|
"""Load translated strings from the configured localedirs if enabled in
|
||||||
the configuration.
|
the configuration.
|
||||||
"""
|
"""
|
||||||
if self.config.language is None:
|
if self.config.language == 'en':
|
||||||
self.translator, has_translation = locale.init([], None)
|
self.translator, has_translation = locale.init([], None)
|
||||||
else:
|
else:
|
||||||
logger.info(bold(__('loading translations [%s]... ') % self.config.language),
|
logger.info(bold(__('loading translations [%s]... ') % self.config.language),
|
||||||
@ -292,8 +278,7 @@ class Sphinx:
|
|||||||
locale_dirs += [path.join(package_dir, 'locale')]
|
locale_dirs += [path.join(package_dir, 'locale')]
|
||||||
|
|
||||||
self.translator, has_translation = locale.init(locale_dirs, self.config.language)
|
self.translator, has_translation = locale.init(locale_dirs, self.config.language)
|
||||||
if has_translation or self.config.language == 'en':
|
if has_translation:
|
||||||
# "en" never needs to be translated
|
|
||||||
logger.info(__('done'))
|
logger.info(__('done'))
|
||||||
else:
|
else:
|
||||||
logger.info(__('not available for built-in messages'))
|
logger.info(__('not available for built-in messages'))
|
||||||
@ -937,24 +922,31 @@ class Sphinx:
|
|||||||
"""
|
"""
|
||||||
self.registry.add_post_transform(transform)
|
self.registry.add_post_transform(transform)
|
||||||
|
|
||||||
def add_js_file(self, filename: str, priority: int = 500, **kwargs: Any) -> None:
|
def add_js_file(self, filename: str, priority: int = 500,
|
||||||
|
loading_method: Optional[str] = None, **kwargs: Any) -> None:
|
||||||
"""Register a JavaScript file to include in the HTML output.
|
"""Register a JavaScript file to include in the HTML output.
|
||||||
|
|
||||||
Add *filename* to the list of JavaScript files that the default HTML
|
:param filename: The filename of the JavaScript file. It must be relative to the HTML
|
||||||
template will include in order of *priority* (ascending). The filename
|
static path, a full URI with scheme, or ``None`` value. The ``None``
|
||||||
must be relative to the HTML static path , or a full URI with scheme.
|
value is used to create inline ``<script>`` tag. See the description
|
||||||
If the priority of the JavaScript file is the same as others, the JavaScript
|
of *kwargs* below.
|
||||||
files will be included in order of registration. If the keyword
|
:param priority: The priority to determine the order of ``<script>`` tag for
|
||||||
argument ``body`` is given, its value will be added between the
|
JavaScript files. See list of "prority range for JavaScript
|
||||||
``<script>`` tags. Extra keyword arguments are included as attributes of
|
files" below. If the priority of the JavaScript files it the same
|
||||||
the ``<script>`` tag.
|
as others, the JavaScript files will be loaded in order of
|
||||||
|
registration.
|
||||||
|
:param loading_method: The loading method of the JavaScript file. ``'async'`` or
|
||||||
|
``'defer'`` is allowed.
|
||||||
|
:param kwargs: Extra keyword arguments are included as attributes of the ``<script>``
|
||||||
|
tag. A special keyword argument ``body`` is given, its value will be
|
||||||
|
added between the ``<script>`` tag.
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
app.add_js_file('example.js')
|
app.add_js_file('example.js')
|
||||||
# => <script src="_static/example.js"></script>
|
# => <script src="_static/example.js"></script>
|
||||||
|
|
||||||
app.add_js_file('example.js', async="async")
|
app.add_js_file('example.js', loading_method="async")
|
||||||
# => <script src="_static/example.js" async="async"></script>
|
# => <script src="_static/example.js" async="async"></script>
|
||||||
|
|
||||||
app.add_js_file(None, body="var myVariable = 'foo';")
|
app.add_js_file(None, body="var myVariable = 'foo';")
|
||||||
@ -983,7 +975,15 @@ class Sphinx:
|
|||||||
|
|
||||||
.. versionchanged:: 3.5
|
.. versionchanged:: 3.5
|
||||||
Take priority argument. Allow to add a JavaScript file to the specific page.
|
Take priority argument. Allow to add a JavaScript file to the specific page.
|
||||||
|
.. versionchanged:: 4.4
|
||||||
|
Take loading_method argument. Allow to change the loading method of the
|
||||||
|
JavaScript file.
|
||||||
"""
|
"""
|
||||||
|
if loading_method == 'async':
|
||||||
|
kwargs['async'] = 'async'
|
||||||
|
elif loading_method == 'defer':
|
||||||
|
kwargs['defer'] = 'defer'
|
||||||
|
|
||||||
self.registry.add_js_file(filename, priority=priority, **kwargs)
|
self.registry.add_js_file(filename, priority=priority, **kwargs)
|
||||||
if hasattr(self.builder, 'add_js_file'):
|
if hasattr(self.builder, 'add_js_file'):
|
||||||
self.builder.add_js_file(filename, priority=priority, **kwargs) # type: ignore
|
self.builder.add_js_file(filename, priority=priority, **kwargs) # type: ignore
|
||||||
@ -991,12 +991,14 @@ class Sphinx:
|
|||||||
def add_css_file(self, filename: str, priority: int = 500, **kwargs: Any) -> None:
|
def add_css_file(self, filename: str, priority: int = 500, **kwargs: Any) -> None:
|
||||||
"""Register a stylesheet to include in the HTML output.
|
"""Register a stylesheet to include in the HTML output.
|
||||||
|
|
||||||
Add *filename* to the list of CSS files that the default HTML template
|
:param filename: The filename of the CSS file. It must be relative to the HTML
|
||||||
will include in order of *priority* (ascending). The filename must be
|
static path, or a full URI with scheme.
|
||||||
relative to the HTML static path, or a full URI with scheme. If the
|
:param priority: The priority to determine the order of ``<link>`` tag for the
|
||||||
priority of the CSS file is the same as others, the CSS files will be
|
CSS files. See list of "prority range for CSS files" below.
|
||||||
included in order of registration. The keyword arguments are also
|
If the priority of the CSS files it the same as others, the
|
||||||
accepted for attributes of ``<link>`` tag.
|
CSS files will be loaded in order of registration.
|
||||||
|
:param kwargs: Extra keyword arguments are included as attributes of the ``<link>``
|
||||||
|
tag.
|
||||||
|
|
||||||
Example::
|
Example::
|
||||||
|
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Builder superclass for all builders."""
|
||||||
sphinx.builders
|
|
||||||
~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Builder superclass for all builders.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import pickle
|
import pickle
|
||||||
import time
|
import time
|
||||||
@ -176,7 +168,7 @@ class Builder:
|
|||||||
def post_process_images(self, doctree: Node) -> None:
|
def post_process_images(self, doctree: Node) -> None:
|
||||||
"""Pick the best candidate for all image URIs."""
|
"""Pick the best candidate for all image URIs."""
|
||||||
images = ImageAdapter(self.env)
|
images = ImageAdapter(self.env)
|
||||||
for node in doctree.traverse(nodes.image):
|
for node in doctree.findall(nodes.image):
|
||||||
if '?' in node['candidates']:
|
if '?' in node['candidates']:
|
||||||
# don't rewrite nonlocal image URIs
|
# don't rewrite nonlocal image URIs
|
||||||
continue
|
continue
|
||||||
@ -562,7 +554,7 @@ class Builder:
|
|||||||
for chunk in status_iterator(chunks, __('writing output... '), "darkgreen",
|
for chunk in status_iterator(chunks, __('writing output... '), "darkgreen",
|
||||||
len(chunks), self.app.verbosity):
|
len(chunks), self.app.verbosity):
|
||||||
arg = []
|
arg = []
|
||||||
for i, docname in enumerate(chunk):
|
for docname in chunk:
|
||||||
doctree = self.env.get_and_resolve_doctree(docname, self)
|
doctree = self.env.get_and_resolve_doctree(docname, self)
|
||||||
self.write_doc_serialized(docname, doctree)
|
self.write_doc_serialized(docname, doctree)
|
||||||
arg.append((docname, doctree))
|
arg.append((docname, doctree))
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Base class of epub2/epub3 builders."""
|
||||||
sphinx.builders._epub_base
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Base class of epub2/epub3 builders.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import html
|
import html
|
||||||
import os
|
import os
|
||||||
@ -277,7 +269,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|||||||
new_ids.append(new_id)
|
new_ids.append(new_id)
|
||||||
node['ids'] = new_ids
|
node['ids'] = new_ids
|
||||||
|
|
||||||
for reference in tree.traverse(nodes.reference):
|
for reference in tree.findall(nodes.reference):
|
||||||
if 'refuri' in reference:
|
if 'refuri' in reference:
|
||||||
m = self.refuri_re.match(reference['refuri'])
|
m = self.refuri_re.match(reference['refuri'])
|
||||||
if m:
|
if m:
|
||||||
@ -285,14 +277,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|||||||
if 'refid' in reference:
|
if 'refid' in reference:
|
||||||
reference['refid'] = self.fix_fragment('', reference['refid'])
|
reference['refid'] = self.fix_fragment('', reference['refid'])
|
||||||
|
|
||||||
for target in tree.traverse(nodes.target):
|
for target in tree.findall(nodes.target):
|
||||||
update_node_id(target)
|
update_node_id(target)
|
||||||
|
|
||||||
next_node: Node = target.next_node(ascend=True)
|
next_node: Node = target.next_node(ascend=True)
|
||||||
if isinstance(next_node, nodes.Element):
|
if isinstance(next_node, nodes.Element):
|
||||||
update_node_id(next_node)
|
update_node_id(next_node)
|
||||||
|
|
||||||
for desc_signature in tree.traverse(addnodes.desc_signature):
|
for desc_signature in tree.findall(addnodes.desc_signature):
|
||||||
update_node_id(desc_signature)
|
update_node_id(desc_signature)
|
||||||
|
|
||||||
def add_visible_links(self, tree: nodes.document, show_urls: str = 'inline') -> None:
|
def add_visible_links(self, tree: nodes.document, show_urls: str = 'inline') -> None:
|
||||||
@ -323,14 +315,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|||||||
# a) place them after the last existing footnote
|
# a) place them after the last existing footnote
|
||||||
# b) place them after an (empty) Footnotes rubric
|
# b) place them after an (empty) Footnotes rubric
|
||||||
# c) create an empty Footnotes rubric at the end of the document
|
# c) create an empty Footnotes rubric at the end of the document
|
||||||
fns = list(tree.traverse(nodes.footnote))
|
fns = list(tree.findall(nodes.footnote))
|
||||||
if fns:
|
if fns:
|
||||||
fn = fns[-1]
|
fn = fns[-1]
|
||||||
return fn.parent, fn.parent.index(fn) + 1
|
return fn.parent, fn.parent.index(fn) + 1
|
||||||
for node in tree.traverse(nodes.rubric):
|
for node in tree.findall(nodes.rubric):
|
||||||
if len(node) == 1 and node.astext() == FOOTNOTES_RUBRIC_NAME:
|
if len(node) == 1 and node.astext() == FOOTNOTES_RUBRIC_NAME:
|
||||||
return node.parent, node.parent.index(node) + 1
|
return node.parent, node.parent.index(node) + 1
|
||||||
doc = list(tree.traverse(nodes.document))[0]
|
doc = next(tree.findall(nodes.document))
|
||||||
rub = nodes.rubric()
|
rub = nodes.rubric()
|
||||||
rub.append(nodes.Text(FOOTNOTES_RUBRIC_NAME))
|
rub.append(nodes.Text(FOOTNOTES_RUBRIC_NAME))
|
||||||
doc.append(rub)
|
doc.append(rub)
|
||||||
@ -339,10 +331,10 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|||||||
if show_urls == 'no':
|
if show_urls == 'no':
|
||||||
return
|
return
|
||||||
if show_urls == 'footnote':
|
if show_urls == 'footnote':
|
||||||
doc = list(tree.traverse(nodes.document))[0]
|
doc = next(tree.findall(nodes.document))
|
||||||
fn_spot, fn_idx = footnote_spot(tree)
|
fn_spot, fn_idx = footnote_spot(tree)
|
||||||
nr = 1
|
nr = 1
|
||||||
for node in list(tree.traverse(nodes.reference)):
|
for node in list(tree.findall(nodes.reference)):
|
||||||
uri = node.get('refuri', '')
|
uri = node.get('refuri', '')
|
||||||
if (uri.startswith('http:') or uri.startswith('https:') or
|
if (uri.startswith('http:') or uri.startswith('https:') or
|
||||||
uri.startswith('ftp:')) and uri not in node.astext():
|
uri.startswith('ftp:')) and uri not in node.astext():
|
||||||
@ -377,14 +369,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|||||||
"""Fix href attributes for genindex pages."""
|
"""Fix href attributes for genindex pages."""
|
||||||
# XXX: modifies tree inline
|
# XXX: modifies tree inline
|
||||||
# Logic modeled from themes/basic/genindex.html
|
# Logic modeled from themes/basic/genindex.html
|
||||||
for key, columns in tree:
|
for _key, columns in tree:
|
||||||
for entryname, (links, subitems, key_) in columns:
|
for _entryname, (links, subitems, _key) in columns:
|
||||||
for (i, (ismain, link)) in enumerate(links):
|
for (i, (ismain, link)) in enumerate(links):
|
||||||
m = self.refuri_re.match(link)
|
m = self.refuri_re.match(link)
|
||||||
if m:
|
if m:
|
||||||
links[i] = (ismain,
|
links[i] = (ismain,
|
||||||
self.fix_fragment(m.group(1), m.group(2)))
|
self.fix_fragment(m.group(1), m.group(2)))
|
||||||
for subentryname, subentrylinks in subitems:
|
for _subentryname, subentrylinks in subitems:
|
||||||
for (i, (ismain, link)) in enumerate(subentrylinks):
|
for (i, (ismain, link)) in enumerate(subentrylinks):
|
||||||
m = self.refuri_re.match(link)
|
m = self.refuri_re.match(link)
|
||||||
if m:
|
if m:
|
||||||
@ -703,7 +695,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|||||||
epub_filename = path.join(self.outdir, outname)
|
epub_filename = path.join(self.outdir, outname)
|
||||||
with ZipFile(epub_filename, 'w', ZIP_DEFLATED) as epub:
|
with ZipFile(epub_filename, 'w', ZIP_DEFLATED) as epub:
|
||||||
epub.write(path.join(self.outdir, 'mimetype'), 'mimetype', ZIP_STORED)
|
epub.write(path.join(self.outdir, 'mimetype'), 'mimetype', ZIP_STORED)
|
||||||
for filename in ['META-INF/container.xml', 'content.opf', 'toc.ncx']:
|
for filename in ('META-INF/container.xml', 'content.opf', 'toc.ncx'):
|
||||||
epub.write(path.join(self.outdir, filename), filename, ZIP_DEFLATED)
|
epub.write(path.join(self.outdir, filename), filename, ZIP_DEFLATED)
|
||||||
for filename in self.files:
|
for filename in self.files:
|
||||||
epub.write(path.join(self.outdir, filename), filename, ZIP_DEFLATED)
|
epub.write(path.join(self.outdir, filename), filename, ZIP_DEFLATED)
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Changelog builder."""
|
||||||
sphinx.builders.changes
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Changelog builder.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import html
|
import html
|
||||||
from os import path
|
from os import path
|
||||||
@ -148,7 +140,7 @@ class ChangesBuilder(Builder):
|
|||||||
|
|
||||||
def hl(self, text: str, version: str) -> str:
|
def hl(self, text: str, version: str) -> str:
|
||||||
text = html.escape(text)
|
text = html.escape(text)
|
||||||
for directive in ['versionchanged', 'versionadded', 'deprecated']:
|
for directive in ('versionchanged', 'versionadded', 'deprecated'):
|
||||||
text = text.replace('.. %s:: %s' % (directive, version),
|
text = text.replace('.. %s:: %s' % (directive, version),
|
||||||
'<b>.. %s:: %s</b>' % (directive, version))
|
'<b>.. %s:: %s</b>' % (directive, version))
|
||||||
return text
|
return text
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Directory HTML builders."""
|
||||||
sphinx.builders.dirhtml
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Directory HTML builders.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Do syntax checks, but no writing."""
|
||||||
sphinx.builders.dummy
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Do syntax checks, but no writing.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import Any, Dict, Set
|
from typing import Any, Dict, Set
|
||||||
|
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
"""
|
"""Build epub3 files.
|
||||||
sphinx.builders.epub3
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Build epub3 files.
|
Originally derived from epub.py.
|
||||||
Originally derived from epub.py.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import html
|
import html
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""The MessageCatalogBuilder class."""
|
||||||
sphinx.builders.gettext
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The MessageCatalogBuilder class.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from codecs import open
|
from codecs import open
|
||||||
from collections import OrderedDict, defaultdict
|
from collections import OrderedDict, defaultdict
|
||||||
@ -146,7 +138,7 @@ class I18nBuilder(Builder):
|
|||||||
def write_doc(self, docname: str, doctree: nodes.document) -> None:
|
def write_doc(self, docname: str, doctree: nodes.document) -> None:
|
||||||
catalog = self.catalogs[docname_to_domain(docname, self.config.gettext_compact)]
|
catalog = self.catalogs[docname_to_domain(docname, self.config.gettext_compact)]
|
||||||
|
|
||||||
for toctree in self.env.tocs[docname].traverse(addnodes.toctree):
|
for toctree in self.env.tocs[docname].findall(addnodes.toctree):
|
||||||
for node, msg in extract_messages(toctree):
|
for node, msg in extract_messages(toctree):
|
||||||
node.uid = '' # type: ignore # Hack UUID model
|
node.uid = '' # type: ignore # Hack UUID model
|
||||||
catalog.add(msg, node)
|
catalog.add(msg, node)
|
||||||
@ -157,7 +149,7 @@ class I18nBuilder(Builder):
|
|||||||
if 'index' in self.env.config.gettext_additional_targets:
|
if 'index' in self.env.config.gettext_additional_targets:
|
||||||
# Extract translatable messages from index entries.
|
# Extract translatable messages from index entries.
|
||||||
for node, entries in traverse_translatable_index(doctree):
|
for node, entries in traverse_translatable_index(doctree):
|
||||||
for typ, msg, tid, main, key_ in entries:
|
for typ, msg, _tid, _main, _key in entries:
|
||||||
for m in split_index_msg(typ, msg):
|
for m in split_index_msg(typ, msg):
|
||||||
if typ == 'pair' and m in pairindextypes.values():
|
if typ == 'pair' and m in pairindextypes.values():
|
||||||
# avoid built-in translated message was incorporated
|
# avoid built-in translated message was incorporated
|
||||||
@ -180,7 +172,7 @@ if source_date_epoch is not None:
|
|||||||
|
|
||||||
class LocalTimeZone(tzinfo):
|
class LocalTimeZone(tzinfo):
|
||||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||||
super().__init__(*args, **kwargs) # type: ignore
|
super().__init__(*args, **kwargs)
|
||||||
self.tzdelta = tzdelta
|
self.tzdelta = tzdelta
|
||||||
|
|
||||||
def utcoffset(self, dt: datetime) -> timedelta:
|
def utcoffset(self, dt: datetime) -> timedelta:
|
||||||
@ -227,7 +219,7 @@ class MessageCatalogBuilder(I18nBuilder):
|
|||||||
template_files = set()
|
template_files = set()
|
||||||
for template_path in self.config.templates_path:
|
for template_path in self.config.templates_path:
|
||||||
tmpl_abs_path = path.join(self.app.srcdir, template_path)
|
tmpl_abs_path = path.join(self.app.srcdir, template_path)
|
||||||
for dirpath, dirs, files in walk(tmpl_abs_path):
|
for dirpath, _dirs, files in walk(tmpl_abs_path):
|
||||||
for fn in files:
|
for fn in files:
|
||||||
if fn.endswith('.html'):
|
if fn.endswith('.html'):
|
||||||
filename = canon_path(path.join(dirpath, fn))
|
filename = canon_path(path.join(dirpath, fn))
|
||||||
@ -247,7 +239,7 @@ class MessageCatalogBuilder(I18nBuilder):
|
|||||||
try:
|
try:
|
||||||
with open(template, encoding='utf-8') as f:
|
with open(template, encoding='utf-8') as f:
|
||||||
context = f.read()
|
context = f.read()
|
||||||
for line, meth, msg in extract_translations(context):
|
for line, _meth, msg in extract_translations(context):
|
||||||
origin = MsgOrigin(template, line)
|
origin = MsgOrigin(template, line)
|
||||||
self.catalogs['sphinx'].add(msg, origin)
|
self.catalogs['sphinx'].add(msg, origin)
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Several HTML builders."""
|
||||||
sphinx.builders.html
|
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Several HTML builders.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import html
|
import html
|
||||||
import os
|
import os
|
||||||
@ -15,7 +7,7 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from os import path
|
from os import path
|
||||||
from typing import IO, Any, Dict, Iterable, Iterator, List, Set, Tuple, Type
|
from typing import IO, Any, Dict, Iterable, Iterator, List, Optional, Set, Tuple, Type
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
@ -76,6 +68,17 @@ def get_stable_hash(obj: Any) -> str:
|
|||||||
return md5(str(obj).encode()).hexdigest()
|
return md5(str(obj).encode()).hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def convert_locale_to_language_tag(locale: Optional[str]) -> Optional[str]:
|
||||||
|
"""Convert a locale string to a language tag (ex. en_US -> en-US).
|
||||||
|
|
||||||
|
refs: BCP 47 (:rfc:`5646`)
|
||||||
|
"""
|
||||||
|
if locale:
|
||||||
|
return locale.replace('_', '-')
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class Stylesheet(str):
|
class Stylesheet(str):
|
||||||
"""A metadata of stylesheet.
|
"""A metadata of stylesheet.
|
||||||
|
|
||||||
@ -315,8 +318,11 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
self.script_files = []
|
self.script_files = []
|
||||||
self.add_js_file('documentation_options.js', id="documentation_options",
|
self.add_js_file('documentation_options.js', id="documentation_options",
|
||||||
data_url_root='', priority=200)
|
data_url_root='', priority=200)
|
||||||
|
# Remove frameworks and compatability module below in Sphinx 6.0
|
||||||
|
# xref RemovedInSphinx60Warning
|
||||||
self.add_js_file('jquery.js', priority=200)
|
self.add_js_file('jquery.js', priority=200)
|
||||||
self.add_js_file('underscore.js', priority=200)
|
self.add_js_file('underscore.js', priority=200)
|
||||||
|
self.add_js_file('_sphinx_javascript_frameworks_compat.js', priority=200)
|
||||||
self.add_js_file('doctools.js', priority=200)
|
self.add_js_file('doctools.js', priority=200)
|
||||||
|
|
||||||
for filename, attrs in self.app.registry.js_files:
|
for filename, attrs in self.app.registry.js_files:
|
||||||
@ -326,7 +332,7 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
attrs.setdefault('priority', 800) # User's JSs are loaded after extensions'
|
attrs.setdefault('priority', 800) # User's JSs are loaded after extensions'
|
||||||
self.add_js_file(filename, **attrs)
|
self.add_js_file(filename, **attrs)
|
||||||
|
|
||||||
if self.config.language and self._get_translations_js():
|
if self._get_translations_js():
|
||||||
self.add_js_file('translations.js')
|
self.add_js_file('translations.js')
|
||||||
|
|
||||||
def add_js_file(self, filename: str, **kwargs: Any) -> None:
|
def add_js_file(self, filename: str, **kwargs: Any) -> None:
|
||||||
@ -431,8 +437,6 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
if self.search:
|
if self.search:
|
||||||
from sphinx.search import IndexBuilder
|
from sphinx.search import IndexBuilder
|
||||||
lang = self.config.html_search_language or self.config.language
|
lang = self.config.html_search_language or self.config.language
|
||||||
if not lang:
|
|
||||||
lang = 'en'
|
|
||||||
self.indexer = IndexBuilder(self.env, lang,
|
self.indexer = IndexBuilder(self.env, lang,
|
||||||
self.config.html_search_options,
|
self.config.html_search_options,
|
||||||
self.config.html_search_scorer)
|
self.config.html_search_scorer)
|
||||||
@ -486,7 +490,7 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
rellinks: List[Tuple[str, str, str, str]] = []
|
rellinks: List[Tuple[str, str, str, str]] = []
|
||||||
if self.use_index:
|
if self.use_index:
|
||||||
rellinks.append(('genindex', _('General Index'), 'I', _('index')))
|
rellinks.append(('genindex', _('General Index'), 'I', _('index')))
|
||||||
for indexname, indexcls, content, collapse in self.domain_indices:
|
for indexname, indexcls, _content, _collapse in self.domain_indices:
|
||||||
# if it has a short name
|
# if it has a short name
|
||||||
if indexcls.shortname:
|
if indexcls.shortname:
|
||||||
rellinks.append((indexname, indexcls.localname,
|
rellinks.append((indexname, indexcls.localname,
|
||||||
@ -509,6 +513,7 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
'docstitle': self.config.html_title,
|
'docstitle': self.config.html_title,
|
||||||
'shorttitle': self.config.html_short_title,
|
'shorttitle': self.config.html_short_title,
|
||||||
'show_copyright': self.config.html_show_copyright,
|
'show_copyright': self.config.html_show_copyright,
|
||||||
|
'show_search_summary': self.config.html_show_search_summary,
|
||||||
'show_sphinx': self.config.html_show_sphinx,
|
'show_sphinx': self.config.html_show_sphinx,
|
||||||
'has_source': self.config.html_copy_source,
|
'has_source': self.config.html_copy_source,
|
||||||
'show_source': self.config.html_show_sourcelink,
|
'show_source': self.config.html_show_sourcelink,
|
||||||
@ -516,7 +521,7 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
'file_suffix': self.out_suffix,
|
'file_suffix': self.out_suffix,
|
||||||
'link_suffix': self.link_suffix,
|
'link_suffix': self.link_suffix,
|
||||||
'script_files': self.script_files,
|
'script_files': self.script_files,
|
||||||
'language': self.config.language,
|
'language': convert_locale_to_language_tag(self.config.language),
|
||||||
'css_files': self.css_files,
|
'css_files': self.css_files,
|
||||||
'sphinx_version': __display_version__,
|
'sphinx_version': __display_version__,
|
||||||
'sphinx_version_tuple': sphinx_version,
|
'sphinx_version_tuple': sphinx_version,
|
||||||
@ -767,10 +772,9 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
|
|
||||||
def copy_translation_js(self) -> None:
|
def copy_translation_js(self) -> None:
|
||||||
"""Copy a JavaScript file for translations."""
|
"""Copy a JavaScript file for translations."""
|
||||||
if self.config.language is not None:
|
jsfile = self._get_translations_js()
|
||||||
jsfile = self._get_translations_js()
|
if jsfile:
|
||||||
if jsfile:
|
copyfile(jsfile, path.join(self.outdir, '_static', 'translations.js'))
|
||||||
copyfile(jsfile, path.join(self.outdir, '_static', 'translations.js'))
|
|
||||||
|
|
||||||
def copy_stemmer_js(self) -> None:
|
def copy_stemmer_js(self) -> None:
|
||||||
"""Copy a JavaScript file for stemmer."""
|
"""Copy a JavaScript file for stemmer."""
|
||||||
@ -866,7 +870,7 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
Builder.post_process_images(self, doctree)
|
Builder.post_process_images(self, doctree)
|
||||||
|
|
||||||
if self.config.html_scaled_image_link and self.html_scaled_image_link:
|
if self.config.html_scaled_image_link and self.html_scaled_image_link:
|
||||||
for node in doctree.traverse(nodes.image):
|
for node in doctree.findall(nodes.image):
|
||||||
if not any((key in node) for key in ['scale', 'width', 'height']):
|
if not any((key in node) for key in ['scale', 'width', 'height']):
|
||||||
# resizing options are not given. scaled image link is available
|
# resizing options are not given. scaled image link is available
|
||||||
# only for resized images.
|
# only for resized images.
|
||||||
@ -1340,6 +1344,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
|
|||||||
app.add_config_value('html_file_suffix', None, 'html', [str])
|
app.add_config_value('html_file_suffix', None, 'html', [str])
|
||||||
app.add_config_value('html_link_suffix', None, 'html', [str])
|
app.add_config_value('html_link_suffix', None, 'html', [str])
|
||||||
app.add_config_value('html_show_copyright', True, 'html')
|
app.add_config_value('html_show_copyright', True, 'html')
|
||||||
|
app.add_config_value('html_show_search_summary', True, 'html')
|
||||||
app.add_config_value('html_show_sphinx', True, 'html')
|
app.add_config_value('html_show_sphinx', True, 'html')
|
||||||
app.add_config_value('html_context', {}, 'html')
|
app.add_config_value('html_context', {}, 'html')
|
||||||
app.add_config_value('html_output_encoding', 'utf-8', 'html')
|
app.add_config_value('html_output_encoding', 'utf-8', 'html')
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Transforms for HTML builder."""
|
||||||
sphinx.builders.html.transforms
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Transforms for HTML builder.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import Any, Dict, List
|
from typing import Any, Dict, List
|
||||||
@ -36,7 +28,7 @@ class KeyboardTransform(SphinxPostTransform):
|
|||||||
x
|
x
|
||||||
"""
|
"""
|
||||||
default_priority = 400
|
default_priority = 400
|
||||||
builders = ('html',)
|
formats = ('html',)
|
||||||
pattern = re.compile(r'(?<=.)(-|\+|\^|\s+)(?=.)')
|
pattern = re.compile(r'(?<=.)(-|\+|\^|\s+)(?=.)')
|
||||||
multiwords_keys = (('caps', 'lock'),
|
multiwords_keys = (('caps', 'lock'),
|
||||||
('page' 'down'),
|
('page' 'down'),
|
||||||
@ -48,7 +40,7 @@ class KeyboardTransform(SphinxPostTransform):
|
|||||||
|
|
||||||
def run(self, **kwargs: Any) -> None:
|
def run(self, **kwargs: Any) -> None:
|
||||||
matcher = NodeMatcher(nodes.literal, classes=["kbd"])
|
matcher = NodeMatcher(nodes.literal, classes=["kbd"])
|
||||||
for node in self.document.traverse(matcher): # type: nodes.literal
|
for node in self.document.findall(matcher): # type: nodes.literal
|
||||||
parts = self.pattern.split(node[-1].astext())
|
parts = self.pattern.split(node[-1].astext())
|
||||||
if len(parts) == 1 or self.is_multiwords_key(parts):
|
if len(parts) == 1 or self.is_multiwords_key(parts):
|
||||||
continue
|
continue
|
||||||
|
@ -1,15 +1,6 @@
|
|||||||
"""
|
"""LaTeX builder."""
|
||||||
sphinx.builders.latex
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
LaTeX builder.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import warnings
|
|
||||||
from os import path
|
from os import path
|
||||||
from typing import Any, Dict, Iterable, List, Tuple, Union
|
from typing import Any, Dict, Iterable, List, Tuple, Union
|
||||||
|
|
||||||
@ -24,7 +15,6 @@ from sphinx.builders.latex.constants import ADDITIONAL_SETTINGS, DEFAULT_SETTING
|
|||||||
from sphinx.builders.latex.theming import Theme, ThemeFactory
|
from sphinx.builders.latex.theming import Theme, ThemeFactory
|
||||||
from sphinx.builders.latex.util import ExtBabel
|
from sphinx.builders.latex.util import ExtBabel
|
||||||
from sphinx.config import ENUM, Config
|
from sphinx.config import ENUM, Config
|
||||||
from sphinx.deprecation import RemovedInSphinx50Warning
|
|
||||||
from sphinx.environment.adapters.asset import ImageAdapter
|
from sphinx.environment.adapters.asset import ImageAdapter
|
||||||
from sphinx.errors import NoUri, SphinxError
|
from sphinx.errors import NoUri, SphinxError
|
||||||
from sphinx.locale import _, __
|
from sphinx.locale import _, __
|
||||||
@ -172,9 +162,8 @@ class LaTeXBuilder(Builder):
|
|||||||
self.context.update(ADDITIONAL_SETTINGS.get(self.config.latex_engine, {}))
|
self.context.update(ADDITIONAL_SETTINGS.get(self.config.latex_engine, {}))
|
||||||
|
|
||||||
# Add special settings for (latex_engine, language_code)
|
# Add special settings for (latex_engine, language_code)
|
||||||
if self.config.language:
|
key = (self.config.latex_engine, self.config.language[:2])
|
||||||
key = (self.config.latex_engine, self.config.language[:2])
|
self.context.update(ADDITIONAL_SETTINGS.get(key, {}))
|
||||||
self.context.update(ADDITIONAL_SETTINGS.get(key, {}))
|
|
||||||
|
|
||||||
# Apply user settings to context
|
# Apply user settings to context
|
||||||
self.context.update(self.config.latex_elements)
|
self.context.update(self.config.latex_elements)
|
||||||
@ -205,7 +194,7 @@ class LaTeXBuilder(Builder):
|
|||||||
|
|
||||||
def init_babel(self) -> None:
|
def init_babel(self) -> None:
|
||||||
self.babel = ExtBabel(self.config.language, not self.context['babel'])
|
self.babel = ExtBabel(self.config.language, not self.context['babel'])
|
||||||
if self.config.language and not self.babel.is_supported_language():
|
if not self.babel.is_supported_language():
|
||||||
# emit warning if specified language is invalid
|
# emit warning if specified language is invalid
|
||||||
# (only emitting, nothing changed to processing)
|
# (only emitting, nothing changed to processing)
|
||||||
logger.warning(__('no Babel option known for language %r'),
|
logger.warning(__('no Babel option known for language %r'),
|
||||||
@ -234,12 +223,11 @@ class LaTeXBuilder(Builder):
|
|||||||
self.context['classoptions'] += ',' + self.babel.get_language()
|
self.context['classoptions'] += ',' + self.babel.get_language()
|
||||||
# this branch is not taken for xelatex/lualatex if default settings
|
# this branch is not taken for xelatex/lualatex if default settings
|
||||||
self.context['multilingual'] = self.context['babel']
|
self.context['multilingual'] = self.context['babel']
|
||||||
if self.config.language:
|
self.context['shorthandoff'] = SHORTHANDOFF
|
||||||
self.context['shorthandoff'] = SHORTHANDOFF
|
|
||||||
|
|
||||||
# Times fonts don't work with Cyrillic languages
|
# Times fonts don't work with Cyrillic languages
|
||||||
if self.babel.uses_cyrillic() and 'fontpkg' not in self.config.latex_elements:
|
if self.babel.uses_cyrillic() and 'fontpkg' not in self.config.latex_elements:
|
||||||
self.context['fontpkg'] = ''
|
self.context['fontpkg'] = ''
|
||||||
elif self.context['polyglossia']:
|
elif self.context['polyglossia']:
|
||||||
self.context['classoptions'] += ',' + self.babel.get_language()
|
self.context['classoptions'] += ',' + self.babel.get_language()
|
||||||
options = self.babel.get_mainlanguage_options()
|
options = self.babel.get_mainlanguage_options()
|
||||||
@ -280,7 +268,7 @@ class LaTeXBuilder(Builder):
|
|||||||
encoding='utf-8', overwrite_if_changed=True)
|
encoding='utf-8', overwrite_if_changed=True)
|
||||||
with progress_message(__("processing %s") % targetname):
|
with progress_message(__("processing %s") % targetname):
|
||||||
doctree = self.env.get_doctree(docname)
|
doctree = self.env.get_doctree(docname)
|
||||||
toctree = next(iter(doctree.traverse(addnodes.toctree)), None)
|
toctree = next(doctree.findall(addnodes.toctree), None)
|
||||||
if toctree and toctree.get('maxdepth') > 0:
|
if toctree and toctree.get('maxdepth') > 0:
|
||||||
tocdepth = toctree.get('maxdepth')
|
tocdepth = toctree.get('maxdepth')
|
||||||
else:
|
else:
|
||||||
@ -310,7 +298,7 @@ class LaTeXBuilder(Builder):
|
|||||||
def get_contentsname(self, indexfile: str) -> str:
|
def get_contentsname(self, indexfile: str) -> str:
|
||||||
tree = self.env.get_doctree(indexfile)
|
tree = self.env.get_doctree(indexfile)
|
||||||
contentsname = None
|
contentsname = None
|
||||||
for toctree in tree.traverse(addnodes.toctree):
|
for toctree in tree.findall(addnodes.toctree):
|
||||||
if 'caption' in toctree:
|
if 'caption' in toctree:
|
||||||
contentsname = toctree['caption']
|
contentsname = toctree['caption']
|
||||||
break
|
break
|
||||||
@ -338,7 +326,7 @@ class LaTeXBuilder(Builder):
|
|||||||
new_sect += nodes.title('<Set title in conf.py>',
|
new_sect += nodes.title('<Set title in conf.py>',
|
||||||
'<Set title in conf.py>')
|
'<Set title in conf.py>')
|
||||||
new_tree += new_sect
|
new_tree += new_sect
|
||||||
for node in tree.traverse(addnodes.toctree):
|
for node in tree.findall(addnodes.toctree):
|
||||||
new_sect += node
|
new_sect += node
|
||||||
tree = new_tree
|
tree = new_tree
|
||||||
largetree = inline_all_toctrees(self, self.docnames, indexfile, tree,
|
largetree = inline_all_toctrees(self, self.docnames, indexfile, tree,
|
||||||
@ -353,7 +341,7 @@ class LaTeXBuilder(Builder):
|
|||||||
self.env.resolve_references(largetree, indexfile, self)
|
self.env.resolve_references(largetree, indexfile, self)
|
||||||
# resolve :ref:s to distant tex files -- we can't add a cross-reference,
|
# resolve :ref:s to distant tex files -- we can't add a cross-reference,
|
||||||
# but append the document name
|
# but append the document name
|
||||||
for pendingnode in largetree.traverse(addnodes.pending_xref):
|
for pendingnode in largetree.findall(addnodes.pending_xref):
|
||||||
docname = pendingnode['refdocname']
|
docname = pendingnode['refdocname']
|
||||||
sectname = pendingnode['refsectname']
|
sectname = pendingnode['refsectname']
|
||||||
newnodes: List[Node] = [nodes.emphasis(sectname, sectname)]
|
newnodes: List[Node] = [nodes.emphasis(sectname, sectname)]
|
||||||
@ -382,14 +370,10 @@ class LaTeXBuilder(Builder):
|
|||||||
# configure usage of xindy (impacts Makefile and latexmkrc)
|
# configure usage of xindy (impacts Makefile and latexmkrc)
|
||||||
# FIXME: convert this rather to a confval with suitable default
|
# FIXME: convert this rather to a confval with suitable default
|
||||||
# according to language ? but would require extra documentation
|
# according to language ? but would require extra documentation
|
||||||
if self.config.language:
|
xindy_lang_option = XINDY_LANG_OPTIONS.get(self.config.language[:2],
|
||||||
xindy_lang_option = \
|
'-L general -C utf8 ')
|
||||||
XINDY_LANG_OPTIONS.get(self.config.language[:2],
|
xindy_cyrillic = self.config.language[:2] in XINDY_CYRILLIC_SCRIPTS
|
||||||
'-L general -C utf8 ')
|
|
||||||
xindy_cyrillic = self.config.language[:2] in XINDY_CYRILLIC_SCRIPTS
|
|
||||||
else:
|
|
||||||
xindy_lang_option = '-L english -C utf8 '
|
|
||||||
xindy_cyrillic = False
|
|
||||||
context = {
|
context = {
|
||||||
'latex_engine': self.config.latex_engine,
|
'latex_engine': self.config.latex_engine,
|
||||||
'xindy_use': self.config.latex_use_xindy,
|
'xindy_use': self.config.latex_use_xindy,
|
||||||
@ -449,18 +433,6 @@ class LaTeXBuilder(Builder):
|
|||||||
filename = path.join(package_dir, 'templates', 'latex', 'sphinxmessages.sty_t')
|
filename = path.join(package_dir, 'templates', 'latex', 'sphinxmessages.sty_t')
|
||||||
copy_asset_file(filename, self.outdir, context=context, renderer=LaTeXRenderer())
|
copy_asset_file(filename, self.outdir, context=context, renderer=LaTeXRenderer())
|
||||||
|
|
||||||
@property
|
|
||||||
def usepackages(self) -> List[Tuple[str, str]]:
|
|
||||||
warnings.warn('LaTeXBuilder.usepackages is deprecated.',
|
|
||||||
RemovedInSphinx50Warning, stacklevel=2)
|
|
||||||
return self.app.registry.latex_packages
|
|
||||||
|
|
||||||
@property
|
|
||||||
def usepackages_after_hyperref(self) -> List[Tuple[str, str]]:
|
|
||||||
warnings.warn('LaTeXBuilder.usepackages_after_hyperref is deprecated.',
|
|
||||||
RemovedInSphinx50Warning, stacklevel=2)
|
|
||||||
return self.app.registry.latex_packages_after_hyperref
|
|
||||||
|
|
||||||
|
|
||||||
def validate_config_values(app: Sphinx, config: Config) -> None:
|
def validate_config_values(app: Sphinx, config: Config) -> None:
|
||||||
for key in list(config.latex_elements):
|
for key in list(config.latex_elements):
|
||||||
@ -488,7 +460,7 @@ def default_latex_engine(config: Config) -> str:
|
|||||||
""" Better default latex_engine settings for specific languages. """
|
""" Better default latex_engine settings for specific languages. """
|
||||||
if config.language == 'ja':
|
if config.language == 'ja':
|
||||||
return 'uplatex'
|
return 'uplatex'
|
||||||
elif (config.language or '').startswith('zh'):
|
elif config.language.startswith('zh'):
|
||||||
return 'xelatex'
|
return 'xelatex'
|
||||||
elif config.language == 'el':
|
elif config.language == 'el':
|
||||||
return 'xelatex'
|
return 'xelatex'
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""consntants for LaTeX builder."""
|
||||||
sphinx.builders.latex.constants
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
consntants for LaTeX builder.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Additional nodes for LaTeX writer."""
|
||||||
sphinx.builders.latex.nodes
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Additional nodes for LaTeX writer.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
|
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Theming support for LaTeX builder."""
|
||||||
sphinx.builders.latex.theming
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Theming support for LaTeX builder.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import configparser
|
import configparser
|
||||||
from os import path
|
from os import path
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Transforms for LaTeX builder."""
|
||||||
sphinx.builders.latex.transforms
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Transforms for LaTeX builder.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import Any, Dict, List, Set, Tuple, cast
|
from typing import Any, Dict, List, Set, Tuple, cast
|
||||||
|
|
||||||
@ -33,7 +25,7 @@ class FootnoteDocnameUpdater(SphinxTransform):
|
|||||||
|
|
||||||
def apply(self, **kwargs: Any) -> None:
|
def apply(self, **kwargs: Any) -> None:
|
||||||
matcher = NodeMatcher(*self.TARGET_NODES)
|
matcher = NodeMatcher(*self.TARGET_NODES)
|
||||||
for node in self.document.traverse(matcher): # type: Element
|
for node in self.document.findall(matcher): # type: Element
|
||||||
node['docname'] = self.env.docname
|
node['docname'] = self.env.docname
|
||||||
|
|
||||||
|
|
||||||
@ -45,7 +37,7 @@ class SubstitutionDefinitionsRemover(SphinxPostTransform):
|
|||||||
formats = ('latex',)
|
formats = ('latex',)
|
||||||
|
|
||||||
def run(self, **kwargs: Any) -> None:
|
def run(self, **kwargs: Any) -> None:
|
||||||
for node in list(self.document.traverse(nodes.substitution_definition)):
|
for node in list(self.document.findall(nodes.substitution_definition)):
|
||||||
node.parent.remove(node)
|
node.parent.remove(node)
|
||||||
|
|
||||||
|
|
||||||
@ -81,7 +73,7 @@ class ShowUrlsTransform(SphinxPostTransform):
|
|||||||
if show_urls is False or show_urls == 'no':
|
if show_urls is False or show_urls == 'no':
|
||||||
return
|
return
|
||||||
|
|
||||||
for node in list(self.document.traverse(nodes.reference)):
|
for node in list(self.document.findall(nodes.reference)):
|
||||||
uri = node.get('refuri', '')
|
uri = node.get('refuri', '')
|
||||||
if uri.startswith(URI_SCHEMES):
|
if uri.startswith(URI_SCHEMES):
|
||||||
if uri.startswith('mailto:'):
|
if uri.startswith('mailto:'):
|
||||||
@ -237,7 +229,8 @@ class LaTeXFootnoteTransform(SphinxPostTransform):
|
|||||||
blah blah blah ...
|
blah blah blah ...
|
||||||
|
|
||||||
* Replace second and subsequent footnote references which refers same footnote definition
|
* Replace second and subsequent footnote references which refers same footnote definition
|
||||||
by footnotemark node.
|
by footnotemark node. Additionally, the footnote definition node is marked as
|
||||||
|
"referred".
|
||||||
|
|
||||||
Before::
|
Before::
|
||||||
|
|
||||||
@ -258,7 +251,7 @@ class LaTeXFootnoteTransform(SphinxPostTransform):
|
|||||||
After::
|
After::
|
||||||
|
|
||||||
blah blah blah
|
blah blah blah
|
||||||
<footnote ids="id1">
|
<footnote ids="id1" referred=True>
|
||||||
<label>
|
<label>
|
||||||
1
|
1
|
||||||
<paragraph>
|
<paragraph>
|
||||||
@ -348,7 +341,7 @@ class LaTeXFootnoteTransform(SphinxPostTransform):
|
|||||||
formats = ('latex',)
|
formats = ('latex',)
|
||||||
|
|
||||||
def run(self, **kwargs: Any) -> None:
|
def run(self, **kwargs: Any) -> None:
|
||||||
footnotes = list(self.document.traverse(nodes.footnote))
|
footnotes = list(self.document.findall(nodes.footnote))
|
||||||
for node in footnotes:
|
for node in footnotes:
|
||||||
node.parent.remove(node)
|
node.parent.remove(node)
|
||||||
|
|
||||||
@ -358,7 +351,7 @@ class LaTeXFootnoteTransform(SphinxPostTransform):
|
|||||||
|
|
||||||
class LaTeXFootnoteVisitor(nodes.NodeVisitor):
|
class LaTeXFootnoteVisitor(nodes.NodeVisitor):
|
||||||
def __init__(self, document: nodes.document, footnotes: List[nodes.footnote]) -> None:
|
def __init__(self, document: nodes.document, footnotes: List[nodes.footnote]) -> None:
|
||||||
self.appeared: Set[Tuple[str, str]] = set()
|
self.appeared: Dict[Tuple[str, str], nodes.footnote] = {}
|
||||||
self.footnotes: List[nodes.footnote] = footnotes
|
self.footnotes: List[nodes.footnote] = footnotes
|
||||||
self.pendings: List[nodes.footnote] = []
|
self.pendings: List[nodes.footnote] = []
|
||||||
self.table_footnotes: List[nodes.footnote] = []
|
self.table_footnotes: List[nodes.footnote] = []
|
||||||
@ -423,7 +416,7 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
|
|||||||
self.unrestrict(node)
|
self.unrestrict(node)
|
||||||
|
|
||||||
def depart_table(self, node: nodes.table) -> None:
|
def depart_table(self, node: nodes.table) -> None:
|
||||||
tbody = list(node.traverse(nodes.tbody))[0]
|
tbody = next(node.findall(nodes.tbody))
|
||||||
for footnote in reversed(self.table_footnotes):
|
for footnote in reversed(self.table_footnotes):
|
||||||
fntext = footnotetext('', *footnote.children, ids=footnote['ids'])
|
fntext = footnotetext('', *footnote.children, ids=footnote['ids'])
|
||||||
tbody.insert(0, fntext)
|
tbody.insert(0, fntext)
|
||||||
@ -439,22 +432,24 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
|
|||||||
def visit_footnote_reference(self, node: nodes.footnote_reference) -> None:
|
def visit_footnote_reference(self, node: nodes.footnote_reference) -> None:
|
||||||
number = node.astext().strip()
|
number = node.astext().strip()
|
||||||
docname = node['docname']
|
docname = node['docname']
|
||||||
if self.restricted:
|
if (docname, number) in self.appeared:
|
||||||
mark = footnotemark('', number, refid=node['refid'])
|
footnote = self.appeared.get((docname, number))
|
||||||
node.replace_self(mark)
|
footnote["referred"] = True
|
||||||
if (docname, number) not in self.appeared:
|
|
||||||
footnote = self.get_footnote_by_reference(node)
|
|
||||||
self.pendings.append(footnote)
|
|
||||||
elif (docname, number) in self.appeared:
|
|
||||||
mark = footnotemark('', number, refid=node['refid'])
|
mark = footnotemark('', number, refid=node['refid'])
|
||||||
node.replace_self(mark)
|
node.replace_self(mark)
|
||||||
else:
|
else:
|
||||||
footnote = self.get_footnote_by_reference(node)
|
footnote = self.get_footnote_by_reference(node)
|
||||||
self.footnotes.remove(footnote)
|
if self.restricted:
|
||||||
node.replace_self(footnote)
|
mark = footnotemark('', number, refid=node['refid'])
|
||||||
footnote.walkabout(self)
|
node.replace_self(mark)
|
||||||
|
self.pendings.append(footnote)
|
||||||
|
else:
|
||||||
|
self.footnotes.remove(footnote)
|
||||||
|
node.replace_self(footnote)
|
||||||
|
footnote.walkabout(self)
|
||||||
|
|
||||||
self.appeared.add((docname, number))
|
self.appeared[(docname, number)] = footnote
|
||||||
raise nodes.SkipNode
|
raise nodes.SkipNode
|
||||||
|
|
||||||
def get_footnote_by_reference(self, node: nodes.footnote_reference) -> nodes.footnote:
|
def get_footnote_by_reference(self, node: nodes.footnote_reference) -> nodes.footnote:
|
||||||
@ -501,7 +496,7 @@ class BibliographyTransform(SphinxPostTransform):
|
|||||||
|
|
||||||
def run(self, **kwargs: Any) -> None:
|
def run(self, **kwargs: Any) -> None:
|
||||||
citations = thebibliography()
|
citations = thebibliography()
|
||||||
for node in list(self.document.traverse(nodes.citation)):
|
for node in list(self.document.findall(nodes.citation)):
|
||||||
node.parent.remove(node)
|
node.parent.remove(node)
|
||||||
citations += node
|
citations += node
|
||||||
|
|
||||||
@ -521,7 +516,7 @@ class CitationReferenceTransform(SphinxPostTransform):
|
|||||||
def run(self, **kwargs: Any) -> None:
|
def run(self, **kwargs: Any) -> None:
|
||||||
domain = cast(CitationDomain, self.env.get_domain('citation'))
|
domain = cast(CitationDomain, self.env.get_domain('citation'))
|
||||||
matcher = NodeMatcher(addnodes.pending_xref, refdomain='citation', reftype='ref')
|
matcher = NodeMatcher(addnodes.pending_xref, refdomain='citation', reftype='ref')
|
||||||
for node in self.document.traverse(matcher): # type: addnodes.pending_xref
|
for node in self.document.findall(matcher): # type: addnodes.pending_xref
|
||||||
docname, labelid, _ = domain.citations.get(node['reftarget'], ('', '', 0))
|
docname, labelid, _ = domain.citations.get(node['reftarget'], ('', '', 0))
|
||||||
if docname:
|
if docname:
|
||||||
citation_ref = nodes.citation_reference('', '', *node.children,
|
citation_ref = nodes.citation_reference('', '', *node.children,
|
||||||
@ -540,7 +535,7 @@ class MathReferenceTransform(SphinxPostTransform):
|
|||||||
|
|
||||||
def run(self, **kwargs: Any) -> None:
|
def run(self, **kwargs: Any) -> None:
|
||||||
equations = self.env.get_domain('math').data['objects']
|
equations = self.env.get_domain('math').data['objects']
|
||||||
for node in self.document.traverse(addnodes.pending_xref):
|
for node in self.document.findall(addnodes.pending_xref):
|
||||||
if node['refdomain'] == 'math' and node['reftype'] in ('eq', 'numref'):
|
if node['refdomain'] == 'math' and node['reftype'] in ('eq', 'numref'):
|
||||||
docname, _ = equations.get(node['reftarget'], (None, None))
|
docname, _ = equations.get(node['reftarget'], (None, None))
|
||||||
if docname:
|
if docname:
|
||||||
@ -555,7 +550,7 @@ class LiteralBlockTransform(SphinxPostTransform):
|
|||||||
|
|
||||||
def run(self, **kwargs: Any) -> None:
|
def run(self, **kwargs: Any) -> None:
|
||||||
matcher = NodeMatcher(nodes.container, literal_block=True)
|
matcher = NodeMatcher(nodes.container, literal_block=True)
|
||||||
for node in self.document.traverse(matcher): # type: nodes.container
|
for node in self.document.findall(matcher): # type: nodes.container
|
||||||
newnode = captioned_literal_block('', *node.children, **node.attributes)
|
newnode = captioned_literal_block('', *node.children, **node.attributes)
|
||||||
node.replace_self(newnode)
|
node.replace_self(newnode)
|
||||||
|
|
||||||
@ -566,7 +561,7 @@ class DocumentTargetTransform(SphinxPostTransform):
|
|||||||
formats = ('latex',)
|
formats = ('latex',)
|
||||||
|
|
||||||
def run(self, **kwargs: Any) -> None:
|
def run(self, **kwargs: Any) -> None:
|
||||||
for node in self.document.traverse(addnodes.start_of_file):
|
for node in self.document.findall(addnodes.start_of_file):
|
||||||
section = node.next_node(nodes.section)
|
section = node.next_node(nodes.section)
|
||||||
if section:
|
if section:
|
||||||
section['ids'].append(':doc') # special label for :doc:
|
section['ids'].append(':doc') # special label for :doc:
|
||||||
@ -602,9 +597,9 @@ class IndexInSectionTitleTransform(SphinxPostTransform):
|
|||||||
formats = ('latex',)
|
formats = ('latex',)
|
||||||
|
|
||||||
def run(self, **kwargs: Any) -> None:
|
def run(self, **kwargs: Any) -> None:
|
||||||
for node in list(self.document.traverse(nodes.title)):
|
for node in list(self.document.findall(nodes.title)):
|
||||||
if isinstance(node.parent, nodes.section):
|
if isinstance(node.parent, nodes.section):
|
||||||
for i, index in enumerate(list(node.traverse(addnodes.index))):
|
for i, index in enumerate(node.findall(addnodes.index)):
|
||||||
# move the index node next to the section title
|
# move the index node next to the section title
|
||||||
node.remove(index)
|
node.remove(index)
|
||||||
node.parent.insert(i + 1, index)
|
node.parent.insert(i + 1, index)
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Utilities for LaTeX builder."""
|
||||||
sphinx.builders.latex.util
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Utilities for LaTeX builder.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
@ -20,7 +12,7 @@ class ExtBabel(Babel):
|
|||||||
self.language_code = language_code
|
self.language_code = language_code
|
||||||
self.use_polyglossia = use_polyglossia
|
self.use_polyglossia = use_polyglossia
|
||||||
self.supported = True
|
self.supported = True
|
||||||
super().__init__(language_code or '')
|
super().__init__(language_code)
|
||||||
|
|
||||||
def uses_cyrillic(self) -> bool:
|
def uses_cyrillic(self) -> bool:
|
||||||
return self.language in self.cyrillic_languages
|
return self.language in self.cyrillic_languages
|
||||||
|
@ -1,37 +1,25 @@
|
|||||||
"""
|
"""The CheckExternalLinksBuilder class."""
|
||||||
sphinx.builders.linkcheck
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The CheckExternalLinksBuilder class.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
import warnings
|
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from email.utils import parsedate_to_datetime
|
from email.utils import parsedate_to_datetime
|
||||||
from html.parser import HTMLParser
|
from html.parser import HTMLParser
|
||||||
from os import path
|
from os import path
|
||||||
from queue import PriorityQueue, Queue
|
from queue import PriorityQueue, Queue
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from typing import (Any, Dict, Generator, List, NamedTuple, Optional, Pattern, Set, Tuple,
|
from typing import Any, Dict, Generator, List, NamedTuple, Optional, Tuple, Union, cast
|
||||||
Union, cast)
|
|
||||||
from urllib.parse import unquote, urlparse, urlunparse
|
from urllib.parse import unquote, urlparse, urlunparse
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.nodes import Element
|
|
||||||
from requests import Response
|
from requests import Response
|
||||||
from requests.exceptions import ConnectionError, HTTPError, TooManyRedirects
|
from requests.exceptions import ConnectionError, HTTPError, TooManyRedirects
|
||||||
|
|
||||||
from sphinx.application import Sphinx
|
from sphinx.application import Sphinx
|
||||||
from sphinx.builders.dummy import DummyBuilder
|
from sphinx.builders.dummy import DummyBuilder
|
||||||
from sphinx.config import Config
|
from sphinx.config import Config
|
||||||
from sphinx.deprecation import RemovedInSphinx50Warning
|
|
||||||
from sphinx.environment import BuildEnvironment
|
from sphinx.environment import BuildEnvironment
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
from sphinx.transforms.post_transforms import SphinxPostTransform
|
from sphinx.transforms.post_transforms import SphinxPostTransform
|
||||||
@ -43,18 +31,31 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
uri_re = re.compile('([a-z]+:)?//') # matches to foo:// and // (a protocol relative URL)
|
uri_re = re.compile('([a-z]+:)?//') # matches to foo:// and // (a protocol relative URL)
|
||||||
|
|
||||||
Hyperlink = NamedTuple('Hyperlink', (('uri', str),
|
|
||||||
('docname', str),
|
class Hyperlink(NamedTuple):
|
||||||
('lineno', Optional[int])))
|
uri: str
|
||||||
CheckRequest = NamedTuple('CheckRequest', (('next_check', float),
|
docname: str
|
||||||
('hyperlink', Optional[Hyperlink])))
|
lineno: Optional[int]
|
||||||
CheckResult = NamedTuple('CheckResult', (('uri', str),
|
|
||||||
('docname', str),
|
|
||||||
('lineno', int),
|
class CheckRequest(NamedTuple):
|
||||||
('status', str),
|
next_check: float
|
||||||
('message', str),
|
hyperlink: Optional[Hyperlink]
|
||||||
('code', int)))
|
|
||||||
RateLimit = NamedTuple('RateLimit', (('delay', float), ('next_check', float)))
|
|
||||||
|
class CheckResult(NamedTuple):
|
||||||
|
uri: str
|
||||||
|
docname: str
|
||||||
|
lineno: int
|
||||||
|
status: str
|
||||||
|
message: str
|
||||||
|
code: int
|
||||||
|
|
||||||
|
|
||||||
|
class RateLimit(NamedTuple):
|
||||||
|
delay: float
|
||||||
|
next_check: float
|
||||||
|
|
||||||
|
|
||||||
# Tuple is old styled CheckRequest
|
# Tuple is old styled CheckRequest
|
||||||
CheckRequestType = Union[CheckRequest, Tuple[float, str, str, int]]
|
CheckRequestType = Union[CheckRequest, Tuple[float, str, str, int]]
|
||||||
@ -67,16 +68,6 @@ QUEUE_POLL_SECS = 1
|
|||||||
DEFAULT_DELAY = 60.0
|
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):
|
class AnchorCheckParser(HTMLParser):
|
||||||
"""Specialized HTML parser that looks for a specific anchor."""
|
"""Specialized HTML parser that looks for a specific anchor."""
|
||||||
|
|
||||||
@ -120,114 +111,11 @@ class CheckExternalLinksBuilder(DummyBuilder):
|
|||||||
'%(outdir)s/output.txt')
|
'%(outdir)s/output.txt')
|
||||||
|
|
||||||
def init(self) -> None:
|
def init(self) -> None:
|
||||||
|
self.broken_hyperlinks = 0
|
||||||
self.hyperlinks: Dict[str, Hyperlink] = {}
|
self.hyperlinks: Dict[str, Hyperlink] = {}
|
||||||
self._good: Set[str] = set()
|
|
||||||
self._broken: Dict[str, str] = {}
|
|
||||||
self._redirected: Dict[str, Tuple[str, int]] = {}
|
|
||||||
# set a timeout for non-responding servers
|
# set a timeout for non-responding servers
|
||||||
socket.setdefaulttimeout(5.0)
|
socket.setdefaulttimeout(5.0)
|
||||||
|
|
||||||
# create queues and worker threads
|
|
||||||
self._wqueue: PriorityQueue[CheckRequestType] = PriorityQueue()
|
|
||||||
self._rqueue: Queue[CheckResult] = Queue()
|
|
||||||
|
|
||||||
@property
|
|
||||||
def anchors_ignore(self) -> List[Pattern]:
|
|
||||||
warnings.warn(
|
|
||||||
"%s.%s is deprecated." % (self.__class__.__name__, "anchors_ignore"),
|
|
||||||
RemovedInSphinx50Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
return [re.compile(x) for x in self.config.linkcheck_anchors_ignore]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def auth(self) -> List[Tuple[Pattern, Any]]:
|
|
||||||
warnings.warn(
|
|
||||||
"%s.%s is deprecated." % (self.__class__.__name__, "auth"),
|
|
||||||
RemovedInSphinx50Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
return [(re.compile(pattern), auth_info) for pattern, auth_info
|
|
||||||
in self.config.linkcheck_auth]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def to_ignore(self) -> List[Pattern]:
|
|
||||||
warnings.warn(
|
|
||||||
"%s.%s is deprecated." % (self.__class__.__name__, "to_ignore"),
|
|
||||||
RemovedInSphinx50Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
return [re.compile(x) for x in self.config.linkcheck_ignore]
|
|
||||||
|
|
||||||
@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:
|
|
||||||
warnings.warn(
|
|
||||||
"%s.%s is deprecated." % (self.__class__.__name__, "check_thread"),
|
|
||||||
RemovedInSphinx50Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
# do nothing.
|
|
||||||
|
|
||||||
def limit_rate(self, response: Response) -> Optional[float]:
|
|
||||||
warnings.warn(
|
|
||||||
"%s.%s is deprecated." % (self.__class__.__name__, "limit_rate"),
|
|
||||||
RemovedInSphinx50Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
worker = HyperlinkAvailabilityCheckWorker(self.env, self.config,
|
|
||||||
None, None, {})
|
|
||||||
return worker.limit_rate(response)
|
|
||||||
|
|
||||||
def rqueue(self, response: Response) -> Queue:
|
|
||||||
warnings.warn(
|
|
||||||
"%s.%s is deprecated." % (self.__class__.__name__, "rqueue"),
|
|
||||||
RemovedInSphinx50Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
return self._rqueue
|
|
||||||
|
|
||||||
def workers(self, response: Response) -> List[Thread]:
|
|
||||||
warnings.warn(
|
|
||||||
"%s.%s is deprecated." % (self.__class__.__name__, "workers"),
|
|
||||||
RemovedInSphinx50Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
return []
|
|
||||||
|
|
||||||
def wqueue(self, response: Response) -> Queue:
|
|
||||||
warnings.warn(
|
|
||||||
"%s.%s is deprecated." % (self.__class__.__name__, "wqueue"),
|
|
||||||
RemovedInSphinx50Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
return self._wqueue
|
|
||||||
|
|
||||||
def process_result(self, result: CheckResult) -> None:
|
def process_result(self, result: CheckResult) -> None:
|
||||||
filename = self.env.doc2path(result.docname, None)
|
filename = self.env.doc2path(result.docname, None)
|
||||||
|
|
||||||
@ -260,6 +148,7 @@ class CheckExternalLinksBuilder(DummyBuilder):
|
|||||||
logger.info(red('broken ') + result.uri + red(' - ' + result.message))
|
logger.info(red('broken ') + result.uri + red(' - ' + result.message))
|
||||||
self.write_entry('broken', result.docname, filename, result.lineno,
|
self.write_entry('broken', result.docname, filename, result.lineno,
|
||||||
result.uri + ': ' + result.message)
|
result.uri + ': ' + result.message)
|
||||||
|
self.broken_hyperlinks += 1
|
||||||
elif result.status == 'redirected':
|
elif result.status == 'redirected':
|
||||||
try:
|
try:
|
||||||
text, color = {
|
text, color = {
|
||||||
@ -292,7 +181,7 @@ class CheckExternalLinksBuilder(DummyBuilder):
|
|||||||
self.json_outfile.write('\n')
|
self.json_outfile.write('\n')
|
||||||
|
|
||||||
def finish(self) -> None:
|
def finish(self) -> None:
|
||||||
checker = HyperlinkAvailabilityChecker(self.env, self.config, self)
|
checker = HyperlinkAvailabilityChecker(self.env, self.config)
|
||||||
logger.info('')
|
logger.info('')
|
||||||
|
|
||||||
with open(path.join(self.outdir, 'output.txt'), 'w') as self.txt_outfile,\
|
with open(path.join(self.outdir, 'output.txt'), 'w') as self.txt_outfile,\
|
||||||
@ -300,42 +189,32 @@ class CheckExternalLinksBuilder(DummyBuilder):
|
|||||||
for result in checker.check(self.hyperlinks):
|
for result in checker.check(self.hyperlinks):
|
||||||
self.process_result(result)
|
self.process_result(result)
|
||||||
|
|
||||||
if self._broken:
|
if self.broken_hyperlinks:
|
||||||
self.app.statuscode = 1
|
self.app.statuscode = 1
|
||||||
|
|
||||||
|
|
||||||
class HyperlinkAvailabilityChecker:
|
class HyperlinkAvailabilityChecker:
|
||||||
def __init__(self, env: BuildEnvironment, config: Config,
|
def __init__(self, env: BuildEnvironment, config: Config) -> None:
|
||||||
builder: CheckExternalLinksBuilder = None) -> None:
|
|
||||||
# Warning: builder argument will be removed in the sphinx-5.0.
|
|
||||||
# Don't use it from extensions.
|
|
||||||
# tag: RemovedInSphinx50Warning
|
|
||||||
self.builder = builder
|
|
||||||
self.config = config
|
self.config = config
|
||||||
self.env = env
|
self.env = env
|
||||||
self.rate_limits: Dict[str, RateLimit] = {}
|
self.rate_limits: Dict[str, RateLimit] = {}
|
||||||
|
self.rqueue: Queue = Queue()
|
||||||
self.workers: List[Thread] = []
|
self.workers: List[Thread] = []
|
||||||
|
self.wqueue: PriorityQueue = PriorityQueue()
|
||||||
|
|
||||||
self.to_ignore = [re.compile(x) for x in self.config.linkcheck_ignore]
|
self.to_ignore = [re.compile(x) for x in self.config.linkcheck_ignore]
|
||||||
|
|
||||||
if builder:
|
|
||||||
self.rqueue = builder._rqueue
|
|
||||||
self.wqueue = builder._wqueue
|
|
||||||
else:
|
|
||||||
self.rqueue = Queue()
|
|
||||||
self.wqueue = PriorityQueue()
|
|
||||||
|
|
||||||
def invoke_threads(self) -> None:
|
def invoke_threads(self) -> None:
|
||||||
for i in range(self.config.linkcheck_workers):
|
for _i in range(self.config.linkcheck_workers):
|
||||||
thread = HyperlinkAvailabilityCheckWorker(self.env, self.config,
|
thread = HyperlinkAvailabilityCheckWorker(self.env, self.config,
|
||||||
self.rqueue, self.wqueue,
|
self.rqueue, self.wqueue,
|
||||||
self.rate_limits, self.builder)
|
self.rate_limits)
|
||||||
thread.start()
|
thread.start()
|
||||||
self.workers.append(thread)
|
self.workers.append(thread)
|
||||||
|
|
||||||
def shutdown_threads(self) -> None:
|
def shutdown_threads(self) -> None:
|
||||||
self.wqueue.join()
|
self.wqueue.join()
|
||||||
for worker in self.workers:
|
for _worker in self.workers:
|
||||||
self.wqueue.put(CheckRequest(CHECK_IMMEDIATELY, None), False)
|
self.wqueue.put(CheckRequest(CHECK_IMMEDIATELY, None), False)
|
||||||
|
|
||||||
def check(self, hyperlinks: Dict[str, Hyperlink]) -> Generator[CheckResult, None, None]:
|
def check(self, hyperlinks: Dict[str, Hyperlink]) -> Generator[CheckResult, None, None]:
|
||||||
@ -365,11 +244,7 @@ class HyperlinkAvailabilityCheckWorker(Thread):
|
|||||||
"""A worker class for checking the availability of hyperlinks."""
|
"""A worker class for checking the availability of hyperlinks."""
|
||||||
|
|
||||||
def __init__(self, env: BuildEnvironment, config: Config, rqueue: Queue,
|
def __init__(self, env: BuildEnvironment, config: Config, rqueue: Queue,
|
||||||
wqueue: Queue, rate_limits: Dict[str, RateLimit],
|
wqueue: Queue, rate_limits: Dict[str, RateLimit]) -> None:
|
||||||
builder: CheckExternalLinksBuilder = None) -> None:
|
|
||||||
# Warning: builder argument will be removed in the sphinx-5.0.
|
|
||||||
# Don't use it from extensions.
|
|
||||||
# tag: RemovedInSphinx50Warning
|
|
||||||
self.config = config
|
self.config = config
|
||||||
self.env = env
|
self.env = env
|
||||||
self.rate_limits = rate_limits
|
self.rate_limits = rate_limits
|
||||||
@ -378,20 +253,11 @@ class HyperlinkAvailabilityCheckWorker(Thread):
|
|||||||
|
|
||||||
self.anchors_ignore = [re.compile(x)
|
self.anchors_ignore = [re.compile(x)
|
||||||
for x in self.config.linkcheck_anchors_ignore]
|
for x in self.config.linkcheck_anchors_ignore]
|
||||||
|
self.documents_exclude = [re.compile(doc)
|
||||||
|
for doc in self.config.linkcheck_exclude_documents]
|
||||||
self.auth = [(re.compile(pattern), auth_info) for pattern, auth_info
|
self.auth = [(re.compile(pattern), auth_info) for pattern, auth_info
|
||||||
in self.config.linkcheck_auth]
|
in self.config.linkcheck_auth]
|
||||||
|
|
||||||
if builder:
|
|
||||||
# if given, fill the result of checks as cache
|
|
||||||
self._good = builder._good
|
|
||||||
self._broken = builder._broken
|
|
||||||
self._redirected = builder._redirected
|
|
||||||
else:
|
|
||||||
# only for compatibility. Will be removed in Sphinx-5.0
|
|
||||||
self._good = set()
|
|
||||||
self._broken = {}
|
|
||||||
self._redirected = {}
|
|
||||||
|
|
||||||
super().__init__(daemon=True)
|
super().__init__(daemon=True)
|
||||||
|
|
||||||
def run(self) -> None:
|
def run(self) -> None:
|
||||||
@ -519,6 +385,15 @@ class HyperlinkAvailabilityCheckWorker(Thread):
|
|||||||
|
|
||||||
def check(docname: str) -> Tuple[str, str, int]:
|
def check(docname: str) -> Tuple[str, str, int]:
|
||||||
# check for various conditions without bothering the network
|
# check for various conditions without bothering the network
|
||||||
|
|
||||||
|
for doc_matcher in self.documents_exclude:
|
||||||
|
if doc_matcher.match(docname):
|
||||||
|
info = (
|
||||||
|
f'{docname} matched {doc_matcher.pattern} from '
|
||||||
|
'linkcheck_exclude_documents'
|
||||||
|
)
|
||||||
|
return 'ignored', info, 0
|
||||||
|
|
||||||
if len(uri) == 0 or uri.startswith(('#', 'mailto:', 'tel:')):
|
if len(uri) == 0 or uri.startswith(('#', 'mailto:', 'tel:')):
|
||||||
return 'unchecked', '', 0
|
return 'unchecked', '', 0
|
||||||
elif not uri.startswith(('http:', 'https:')):
|
elif not uri.startswith(('http:', 'https:')):
|
||||||
@ -530,14 +405,7 @@ class HyperlinkAvailabilityCheckWorker(Thread):
|
|||||||
if path.exists(path.join(srcdir, uri)):
|
if path.exists(path.join(srcdir, uri)):
|
||||||
return 'working', '', 0
|
return 'working', '', 0
|
||||||
else:
|
else:
|
||||||
self._broken[uri] = ''
|
|
||||||
return 'broken', '', 0
|
return 'broken', '', 0
|
||||||
elif uri in self._good:
|
|
||||||
return 'working', 'old', 0
|
|
||||||
elif uri in self._broken:
|
|
||||||
return 'broken', self._broken[uri], 0
|
|
||||||
elif uri in self._redirected:
|
|
||||||
return 'redirected', self._redirected[uri][0], self._redirected[uri][1]
|
|
||||||
|
|
||||||
# need to actually check the URI
|
# need to actually check the URI
|
||||||
for _ in range(self.config.linkcheck_retries):
|
for _ in range(self.config.linkcheck_retries):
|
||||||
@ -545,13 +413,6 @@ class HyperlinkAvailabilityCheckWorker(Thread):
|
|||||||
if status != "broken":
|
if status != "broken":
|
||||||
break
|
break
|
||||||
|
|
||||||
if status == "working":
|
|
||||||
self._good.add(uri)
|
|
||||||
elif status == "broken":
|
|
||||||
self._broken[uri] = info
|
|
||||||
elif status == "redirected":
|
|
||||||
self._redirected[uri] = (info, code)
|
|
||||||
|
|
||||||
return (status, info, code)
|
return (status, info, code)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
@ -639,7 +500,7 @@ class HyperlinkCollector(SphinxPostTransform):
|
|||||||
hyperlinks = builder.hyperlinks
|
hyperlinks = builder.hyperlinks
|
||||||
|
|
||||||
# reference nodes
|
# reference nodes
|
||||||
for refnode in self.document.traverse(nodes.reference):
|
for refnode in self.document.findall(nodes.reference):
|
||||||
if 'refuri' not in refnode:
|
if 'refuri' not in refnode:
|
||||||
continue
|
continue
|
||||||
uri = refnode['refuri']
|
uri = refnode['refuri']
|
||||||
@ -653,7 +514,7 @@ class HyperlinkCollector(SphinxPostTransform):
|
|||||||
hyperlinks[uri] = uri_info
|
hyperlinks[uri] = uri_info
|
||||||
|
|
||||||
# image nodes
|
# image nodes
|
||||||
for imgnode in self.document.traverse(nodes.image):
|
for imgnode in self.document.findall(nodes.image):
|
||||||
uri = imgnode['candidates'].get('?')
|
uri = imgnode['candidates'].get('?')
|
||||||
if uri and '://' in uri:
|
if uri and '://' in uri:
|
||||||
newuri = self.app.emit_firstresult('linkcheck-process-uri', uri)
|
newuri = self.app.emit_firstresult('linkcheck-process-uri', uri)
|
||||||
@ -699,6 +560,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
|
|||||||
app.add_post_transform(HyperlinkCollector)
|
app.add_post_transform(HyperlinkCollector)
|
||||||
|
|
||||||
app.add_config_value('linkcheck_ignore', [], None)
|
app.add_config_value('linkcheck_ignore', [], None)
|
||||||
|
app.add_config_value('linkcheck_exclude_documents', [], None)
|
||||||
app.add_config_value('linkcheck_allowed_redirects', {}, None)
|
app.add_config_value('linkcheck_allowed_redirects', {}, None)
|
||||||
app.add_config_value('linkcheck_auth', [], None)
|
app.add_config_value('linkcheck_auth', [], None)
|
||||||
app.add_config_value('linkcheck_request_headers', {}, None)
|
app.add_config_value('linkcheck_request_headers', {}, None)
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Manual pages builder."""
|
||||||
sphinx.builders.manpage
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Manual pages builder.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
from typing import Any, Dict, List, Set, Tuple, Union
|
from typing import Any, Dict, List, Set, Tuple, Union
|
||||||
@ -18,7 +10,6 @@ from sphinx import addnodes
|
|||||||
from sphinx.application import Sphinx
|
from sphinx.application import Sphinx
|
||||||
from sphinx.builders import Builder
|
from sphinx.builders import Builder
|
||||||
from sphinx.config import Config
|
from sphinx.config import Config
|
||||||
from sphinx.errors import NoUri
|
|
||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
from sphinx.util import logging, progress_message
|
from sphinx.util import logging, progress_message
|
||||||
from sphinx.util.console import darkgreen # type: ignore
|
from sphinx.util.console import darkgreen # type: ignore
|
||||||
@ -49,9 +40,7 @@ class ManualPageBuilder(Builder):
|
|||||||
return 'all manpages' # for now
|
return 'all manpages' # for now
|
||||||
|
|
||||||
def get_target_uri(self, docname: str, typ: str = None) -> str:
|
def get_target_uri(self, docname: str, typ: str = None) -> str:
|
||||||
if typ == 'token':
|
return ''
|
||||||
return ''
|
|
||||||
raise NoUri(docname, typ)
|
|
||||||
|
|
||||||
@progress_message(__('writing'))
|
@progress_message(__('writing'))
|
||||||
def write(self, *ignored: Any) -> None:
|
def write(self, *ignored: Any) -> None:
|
||||||
@ -98,7 +87,7 @@ class ManualPageBuilder(Builder):
|
|||||||
logger.info('} ', nonl=True)
|
logger.info('} ', nonl=True)
|
||||||
self.env.resolve_references(largetree, docname, self)
|
self.env.resolve_references(largetree, docname, self)
|
||||||
# remove pending_xref nodes
|
# remove pending_xref nodes
|
||||||
for pendingnode in largetree.traverse(addnodes.pending_xref):
|
for pendingnode in largetree.findall(addnodes.pending_xref):
|
||||||
pendingnode.replace_self(pendingnode.children)
|
pendingnode.replace_self(pendingnode.children)
|
||||||
|
|
||||||
docwriter.write(largetree, destination)
|
docwriter.write(largetree, destination)
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Single HTML builders."""
|
||||||
sphinx.builders.singlehtml
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Single HTML builders.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
from typing import Any, Dict, List, Tuple, Union
|
from typing import Any, Dict, List, Tuple, Union
|
||||||
@ -54,7 +46,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
|||||||
def fix_refuris(self, tree: Node) -> None:
|
def fix_refuris(self, tree: Node) -> None:
|
||||||
# fix refuris with double anchor
|
# fix refuris with double anchor
|
||||||
fname = self.config.root_doc + self.out_suffix
|
fname = self.config.root_doc + self.out_suffix
|
||||||
for refnode in tree.traverse(nodes.reference):
|
for refnode in tree.findall(nodes.reference):
|
||||||
if 'refuri' not in refnode:
|
if 'refuri' not in refnode:
|
||||||
continue
|
continue
|
||||||
refuri = refnode['refuri']
|
refuri = refnode['refuri']
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Texinfo builder."""
|
||||||
sphinx.builders.texinfo
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Texinfo builder.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from os import path
|
from os import path
|
||||||
@ -138,7 +130,7 @@ class TexinfoBuilder(Builder):
|
|||||||
new_sect += nodes.title('<Set title in conf.py>',
|
new_sect += nodes.title('<Set title in conf.py>',
|
||||||
'<Set title in conf.py>')
|
'<Set title in conf.py>')
|
||||||
new_tree += new_sect
|
new_tree += new_sect
|
||||||
for node in tree.traverse(addnodes.toctree):
|
for node in tree.findall(addnodes.toctree):
|
||||||
new_sect += node
|
new_sect += node
|
||||||
tree = new_tree
|
tree = new_tree
|
||||||
largetree = inline_all_toctrees(self, self.docnames, indexfile, tree,
|
largetree = inline_all_toctrees(self, self.docnames, indexfile, tree,
|
||||||
@ -152,7 +144,7 @@ class TexinfoBuilder(Builder):
|
|||||||
logger.info(__("resolving references..."))
|
logger.info(__("resolving references..."))
|
||||||
self.env.resolve_references(largetree, indexfile, self)
|
self.env.resolve_references(largetree, indexfile, self)
|
||||||
# TODO: add support for external :ref:s
|
# TODO: add support for external :ref:s
|
||||||
for pendingnode in largetree.traverse(addnodes.pending_xref):
|
for pendingnode in largetree.findall(addnodes.pending_xref):
|
||||||
docname = pendingnode['refdocname']
|
docname = pendingnode['refdocname']
|
||||||
sectname = pendingnode['refsectname']
|
sectname = pendingnode['refsectname']
|
||||||
newnodes: List[Node] = [nodes.emphasis(sectname, sectname)]
|
newnodes: List[Node] = [nodes.emphasis(sectname, sectname)]
|
||||||
@ -211,6 +203,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
|
|||||||
app.add_config_value('texinfo_domain_indices', True, None, [list])
|
app.add_config_value('texinfo_domain_indices', True, None, [list])
|
||||||
app.add_config_value('texinfo_show_urls', 'footnote', None)
|
app.add_config_value('texinfo_show_urls', 'footnote', None)
|
||||||
app.add_config_value('texinfo_no_detailmenu', False, None)
|
app.add_config_value('texinfo_no_detailmenu', False, None)
|
||||||
|
app.add_config_value('texinfo_cross_references', True, None)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'version': 'builtin',
|
'version': 'builtin',
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Plain-text Sphinx builder."""
|
||||||
sphinx.builders.text
|
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Plain-text Sphinx builder.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
from typing import Any, Dict, Iterator, Set, Tuple
|
from typing import Any, Dict, Iterator, Set, Tuple
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Docutils-native XML and pseudo-XML builders."""
|
||||||
sphinx.builders.xml
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Docutils-native XML and pseudo-XML builders.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
from typing import Any, Dict, Iterator, Set, Type, Union
|
from typing import Any, Dict, Iterator, Set, Type, Union
|
||||||
@ -71,7 +63,10 @@ class XMLBuilder(Builder):
|
|||||||
# work around multiple string % tuple issues in docutils;
|
# work around multiple string % tuple issues in docutils;
|
||||||
# replace tuples in attribute values with lists
|
# replace tuples in attribute values with lists
|
||||||
doctree = doctree.deepcopy()
|
doctree = doctree.deepcopy()
|
||||||
for node in doctree.traverse(nodes.Element):
|
for domain in self.env.domains.values():
|
||||||
|
xmlns = "xmlns:" + domain.name
|
||||||
|
doctree[xmlns] = "https://www.sphinx-doc.org/" # type: ignore
|
||||||
|
for node in doctree.findall(nodes.Element):
|
||||||
for att, value in node.attributes.items():
|
for att, value in node.attributes.items():
|
||||||
if isinstance(value, tuple):
|
if isinstance(value, tuple):
|
||||||
node.attributes[att] = list(value)
|
node.attributes[att] = list(value)
|
||||||
|
@ -1,9 +1 @@
|
|||||||
"""
|
"""Modules for command line executables."""
|
||||||
sphinx.cmd
|
|
||||||
~~~~~~~~~~
|
|
||||||
|
|
||||||
Modules for command line executables.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Build documentation from a provided source."""
|
||||||
sphinx.cmd.build
|
|
||||||
~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Build documentation from a provided source.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import bdb
|
import bdb
|
||||||
@ -16,6 +8,7 @@ import os
|
|||||||
import pdb
|
import pdb
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
from os import path
|
||||||
from typing import IO, Any, List
|
from typing import IO, Any, List
|
||||||
|
|
||||||
from docutils.utils import SystemMessage
|
from docutils.utils import SystemMessage
|
||||||
@ -28,6 +21,7 @@ from sphinx.locale import __
|
|||||||
from sphinx.util import Tee, format_exception_cut_frames, save_traceback
|
from sphinx.util import Tee, format_exception_cut_frames, save_traceback
|
||||||
from sphinx.util.console import color_terminal, nocolor, red, 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
|
from sphinx.util.docutils import docutils_namespace, patch_docutils
|
||||||
|
from sphinx.util.osutil import abspath, ensuredir
|
||||||
|
|
||||||
|
|
||||||
def handle_exception(app: Sphinx, args: Any, exception: BaseException, stderr: IO = sys.stderr) -> None: # NOQA
|
def handle_exception(app: Sphinx, args: Any, exception: BaseException, stderr: IO = sys.stderr) -> None: # NOQA
|
||||||
@ -240,6 +234,8 @@ def build_main(argv: List[str] = sys.argv[1:]) -> int:
|
|||||||
|
|
||||||
if warning and args.warnfile:
|
if warning and args.warnfile:
|
||||||
try:
|
try:
|
||||||
|
warnfile = abspath(args.warnfile)
|
||||||
|
ensuredir(path.dirname(warnfile))
|
||||||
warnfp = open(args.warnfile, 'w')
|
warnfp = open(args.warnfile, 'w')
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
parser.error(__('cannot open warning file %r: %s') % (
|
parser.error(__('cannot open warning file %r: %s') % (
|
||||||
|
@ -1,17 +1,10 @@
|
|||||||
"""
|
"""sphinx-build -M command-line handling.
|
||||||
sphinx.cmd.make_mode
|
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
sphinx-build -M command-line handling.
|
This replaces the old, platform-dependent and once-generated content
|
||||||
|
of Makefile / make.bat.
|
||||||
|
|
||||||
This replaces the old, platform-dependent and once-generated content
|
This is in its own module so that importing it is fast. It should not
|
||||||
of Makefile / make.bat.
|
import the main Sphinx modules (like sphinx.applications, sphinx.builders).
|
||||||
|
|
||||||
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-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Quickly setup documentation source to work with Sphinx."""
|
||||||
sphinx.cmd.quickstart
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Quickly setup documentation source to work with Sphinx.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import locale
|
import locale
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Build configuration file handling."""
|
||||||
sphinx.config
|
|
||||||
~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Build configuration file handling.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import traceback
|
import traceback
|
||||||
@ -100,7 +92,7 @@ class Config:
|
|||||||
# the real default is locale-dependent
|
# the real default is locale-dependent
|
||||||
'today_fmt': (None, 'env', [str]),
|
'today_fmt': (None, 'env', [str]),
|
||||||
|
|
||||||
'language': (None, 'env', [str]),
|
'language': ('en', 'env', [str]),
|
||||||
'locale_dirs': (['locales'], 'env', []),
|
'locale_dirs': (['locales'], 'env', []),
|
||||||
'figure_language_filename': ('{root}.{language}{ext}', 'env', [str]),
|
'figure_language_filename': ('{root}.{language}{ext}', 'env', [str]),
|
||||||
'gettext_allow_fuzzy_translations': (False, 'gettext', []),
|
'gettext_allow_fuzzy_translations': (False, 'gettext', []),
|
||||||
@ -206,7 +198,7 @@ class Config:
|
|||||||
except ValueError as exc:
|
except ValueError as exc:
|
||||||
raise ValueError(__('invalid number %r for config value %r, ignoring') %
|
raise ValueError(__('invalid number %r for config value %r, ignoring') %
|
||||||
(value, name)) from exc
|
(value, name)) from exc
|
||||||
elif hasattr(defvalue, '__call__'):
|
elif callable(defvalue):
|
||||||
return value
|
return value
|
||||||
elif defvalue is not None and not isinstance(defvalue, str):
|
elif defvalue is not None and not isinstance(defvalue, str):
|
||||||
raise ValueError(__('cannot override config setting %r with unsupported '
|
raise ValueError(__('cannot override config setting %r with unsupported '
|
||||||
@ -251,13 +243,24 @@ class Config:
|
|||||||
if name in self.values:
|
if name in self.values:
|
||||||
self.__dict__[name] = config[name]
|
self.__dict__[name] = config[name]
|
||||||
|
|
||||||
|
def post_init_values(self) -> None:
|
||||||
|
"""
|
||||||
|
Initialize additional config variables that are added after init_values() called.
|
||||||
|
"""
|
||||||
|
config = self._raw_config
|
||||||
|
for name in config:
|
||||||
|
if name not in self.__dict__ and name in self.values:
|
||||||
|
self.__dict__[name] = config[name]
|
||||||
|
|
||||||
|
check_confval_types(None, self)
|
||||||
|
|
||||||
def __getattr__(self, name: str) -> Any:
|
def __getattr__(self, name: str) -> Any:
|
||||||
if name.startswith('_'):
|
if name.startswith('_'):
|
||||||
raise AttributeError(name)
|
raise AttributeError(name)
|
||||||
if name not in self.values:
|
if name not in self.values:
|
||||||
raise AttributeError(__('No such config value: %s') % name)
|
raise AttributeError(__('No such config value: %s') % name)
|
||||||
default = self.values[name][0]
|
default = self.values[name][0]
|
||||||
if hasattr(default, '__call__'):
|
if callable(default):
|
||||||
return default(self)
|
return default(self)
|
||||||
return default
|
return default
|
||||||
|
|
||||||
@ -413,7 +416,7 @@ def check_confval_types(app: "Sphinx", config: Config) -> None:
|
|||||||
for confval in config:
|
for confval in config:
|
||||||
default, rebuild, annotations = config.values[confval.name]
|
default, rebuild, annotations = config.values[confval.name]
|
||||||
|
|
||||||
if hasattr(default, '__call__'):
|
if callable(default):
|
||||||
default = default(config) # evaluate default value
|
default = default(config) # evaluate default value
|
||||||
if default is None and not annotations:
|
if default is None and not annotations:
|
||||||
continue # neither inferable nor expliclitly annotated types
|
continue # neither inferable nor expliclitly annotated types
|
||||||
@ -427,7 +430,7 @@ def check_confval_types(app: "Sphinx", config: Config) -> None:
|
|||||||
"but `{current}` is given.")
|
"but `{current}` is given.")
|
||||||
logger.warning(msg.format(name=confval.name,
|
logger.warning(msg.format(name=confval.name,
|
||||||
current=confval.value,
|
current=confval.value,
|
||||||
candidates=annotations.candidates))
|
candidates=annotations.candidates), once=True)
|
||||||
else:
|
else:
|
||||||
if type(confval.value) is type(default):
|
if type(confval.value) is type(default):
|
||||||
continue
|
continue
|
||||||
@ -452,13 +455,13 @@ def check_confval_types(app: "Sphinx", config: Config) -> None:
|
|||||||
permitted = " or ".join(wrapped_annotations)
|
permitted = " or ".join(wrapped_annotations)
|
||||||
logger.warning(msg.format(name=confval.name,
|
logger.warning(msg.format(name=confval.name,
|
||||||
current=type(confval.value),
|
current=type(confval.value),
|
||||||
permitted=permitted))
|
permitted=permitted), once=True)
|
||||||
else:
|
else:
|
||||||
msg = __("The config value `{name}' has type `{current.__name__}', "
|
msg = __("The config value `{name}' has type `{current.__name__}', "
|
||||||
"defaults to `{default.__name__}'.")
|
"defaults to `{default.__name__}'.")
|
||||||
logger.warning(msg.format(name=confval.name,
|
logger.warning(msg.format(name=confval.name,
|
||||||
current=type(confval.value),
|
current=type(confval.value),
|
||||||
default=type(default)))
|
default=type(default)), once=True)
|
||||||
|
|
||||||
|
|
||||||
def check_primary_domain(app: "Sphinx", config: Config) -> None:
|
def check_primary_domain(app: "Sphinx", config: Config) -> None:
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Sphinx deprecation classes and utilities."""
|
||||||
sphinx.deprecation
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Sphinx deprecation classes and utilities.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
@ -22,6 +14,10 @@ class RemovedInSphinx60Warning(PendingDeprecationWarning):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class RemovedInSphinx70Warning(PendingDeprecationWarning):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
RemovedInNextVersionWarning = RemovedInSphinx50Warning
|
RemovedInNextVersionWarning = RemovedInSphinx50Warning
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Handlers for additional ReST directives."""
|
||||||
sphinx.directives
|
|
||||||
~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Handlers for additional ReST directives.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import TYPE_CHECKING, Any, Dict, Generic, List, Tuple, TypeVar, cast
|
from typing import TYPE_CHECKING, Any, Dict, Generic, List, Tuple, TypeVar, cast
|
||||||
@ -17,7 +9,6 @@ from docutils.parsers.rst import directives, roles
|
|||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.addnodes import desc_signature
|
from sphinx.addnodes import desc_signature
|
||||||
from sphinx.deprecation import RemovedInSphinx50Warning, deprecated_alias
|
|
||||||
from sphinx.util import docutils
|
from sphinx.util import docutils
|
||||||
from sphinx.util.docfields import DocFieldTransformer, Field, TypedField
|
from sphinx.util.docfields import DocFieldTransformer, Field, TypedField
|
||||||
from sphinx.util.docutils import SphinxDirective
|
from sphinx.util.docutils import SphinxDirective
|
||||||
@ -176,7 +167,7 @@ class ObjectDescription(SphinxDirective, Generic[T]):
|
|||||||
|
|
||||||
self.names: List[T] = []
|
self.names: List[T] = []
|
||||||
signatures = self.get_signatures()
|
signatures = self.get_signatures()
|
||||||
for i, sig in enumerate(signatures):
|
for sig in signatures:
|
||||||
# add a signature node for each signature in the current unit
|
# add a signature node for each signature in the current unit
|
||||||
# and add a reference target for it
|
# and add a reference target for it
|
||||||
signode = addnodes.desc_signature(sig, '')
|
signode = addnodes.desc_signature(sig, '')
|
||||||
@ -266,16 +257,6 @@ class DefaultDomain(SphinxDirective):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
deprecated_alias('sphinx.directives',
|
|
||||||
{
|
|
||||||
'DescDirective': ObjectDescription,
|
|
||||||
},
|
|
||||||
RemovedInSphinx50Warning,
|
|
||||||
{
|
|
||||||
'DescDirective': 'sphinx.directives.ObjectDescription',
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
def setup(app: "Sphinx") -> Dict[str, Any]:
|
def setup(app: "Sphinx") -> Dict[str, Any]:
|
||||||
app.add_config_value("strip_signature_backslash", False, 'env')
|
app.add_config_value("strip_signature_backslash", False, 'env')
|
||||||
directives.register_directive('default-role', DefaultRole)
|
directives.register_directive('default-role', DefaultRole)
|
||||||
|
@ -1,11 +1,3 @@
|
|||||||
"""
|
|
||||||
sphinx.directives.code
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import textwrap
|
import textwrap
|
||||||
from difflib import unified_diff
|
from difflib import unified_diff
|
||||||
@ -57,7 +49,7 @@ class Highlight(SphinxDirective):
|
|||||||
|
|
||||||
|
|
||||||
def dedent_lines(lines: List[str], dedent: int, location: Tuple[str, int] = None) -> List[str]:
|
def dedent_lines(lines: List[str], dedent: int, location: Tuple[str, int] = None) -> List[str]:
|
||||||
if not dedent:
|
if dedent is None:
|
||||||
return textwrap.dedent(''.join(lines)).splitlines(True)
|
return textwrap.dedent(''.join(lines)).splitlines(True)
|
||||||
|
|
||||||
if any(s[:dedent].strip() for s in lines):
|
if any(s[:dedent].strip() for s in lines):
|
||||||
@ -138,9 +130,9 @@ class CodeBlock(SphinxDirective):
|
|||||||
|
|
||||||
if 'dedent' in self.options:
|
if 'dedent' in self.options:
|
||||||
location = self.state_machine.get_source_and_line(self.lineno)
|
location = self.state_machine.get_source_and_line(self.lineno)
|
||||||
lines = code.split('\n')
|
lines = code.splitlines(True)
|
||||||
lines = dedent_lines(lines, self.options['dedent'], location=location)
|
lines = dedent_lines(lines, self.options['dedent'], location=location)
|
||||||
code = '\n'.join(lines)
|
code = ''.join(lines)
|
||||||
|
|
||||||
literal: Element = nodes.literal_block(code, code)
|
literal: Element = nodes.literal_block(code, code)
|
||||||
if 'linenos' in self.options or 'lineno-start' in self.options:
|
if 'linenos' in self.options or 'lineno-start' in self.options:
|
||||||
@ -232,9 +224,9 @@ class LiteralIncludeReader:
|
|||||||
self.start_filter,
|
self.start_filter,
|
||||||
self.end_filter,
|
self.end_filter,
|
||||||
self.lines_filter,
|
self.lines_filter,
|
||||||
|
self.dedent_filter,
|
||||||
self.prepend_filter,
|
self.prepend_filter,
|
||||||
self.append_filter,
|
self.append_filter]
|
||||||
self.dedent_filter]
|
|
||||||
lines = self.read_file(self.filename, location=location)
|
lines = self.read_file(self.filename, location=location)
|
||||||
for func in filters:
|
for func in filters:
|
||||||
lines = func(lines, location=location)
|
lines = func(lines, location=location)
|
||||||
|
@ -1,11 +1,3 @@
|
|||||||
"""
|
|
||||||
sphinx.directives.other
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import TYPE_CHECKING, Any, Dict, List, cast
|
from typing import TYPE_CHECKING, Any, Dict, List, cast
|
||||||
|
|
||||||
@ -342,7 +334,7 @@ class Only(SphinxDirective):
|
|||||||
# be placed in the doctree.
|
# be placed in the doctree.
|
||||||
n_sects_to_raise = current_depth - nested_depth + 1
|
n_sects_to_raise = current_depth - nested_depth + 1
|
||||||
parent = cast(nodes.Element, self.state.parent)
|
parent = cast(nodes.Element, self.state.parent)
|
||||||
for i in range(n_sects_to_raise):
|
for _i in range(n_sects_to_raise):
|
||||||
if parent.parent:
|
if parent.parent:
|
||||||
parent = parent.parent
|
parent = parent.parent
|
||||||
parent.append(node)
|
parent.append(node)
|
||||||
|
@ -1,15 +1,7 @@
|
|||||||
"""
|
|
||||||
sphinx.directives.patches
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import warnings
|
import warnings
|
||||||
from os import path
|
from os import path
|
||||||
from typing import TYPE_CHECKING, Any, Dict, List, Tuple, cast
|
from typing import TYPE_CHECKING, Any, Dict, List, Sequence, Tuple, cast
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.nodes import Node, make_id, system_message
|
from docutils.nodes import Node, make_id, system_message
|
||||||
@ -29,13 +21,10 @@ from sphinx.util.osutil import SEP, os_path, relpath
|
|||||||
from sphinx.util.typing import OptionSpec
|
from sphinx.util.typing import OptionSpec
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from docutils.nodes import meta as meta_node # type: ignore
|
|
||||||
from docutils.parsers.rst.directives.misc import Meta as MetaBase # type: ignore
|
from docutils.parsers.rst.directives.misc import Meta as MetaBase # type: ignore
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# docutils-0.17 or older
|
# docutils-0.17 or older
|
||||||
from docutils.parsers.rst.directives.html import Meta as MetaBase
|
from docutils.parsers.rst.directives.html import Meta as MetaBase
|
||||||
from docutils.parsers.rst.directives.html import MetaBody
|
|
||||||
meta_node = MetaBody.meta
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from sphinx.application import Sphinx
|
from sphinx.application import Sphinx
|
||||||
@ -71,11 +60,13 @@ class Figure(images.Figure):
|
|||||||
|
|
||||||
|
|
||||||
class Meta(MetaBase, SphinxDirective):
|
class Meta(MetaBase, SphinxDirective):
|
||||||
def run(self) -> List[Node]:
|
def run(self) -> Sequence[Node]:
|
||||||
result = super().run()
|
result = super().run()
|
||||||
for node in result:
|
for node in result:
|
||||||
|
# for docutils-0.17 or older. Since docutils-0.18, patching is no longer needed
|
||||||
|
# because it uses picklable node; ``docutils.nodes.meta``.
|
||||||
if (isinstance(node, nodes.pending) and
|
if (isinstance(node, nodes.pending) and
|
||||||
isinstance(node.details['nodes'][0], meta_node)):
|
isinstance(node.details['nodes'][0], addnodes.docutils_meta)):
|
||||||
meta = node.details['nodes'][0]
|
meta = node.details['nodes'][0]
|
||||||
meta.source = self.env.doc2path(self.env.docname)
|
meta.source = self.env.doc2path(self.env.docname)
|
||||||
meta.line = self.lineno
|
meta.line = self.lineno
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
"""
|
"""Support for domains.
|
||||||
sphinx.domains
|
|
||||||
~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Support for domains, which are groupings of description directives
|
Domains are groupings of description directives
|
||||||
and roles describing e.g. constructs of one programming language.
|
and roles describing e.g. constructs of one programming language.
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""The C language domain."""
|
||||||
sphinx.domains.c
|
|
||||||
~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The C language domain.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import (Any, Callable, Dict, Generator, Iterator, List, Optional, Tuple, TypeVar,
|
from typing import (Any, Callable, Dict, Generator, Iterator, List, Optional, Tuple, TypeVar,
|
||||||
@ -20,7 +12,7 @@ from sphinx import addnodes
|
|||||||
from sphinx.addnodes import pending_xref
|
from sphinx.addnodes import pending_xref
|
||||||
from sphinx.application import Sphinx
|
from sphinx.application import Sphinx
|
||||||
from sphinx.builders import Builder
|
from sphinx.builders import Builder
|
||||||
from sphinx.deprecation import RemovedInSphinx50Warning
|
from sphinx.deprecation import RemovedInSphinx60Warning
|
||||||
from sphinx.directives import ObjectDescription
|
from sphinx.directives import ObjectDescription
|
||||||
from sphinx.domains import Domain, ObjType
|
from sphinx.domains import Domain, ObjType
|
||||||
from sphinx.environment import BuildEnvironment
|
from sphinx.environment import BuildEnvironment
|
||||||
@ -92,31 +84,22 @@ _id_prefix = [None, 'c.', 'Cv2.']
|
|||||||
_string_re = re.compile(r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'"
|
_string_re = re.compile(r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'"
|
||||||
r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
|
r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
|
||||||
|
|
||||||
|
# bool, complex, and imaginary are macro "keywords", so they are handled seperately
|
||||||
_simple_type_specifiers_re = re.compile(r"""(?x)
|
_simple_type_specifiers_re = re.compile(r"""(?x)
|
||||||
\b(
|
\b(
|
||||||
void|_Bool|bool
|
void|_Bool
|
||||||
# Integer
|
|
||||||
# -------
|
|
||||||
|((signed|unsigned)\s+)?(char|(
|
|
||||||
((long\s+long|long|short)\s+)?int
|
|
||||||
))
|
|
||||||
|__uint128|__int128
|
|
||||||
# extensions
|
|
||||||
|((signed|unsigned)\s+)?__int(8|16|32|64|128)
|
|
||||||
# Floating-point
|
|
||||||
# --------------
|
|
||||||
|(float|double|long\s+double)(\s+(_Complex|complex|_Imaginary|imaginary))?
|
|
||||||
|(_Complex|complex|_Imaginary|imaginary)\s+(float|double|long\s+double)
|
|
||||||
|_Decimal(32|64|128)
|
|
||||||
# extensions
|
|
||||||
|__float80|_Float64x|__float128|_Float128|__ibm128
|
|
||||||
|__fp16
|
|
||||||
# Fixed-point, extension
|
|
||||||
|(_Sat\s+)?((signed|unsigned)\s+)?((short|long|long\s+long)\s+)?(_Fract|fract|_Accum|accum)
|
|
||||||
# Integer types that could be prefixes of the previous ones
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
|((signed|unsigned)\s+)?(long\s+long|long|short)
|
|
||||||
|signed|unsigned
|
|signed|unsigned
|
||||||
|
|short|long
|
||||||
|
|char
|
||||||
|
|int
|
||||||
|
|__uint128|__int128
|
||||||
|
|__int(8|16|32|64|128) # extension
|
||||||
|
|float|double
|
||||||
|
|_Decimal(32|64|128)
|
||||||
|
|_Complex|_Imaginary
|
||||||
|
|__float80|_Float64x|__float128|_Float128|__ibm128 # extension
|
||||||
|
|__fp16 # extension
|
||||||
|
|_Sat|_Fract|fract|_Accum|accum # extension
|
||||||
)\b
|
)\b
|
||||||
""")
|
""")
|
||||||
|
|
||||||
@ -226,7 +209,7 @@ class ASTNestedName(ASTBase):
|
|||||||
assert not self.rooted, str(self)
|
assert not self.rooted, str(self)
|
||||||
assert len(self.names) == 1
|
assert len(self.names) == 1
|
||||||
self.names[0].describe_signature(signode, 'noneIsName', env, '', symbol)
|
self.names[0].describe_signature(signode, 'noneIsName', env, '', symbol)
|
||||||
elif mode == 'markType' or mode == 'lastIsName' or mode == 'markName':
|
elif mode in ('markType', 'lastIsName', 'markName'):
|
||||||
# Each element should be a pending xref targeting the complete
|
# Each element should be a pending xref targeting the complete
|
||||||
# prefix.
|
# prefix.
|
||||||
prefix = ''
|
prefix = ''
|
||||||
@ -636,8 +619,9 @@ class ASTTrailingTypeSpec(ASTBase):
|
|||||||
|
|
||||||
|
|
||||||
class ASTTrailingTypeSpecFundamental(ASTTrailingTypeSpec):
|
class ASTTrailingTypeSpecFundamental(ASTTrailingTypeSpec):
|
||||||
def __init__(self, name: str) -> None:
|
def __init__(self, names: List[str]) -> None:
|
||||||
self.names = name.split()
|
assert len(names) != 0
|
||||||
|
self.names = names
|
||||||
|
|
||||||
def _stringify(self, transform: StringifyTransform) -> str:
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||||||
return ' '.join(self.names)
|
return ' '.join(self.names)
|
||||||
@ -2580,12 +2564,36 @@ class DefinitionParser(BaseParser):
|
|||||||
break
|
break
|
||||||
return ASTNestedName(names, rooted)
|
return ASTNestedName(names, rooted)
|
||||||
|
|
||||||
|
def _parse_simple_type_specifier(self) -> Optional[str]:
|
||||||
|
if self.match(_simple_type_specifiers_re):
|
||||||
|
return self.matched_text
|
||||||
|
for t in ('bool', 'complex', 'imaginary'):
|
||||||
|
if t in self.config.c_extra_keywords:
|
||||||
|
if self.skip_word(t):
|
||||||
|
return t
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _parse_simple_type_specifiers(self) -> ASTTrailingTypeSpecFundamental:
|
||||||
|
names: List[str] = []
|
||||||
|
|
||||||
|
self.skip_ws()
|
||||||
|
while True:
|
||||||
|
t = self._parse_simple_type_specifier()
|
||||||
|
if t is None:
|
||||||
|
break
|
||||||
|
names.append(t)
|
||||||
|
self.skip_ws()
|
||||||
|
if len(names) == 0:
|
||||||
|
return None
|
||||||
|
return ASTTrailingTypeSpecFundamental(names)
|
||||||
|
|
||||||
def _parse_trailing_type_spec(self) -> ASTTrailingTypeSpec:
|
def _parse_trailing_type_spec(self) -> ASTTrailingTypeSpec:
|
||||||
# fundamental types, https://en.cppreference.com/w/c/language/type
|
# fundamental types, https://en.cppreference.com/w/c/language/type
|
||||||
# and extensions
|
# and extensions
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
if self.match(_simple_type_specifiers_re):
|
res = self._parse_simple_type_specifiers()
|
||||||
return ASTTrailingTypeSpecFundamental(self.matched_text)
|
if res is not None:
|
||||||
|
return res
|
||||||
|
|
||||||
# prefixed
|
# prefixed
|
||||||
prefix = None
|
prefix = None
|
||||||
@ -3260,7 +3268,7 @@ class CObject(ObjectDescription[ASTDeclaration]):
|
|||||||
msg = "{}: Pre-v3 C type directive '.. c:type:: {}' converted to " \
|
msg = "{}: Pre-v3 C type directive '.. c:type:: {}' converted to " \
|
||||||
"'.. c:{}:: {}'." \
|
"'.. c:{}:: {}'." \
|
||||||
"\nThe original parsing error was:\n{}"
|
"\nThe original parsing error was:\n{}"
|
||||||
msg = msg.format(RemovedInSphinx50Warning.__name__,
|
msg = msg.format(RemovedInSphinx60Warning.__name__,
|
||||||
sig, ast.objectType, ast, eOrig)
|
sig, ast.objectType, ast, eOrig)
|
||||||
logger.warning(msg, location=signode)
|
logger.warning(msg, location=signode)
|
||||||
except DefinitionError as e:
|
except DefinitionError as e:
|
||||||
@ -3540,7 +3548,7 @@ class AliasTransform(SphinxTransform):
|
|||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
def apply(self, **kwargs: Any) -> None:
|
def apply(self, **kwargs: Any) -> None:
|
||||||
for node in self.document.traverse(AliasNode):
|
for node in self.document.findall(AliasNode):
|
||||||
node = cast(AliasNode, node)
|
node = cast(AliasNode, node)
|
||||||
sig = node.sig
|
sig = node.sig
|
||||||
parentKey = node.parentKey
|
parentKey = node.parentKey
|
||||||
@ -3638,8 +3646,7 @@ class CAliasObject(ObjectDescription):
|
|||||||
" When skipping the root declaration,"
|
" When skipping the root declaration,"
|
||||||
" need 'maxdepth' 0 for infinite or at least 2.",
|
" need 'maxdepth' 0 for infinite or at least 2.",
|
||||||
location=self.get_location())
|
location=self.get_location())
|
||||||
signatures = self.get_signatures()
|
for sig in self.get_signatures():
|
||||||
for i, sig in enumerate(signatures):
|
|
||||||
node.append(AliasNode(sig, aliasOptions, self.state.document, env=self.env))
|
node.append(AliasNode(sig, aliasOptions, self.state.document, env=self.env))
|
||||||
return [node]
|
return [node]
|
||||||
|
|
||||||
@ -3694,7 +3701,7 @@ class CXRefRole(XRefRole):
|
|||||||
if self.env.config['c_warn_on_allowed_pre_v3']:
|
if self.env.config['c_warn_on_allowed_pre_v3']:
|
||||||
msg = "{}: Pre-v3 C type role ':c:type:`{}`' converted to ':c:expr:`{}`'."
|
msg = "{}: Pre-v3 C type role ':c:type:`{}`' converted to ':c:expr:`{}`'."
|
||||||
msg += "\nThe original parsing error was:\n{}"
|
msg += "\nThe original parsing error was:\n{}"
|
||||||
msg = msg.format(RemovedInSphinx50Warning.__name__, text, text, eOrig)
|
msg = msg.format(RemovedInSphinx60Warning.__name__, text, text, eOrig)
|
||||||
logger.warning(msg, location=self.get_location())
|
logger.warning(msg, location=self.get_location())
|
||||||
return [signode], []
|
return [signode], []
|
||||||
|
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""The changeset domain."""
|
||||||
sphinx.domains.changeset
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The changeset domain.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Any, Dict, List, NamedTuple, cast
|
from typing import TYPE_CHECKING, Any, Dict, List, NamedTuple, cast
|
||||||
|
|
||||||
@ -130,7 +122,7 @@ class ChangeSetDomain(Domain):
|
|||||||
self.changesets.setdefault(version, []).append(changeset)
|
self.changesets.setdefault(version, []).append(changeset)
|
||||||
|
|
||||||
def clear_doc(self, docname: str) -> None:
|
def clear_doc(self, docname: str) -> None:
|
||||||
for version, changes in self.changesets.items():
|
for changes in self.changesets.values():
|
||||||
for changeset in changes[:]:
|
for changeset in changes[:]:
|
||||||
if changeset.docname == docname:
|
if changeset.docname == docname:
|
||||||
changes.remove(changeset)
|
changes.remove(changeset)
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""The citation domain."""
|
||||||
sphinx.domains.citation
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The citation domain.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple, cast
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple, cast
|
||||||
|
|
||||||
@ -48,7 +40,7 @@ class CitationDomain(Domain):
|
|||||||
return self.data.setdefault('citation_refs', {})
|
return self.data.setdefault('citation_refs', {})
|
||||||
|
|
||||||
def clear_doc(self, docname: str) -> None:
|
def clear_doc(self, docname: str) -> None:
|
||||||
for key, (fn, _l, lineno) in list(self.citations.items()):
|
for key, (fn, _l, _lineno) in list(self.citations.items()):
|
||||||
if fn == docname:
|
if fn == docname:
|
||||||
del self.citations[key]
|
del self.citations[key]
|
||||||
for key, docnames in list(self.citation_refs.items()):
|
for key, docnames in list(self.citation_refs.items()):
|
||||||
@ -81,7 +73,7 @@ class CitationDomain(Domain):
|
|||||||
docnames.add(self.env.docname)
|
docnames.add(self.env.docname)
|
||||||
|
|
||||||
def check_consistency(self) -> None:
|
def check_consistency(self) -> None:
|
||||||
for name, (docname, labelid, lineno) in self.citations.items():
|
for name, (docname, _labelid, lineno) in self.citations.items():
|
||||||
if name not in self.citation_refs:
|
if name not in self.citation_refs:
|
||||||
logger.warning(__('Citation [%s] is not referenced.'), name,
|
logger.warning(__('Citation [%s] is not referenced.'), name,
|
||||||
type='ref', subtype='citation', location=(docname, lineno))
|
type='ref', subtype='citation', location=(docname, lineno))
|
||||||
@ -112,7 +104,7 @@ class CitationDefinitionTransform(SphinxTransform):
|
|||||||
|
|
||||||
def apply(self, **kwargs: Any) -> None:
|
def apply(self, **kwargs: Any) -> None:
|
||||||
domain = cast(CitationDomain, self.env.get_domain('citation'))
|
domain = cast(CitationDomain, self.env.get_domain('citation'))
|
||||||
for node in self.document.traverse(nodes.citation):
|
for node in self.document.findall(nodes.citation):
|
||||||
# register citation node to domain
|
# register citation node to domain
|
||||||
node['docname'] = self.env.docname
|
node['docname'] = self.env.docname
|
||||||
domain.note_citation(node)
|
domain.note_citation(node)
|
||||||
@ -131,7 +123,7 @@ class CitationReferenceTransform(SphinxTransform):
|
|||||||
|
|
||||||
def apply(self, **kwargs: Any) -> None:
|
def apply(self, **kwargs: Any) -> None:
|
||||||
domain = cast(CitationDomain, self.env.get_domain('citation'))
|
domain = cast(CitationDomain, self.env.get_domain('citation'))
|
||||||
for node in self.document.traverse(nodes.citation_reference):
|
for node in self.document.findall(nodes.citation_reference):
|
||||||
target = node.astext()
|
target = node.astext()
|
||||||
ref = pending_xref(target, refdomain='citation', reftype='ref',
|
ref = pending_xref(target, refdomain='citation', reftype='ref',
|
||||||
reftarget=target, refwarn=True,
|
reftarget=target, refwarn=True,
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""The C++ language domain."""
|
||||||
sphinx.domains.cpp
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The C++ language domain.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import (Any, Callable, Dict, Generator, Iterator, List, Optional, Tuple, TypeVar,
|
from typing import (Any, Callable, Dict, Generator, Iterator, List, Optional, Tuple, TypeVar,
|
||||||
@ -267,7 +259,8 @@ T = TypeVar('T')
|
|||||||
class_object:
|
class_object:
|
||||||
goal: a class declaration, but with specification of a base class
|
goal: a class declaration, but with specification of a base class
|
||||||
grammar:
|
grammar:
|
||||||
nested-name "final"[opt] (":" base-specifier-list)[opt]
|
attribute-specifier-seq[opt]
|
||||||
|
nested-name "final"[opt] (":" base-specifier-list)[opt]
|
||||||
base-specifier-list ->
|
base-specifier-list ->
|
||||||
base-specifier "..."[opt]
|
base-specifier "..."[opt]
|
||||||
| base-specifier-list, base-specifier "..."[opt]
|
| base-specifier-list, base-specifier "..."[opt]
|
||||||
@ -281,7 +274,8 @@ T = TypeVar('T')
|
|||||||
goal: an unscoped enum or a scoped enum, optionally with the underlying
|
goal: an unscoped enum or a scoped enum, optionally with the underlying
|
||||||
type specified
|
type specified
|
||||||
grammar:
|
grammar:
|
||||||
("class" | "struct")[opt] visibility[opt] nested-name (":" type)[opt]
|
("class" | "struct")[opt] visibility[opt]
|
||||||
|
attribute-specifier-seq[opt] nested-name (":" type)[opt]
|
||||||
enumerator_object:
|
enumerator_object:
|
||||||
goal: an element in a scoped or unscoped enum. The name should be
|
goal: an element in a scoped or unscoped enum. The name should be
|
||||||
injected according to the scopedness.
|
injected according to the scopedness.
|
||||||
@ -338,24 +332,14 @@ _keywords = [
|
|||||||
_simple_type_specifiers_re = re.compile(r"""(?x)
|
_simple_type_specifiers_re = re.compile(r"""(?x)
|
||||||
\b(
|
\b(
|
||||||
auto|void|bool
|
auto|void|bool
|
||||||
# Integer
|
|
||||||
# -------
|
|
||||||
|((signed|unsigned)\s+)?(char|__int128|(
|
|
||||||
((long\s+long|long|short)\s+)?int
|
|
||||||
))
|
|
||||||
|wchar_t|char(8|16|32)_t
|
|
||||||
# extensions
|
|
||||||
|((signed|unsigned)\s+)?__int(64|128)
|
|
||||||
# Floating-point
|
|
||||||
# --------------
|
|
||||||
|(float|double|long\s+double)(\s+(_Complex|_Imaginary))?
|
|
||||||
|(_Complex|_Imaginary)\s+(float|double|long\s+double)
|
|
||||||
# extensions
|
|
||||||
|__float80|_Float64x|__float128|_Float128
|
|
||||||
# Integer types that could be prefixes of the previous ones
|
|
||||||
# ---------------------------------------------------------
|
|
||||||
|((signed|unsigned)\s+)?(long\s+long|long|short)
|
|
||||||
|signed|unsigned
|
|signed|unsigned
|
||||||
|
|short|long
|
||||||
|
|char|wchar_t|char(8|16|32)_t
|
||||||
|
|int
|
||||||
|
|__int(64|128) # extension
|
||||||
|
|float|double
|
||||||
|
|__float80|_Float64x|__float128|_Float128 # extension
|
||||||
|
|_Complex|_Imaginary # extension
|
||||||
)\b
|
)\b
|
||||||
""")
|
""")
|
||||||
|
|
||||||
@ -485,12 +469,12 @@ _id_fundamental_v2 = {
|
|||||||
'long double': 'e',
|
'long double': 'e',
|
||||||
'__float80': 'e', '_Float64x': 'e',
|
'__float80': 'e', '_Float64x': 'e',
|
||||||
'__float128': 'g', '_Float128': 'g',
|
'__float128': 'g', '_Float128': 'g',
|
||||||
'float _Complex': 'Cf', '_Complex float': 'Cf',
|
'_Complex float': 'Cf',
|
||||||
'double _Complex': 'Cd', '_Complex double': 'Cd',
|
'_Complex double': 'Cd',
|
||||||
'long double _Complex': 'Ce', '_Complex long double': 'Ce',
|
'_Complex long double': 'Ce',
|
||||||
'float _Imaginary': 'f', '_Imaginary float': 'f',
|
'_Imaginary float': 'f',
|
||||||
'double _Imaginary': 'd', '_Imaginary double': 'd',
|
'_Imaginary double': 'd',
|
||||||
'long double _Imaginary': 'e', '_Imaginary long double': 'e',
|
'_Imaginary long double': 'e',
|
||||||
'auto': 'Da',
|
'auto': 'Da',
|
||||||
'decltype(auto)': 'Dc',
|
'decltype(auto)': 'Dc',
|
||||||
'std::nullptr_t': 'Dn'
|
'std::nullptr_t': 'Dn'
|
||||||
@ -786,7 +770,7 @@ class ASTNestedName(ASTBase):
|
|||||||
assert len(self.names) == 1
|
assert len(self.names) == 1
|
||||||
assert not self.templates[0]
|
assert not self.templates[0]
|
||||||
self.names[0].describe_signature(signode, 'param', env, '', symbol)
|
self.names[0].describe_signature(signode, 'param', env, '', symbol)
|
||||||
elif mode == 'markType' or mode == 'lastIsName' or mode == 'markName':
|
elif mode in ('markType', 'lastIsName', 'markName'):
|
||||||
# Each element should be a pending xref targeting the complete
|
# Each element should be a pending xref targeting the complete
|
||||||
# prefix. however, only the identifier part should be a link, such
|
# prefix. however, only the identifier part should be a link, such
|
||||||
# that template args can be a link as well.
|
# that template args can be a link as well.
|
||||||
@ -1853,8 +1837,12 @@ class ASTTrailingTypeSpec(ASTBase):
|
|||||||
|
|
||||||
|
|
||||||
class ASTTrailingTypeSpecFundamental(ASTTrailingTypeSpec):
|
class ASTTrailingTypeSpecFundamental(ASTTrailingTypeSpec):
|
||||||
def __init__(self, name: str) -> None:
|
def __init__(self, names: List[str], canonNames: List[str]) -> None:
|
||||||
self.names = name.split()
|
assert len(names) != 0
|
||||||
|
assert len(names) == len(canonNames), (names, canonNames)
|
||||||
|
self.names = names
|
||||||
|
# the canonical name list is for ID lookup
|
||||||
|
self.canonNames = canonNames
|
||||||
|
|
||||||
def _stringify(self, transform: StringifyTransform) -> str:
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||||||
return ' '.join(self.names)
|
return ' '.join(self.names)
|
||||||
@ -1862,14 +1850,14 @@ class ASTTrailingTypeSpecFundamental(ASTTrailingTypeSpec):
|
|||||||
def get_id(self, version: int) -> str:
|
def get_id(self, version: int) -> str:
|
||||||
if version == 1:
|
if version == 1:
|
||||||
res = []
|
res = []
|
||||||
for a in self.names:
|
for a in self.canonNames:
|
||||||
if a in _id_fundamental_v1:
|
if a in _id_fundamental_v1:
|
||||||
res.append(_id_fundamental_v1[a])
|
res.append(_id_fundamental_v1[a])
|
||||||
else:
|
else:
|
||||||
res.append(a)
|
res.append(a)
|
||||||
return '-'.join(res)
|
return '-'.join(res)
|
||||||
|
|
||||||
txt = str(self)
|
txt = ' '.join(self.canonNames)
|
||||||
if txt not in _id_fundamental_v2:
|
if txt not in _id_fundamental_v2:
|
||||||
raise Exception(
|
raise Exception(
|
||||||
'Semi-internal error: Fundamental type "%s" can not be mapped '
|
'Semi-internal error: Fundamental type "%s" can not be mapped '
|
||||||
@ -3324,16 +3312,20 @@ class ASTBaseClass(ASTBase):
|
|||||||
|
|
||||||
|
|
||||||
class ASTClass(ASTBase):
|
class ASTClass(ASTBase):
|
||||||
def __init__(self, name: ASTNestedName, final: bool, bases: List[ASTBaseClass]) -> None:
|
def __init__(self, name: ASTNestedName, final: bool, bases: List[ASTBaseClass],
|
||||||
|
attrs: List[ASTAttribute]) -> None:
|
||||||
self.name = name
|
self.name = name
|
||||||
self.final = final
|
self.final = final
|
||||||
self.bases = bases
|
self.bases = bases
|
||||||
|
self.attrs = attrs
|
||||||
|
|
||||||
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
|
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
|
||||||
return symbol.get_full_nested_name().get_id(version)
|
return symbol.get_full_nested_name().get_id(version)
|
||||||
|
|
||||||
def _stringify(self, transform: StringifyTransform) -> str:
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||||||
res = []
|
res = []
|
||||||
|
for attr in self.attrs:
|
||||||
|
res.append(transform(attr) + ' ')
|
||||||
res.append(transform(self.name))
|
res.append(transform(self.name))
|
||||||
if self.final:
|
if self.final:
|
||||||
res.append(' final')
|
res.append(' final')
|
||||||
@ -3350,6 +3342,9 @@ class ASTClass(ASTBase):
|
|||||||
def describe_signature(self, signode: TextElement, mode: str,
|
def describe_signature(self, signode: TextElement, mode: str,
|
||||||
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
||||||
verify_description_mode(mode)
|
verify_description_mode(mode)
|
||||||
|
for attr in self.attrs:
|
||||||
|
attr.describe_signature(signode)
|
||||||
|
signode += addnodes.desc_sig_space()
|
||||||
self.name.describe_signature(signode, mode, env, symbol=symbol)
|
self.name.describe_signature(signode, mode, env, symbol=symbol)
|
||||||
if self.final:
|
if self.final:
|
||||||
signode += addnodes.desc_sig_space()
|
signode += addnodes.desc_sig_space()
|
||||||
@ -3367,8 +3362,9 @@ class ASTClass(ASTBase):
|
|||||||
|
|
||||||
|
|
||||||
class ASTUnion(ASTBase):
|
class ASTUnion(ASTBase):
|
||||||
def __init__(self, name: ASTNestedName) -> None:
|
def __init__(self, name: ASTNestedName, attrs: List[ASTAttribute]) -> None:
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.attrs = attrs
|
||||||
|
|
||||||
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
|
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
|
||||||
if version == 1:
|
if version == 1:
|
||||||
@ -3376,20 +3372,28 @@ class ASTUnion(ASTBase):
|
|||||||
return symbol.get_full_nested_name().get_id(version)
|
return symbol.get_full_nested_name().get_id(version)
|
||||||
|
|
||||||
def _stringify(self, transform: StringifyTransform) -> str:
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||||||
return transform(self.name)
|
res = []
|
||||||
|
for attr in self.attrs:
|
||||||
|
res.append(transform(attr) + ' ')
|
||||||
|
res.append(transform(self.name))
|
||||||
|
return ''.join(res)
|
||||||
|
|
||||||
def describe_signature(self, signode: TextElement, mode: str,
|
def describe_signature(self, signode: TextElement, mode: str,
|
||||||
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
||||||
verify_description_mode(mode)
|
verify_description_mode(mode)
|
||||||
|
for attr in self.attrs:
|
||||||
|
attr.describe_signature(signode)
|
||||||
|
signode += addnodes.desc_sig_space()
|
||||||
self.name.describe_signature(signode, mode, env, symbol=symbol)
|
self.name.describe_signature(signode, mode, env, symbol=symbol)
|
||||||
|
|
||||||
|
|
||||||
class ASTEnum(ASTBase):
|
class ASTEnum(ASTBase):
|
||||||
def __init__(self, name: ASTNestedName, scoped: str,
|
def __init__(self, name: ASTNestedName, scoped: str, underlyingType: ASTType,
|
||||||
underlyingType: ASTType) -> None:
|
attrs: List[ASTAttribute]) -> None:
|
||||||
self.name = name
|
self.name = name
|
||||||
self.scoped = scoped
|
self.scoped = scoped
|
||||||
self.underlyingType = underlyingType
|
self.underlyingType = underlyingType
|
||||||
|
self.attrs = attrs
|
||||||
|
|
||||||
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
|
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
|
||||||
if version == 1:
|
if version == 1:
|
||||||
@ -3401,6 +3405,8 @@ class ASTEnum(ASTBase):
|
|||||||
if self.scoped:
|
if self.scoped:
|
||||||
res.append(self.scoped)
|
res.append(self.scoped)
|
||||||
res.append(' ')
|
res.append(' ')
|
||||||
|
for attr in self.attrs:
|
||||||
|
res.append(transform(attr) + ' ')
|
||||||
res.append(transform(self.name))
|
res.append(transform(self.name))
|
||||||
if self.underlyingType:
|
if self.underlyingType:
|
||||||
res.append(' : ')
|
res.append(' : ')
|
||||||
@ -3411,6 +3417,9 @@ class ASTEnum(ASTBase):
|
|||||||
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
||||||
verify_description_mode(mode)
|
verify_description_mode(mode)
|
||||||
# self.scoped has been done by the CPPEnumObject
|
# self.scoped has been done by the CPPEnumObject
|
||||||
|
for attr in self.attrs:
|
||||||
|
attr.describe_signature(signode)
|
||||||
|
signode += addnodes.desc_sig_space()
|
||||||
self.name.describe_signature(signode, mode, env, symbol=symbol)
|
self.name.describe_signature(signode, mode, env, symbol=symbol)
|
||||||
if self.underlyingType:
|
if self.underlyingType:
|
||||||
signode += addnodes.desc_sig_space()
|
signode += addnodes.desc_sig_space()
|
||||||
@ -5391,7 +5400,7 @@ class DefinitionParser(BaseParser):
|
|||||||
postFixes: List[ASTPostfixOp] = []
|
postFixes: List[ASTPostfixOp] = []
|
||||||
while True:
|
while True:
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
if prefixType in ['expr', 'cast', 'typeid']:
|
if prefixType in ('expr', 'cast', 'typeid'):
|
||||||
if self.skip_string_and_ws('['):
|
if self.skip_string_and_ws('['):
|
||||||
expr = self._parse_expression()
|
expr = self._parse_expression()
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
@ -5855,12 +5864,102 @@ class DefinitionParser(BaseParser):
|
|||||||
|
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
|
|
||||||
|
def _parse_simple_type_specifiers(self) -> ASTTrailingTypeSpecFundamental:
|
||||||
|
modifier: Optional[str] = None
|
||||||
|
signedness: Optional[str] = None
|
||||||
|
width: List[str] = []
|
||||||
|
typ: Optional[str] = None
|
||||||
|
names: List[str] = [] # the parsed sequence
|
||||||
|
|
||||||
|
self.skip_ws()
|
||||||
|
while self.match(_simple_type_specifiers_re):
|
||||||
|
t = self.matched_text
|
||||||
|
names.append(t)
|
||||||
|
if t in ('auto', 'void', 'bool',
|
||||||
|
'char', 'wchar_t', 'char8_t', 'char16_t', 'char32_t',
|
||||||
|
'int', '__int64', '__int128',
|
||||||
|
'float', 'double',
|
||||||
|
'__float80', '_Float64x', '__float128', '_Float128'):
|
||||||
|
if typ is not None:
|
||||||
|
self.fail("Can not have both {} and {}.".format(t, typ))
|
||||||
|
typ = t
|
||||||
|
elif t in ('signed', 'unsigned'):
|
||||||
|
if signedness is not None:
|
||||||
|
self.fail("Can not have both {} and {}.".format(t, signedness))
|
||||||
|
signedness = t
|
||||||
|
elif t == 'short':
|
||||||
|
if len(width) != 0:
|
||||||
|
self.fail("Can not have both {} and {}.".format(t, width[0]))
|
||||||
|
width.append(t)
|
||||||
|
elif t == 'long':
|
||||||
|
if len(width) != 0 and width[0] != 'long':
|
||||||
|
self.fail("Can not have both {} and {}.".format(t, width[0]))
|
||||||
|
width.append(t)
|
||||||
|
elif t in ('_Imaginary', '_Complex'):
|
||||||
|
if modifier is not None:
|
||||||
|
self.fail("Can not have both {} and {}.".format(t, modifier))
|
||||||
|
modifier = t
|
||||||
|
self.skip_ws()
|
||||||
|
if len(names) == 0:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if typ in ('auto', 'void', 'bool',
|
||||||
|
'wchar_t', 'char8_t', 'char16_t', 'char32_t',
|
||||||
|
'__float80', '_Float64x', '__float128', '_Float128'):
|
||||||
|
if modifier is not None:
|
||||||
|
self.fail("Can not have both {} and {}.".format(typ, modifier))
|
||||||
|
if signedness is not None:
|
||||||
|
self.fail("Can not have both {} and {}.".format(typ, signedness))
|
||||||
|
if len(width) != 0:
|
||||||
|
self.fail("Can not have both {} and {}.".format(typ, ' '.join(width)))
|
||||||
|
elif typ == 'char':
|
||||||
|
if modifier is not None:
|
||||||
|
self.fail("Can not have both {} and {}.".format(typ, modifier))
|
||||||
|
if len(width) != 0:
|
||||||
|
self.fail("Can not have both {} and {}.".format(typ, ' '.join(width)))
|
||||||
|
elif typ == 'int':
|
||||||
|
if modifier is not None:
|
||||||
|
self.fail("Can not have both {} and {}.".format(typ, modifier))
|
||||||
|
elif typ in ('__int64', '__int128'):
|
||||||
|
if modifier is not None:
|
||||||
|
self.fail("Can not have both {} and {}.".format(typ, modifier))
|
||||||
|
if len(width) != 0:
|
||||||
|
self.fail("Can not have both {} and {}.".format(typ, ' '.join(width)))
|
||||||
|
elif typ == 'float':
|
||||||
|
if signedness is not None:
|
||||||
|
self.fail("Can not have both {} and {}.".format(typ, signedness))
|
||||||
|
if len(width) != 0:
|
||||||
|
self.fail("Can not have both {} and {}.".format(typ, ' '.join(width)))
|
||||||
|
elif typ == 'double':
|
||||||
|
if signedness is not None:
|
||||||
|
self.fail("Can not have both {} and {}.".format(typ, signedness))
|
||||||
|
if len(width) > 1:
|
||||||
|
self.fail("Can not have both {} and {}.".format(typ, ' '.join(width)))
|
||||||
|
if len(width) == 1 and width[0] != 'long':
|
||||||
|
self.fail("Can not have both {} and {}.".format(typ, ' '.join(width)))
|
||||||
|
elif typ is None:
|
||||||
|
if modifier is not None:
|
||||||
|
self.fail("Can not have {} without a floating point type.".format(modifier))
|
||||||
|
else:
|
||||||
|
assert False, "Unhandled type {}".format(typ)
|
||||||
|
|
||||||
|
canonNames: List[str] = []
|
||||||
|
if modifier is not None:
|
||||||
|
canonNames.append(modifier)
|
||||||
|
if signedness is not None:
|
||||||
|
canonNames.append(signedness)
|
||||||
|
canonNames.extend(width)
|
||||||
|
if typ is not None:
|
||||||
|
canonNames.append(typ)
|
||||||
|
return ASTTrailingTypeSpecFundamental(names, canonNames)
|
||||||
|
|
||||||
def _parse_trailing_type_spec(self) -> ASTTrailingTypeSpec:
|
def _parse_trailing_type_spec(self) -> ASTTrailingTypeSpec:
|
||||||
# fundamental types, https://en.cppreference.com/w/cpp/language/type
|
# fundamental types, https://en.cppreference.com/w/cpp/language/type
|
||||||
# and extensions
|
# and extensions
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
if self.match(_simple_type_specifiers_re):
|
res = self._parse_simple_type_specifiers()
|
||||||
return ASTTrailingTypeSpecFundamental(self.matched_text)
|
if res is not None:
|
||||||
|
return res
|
||||||
|
|
||||||
# decltype
|
# decltype
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
@ -6483,6 +6582,12 @@ class DefinitionParser(BaseParser):
|
|||||||
return ASTConcept(nestedName, initializer)
|
return ASTConcept(nestedName, initializer)
|
||||||
|
|
||||||
def _parse_class(self) -> ASTClass:
|
def _parse_class(self) -> ASTClass:
|
||||||
|
attrs = []
|
||||||
|
while 1:
|
||||||
|
attr = self._parse_attribute()
|
||||||
|
if attr is None:
|
||||||
|
break
|
||||||
|
attrs.append(attr)
|
||||||
name = self._parse_nested_name()
|
name = self._parse_nested_name()
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
final = self.skip_word_and_ws('final')
|
final = self.skip_word_and_ws('final')
|
||||||
@ -6510,21 +6615,33 @@ class DefinitionParser(BaseParser):
|
|||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
return ASTClass(name, final, bases)
|
return ASTClass(name, final, bases, attrs)
|
||||||
|
|
||||||
def _parse_union(self) -> ASTUnion:
|
def _parse_union(self) -> ASTUnion:
|
||||||
|
attrs = []
|
||||||
|
while 1:
|
||||||
|
attr = self._parse_attribute()
|
||||||
|
if attr is None:
|
||||||
|
break
|
||||||
|
attrs.append(attr)
|
||||||
name = self._parse_nested_name()
|
name = self._parse_nested_name()
|
||||||
return ASTUnion(name)
|
return ASTUnion(name, attrs)
|
||||||
|
|
||||||
def _parse_enum(self) -> ASTEnum:
|
def _parse_enum(self) -> ASTEnum:
|
||||||
scoped = None # is set by CPPEnumObject
|
scoped = None # is set by CPPEnumObject
|
||||||
|
attrs = []
|
||||||
|
while 1:
|
||||||
|
attr = self._parse_attribute()
|
||||||
|
if attr is None:
|
||||||
|
break
|
||||||
|
attrs.append(attr)
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
name = self._parse_nested_name()
|
name = self._parse_nested_name()
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
underlyingType = None
|
underlyingType = None
|
||||||
if self.skip_string(':'):
|
if self.skip_string(':'):
|
||||||
underlyingType = self._parse_type(named=False)
|
underlyingType = self._parse_type(named=False)
|
||||||
return ASTEnum(name, scoped, underlyingType)
|
return ASTEnum(name, scoped, underlyingType, attrs)
|
||||||
|
|
||||||
def _parse_enumerator(self) -> ASTEnumerator:
|
def _parse_enumerator(self) -> ASTEnumerator:
|
||||||
name = self._parse_nested_name()
|
name = self._parse_nested_name()
|
||||||
@ -6541,7 +6658,7 @@ class DefinitionParser(BaseParser):
|
|||||||
|
|
||||||
# ==========================================================================
|
# ==========================================================================
|
||||||
|
|
||||||
def _parse_template_paramter(self) -> ASTTemplateParam:
|
def _parse_template_parameter(self) -> ASTTemplateParam:
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
if self.skip_word('template'):
|
if self.skip_word('template'):
|
||||||
# declare a tenplate template parameter
|
# declare a tenplate template parameter
|
||||||
@ -6613,7 +6730,7 @@ class DefinitionParser(BaseParser):
|
|||||||
pos = self.pos
|
pos = self.pos
|
||||||
err = None
|
err = None
|
||||||
try:
|
try:
|
||||||
param = self._parse_template_paramter()
|
param = self._parse_template_parameter()
|
||||||
templateParams.append(param)
|
templateParams.append(param)
|
||||||
except DefinitionError as eParam:
|
except DefinitionError as eParam:
|
||||||
self.pos = pos
|
self.pos = pos
|
||||||
@ -6789,7 +6906,7 @@ class DefinitionParser(BaseParser):
|
|||||||
self.warn(msg)
|
self.warn(msg)
|
||||||
|
|
||||||
newTemplates: List[Union[ASTTemplateParams, ASTTemplateIntroduction]] = []
|
newTemplates: List[Union[ASTTemplateParams, ASTTemplateIntroduction]] = []
|
||||||
for i in range(numExtra):
|
for _i in range(numExtra):
|
||||||
newTemplates.append(ASTTemplateParams([]))
|
newTemplates.append(ASTTemplateParams([]))
|
||||||
if templatePrefix and not isMemberInstantiation:
|
if templatePrefix and not isMemberInstantiation:
|
||||||
newTemplates.extend(templatePrefix.templates)
|
newTemplates.extend(templatePrefix.templates)
|
||||||
@ -7375,7 +7492,7 @@ class AliasTransform(SphinxTransform):
|
|||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
def apply(self, **kwargs: Any) -> None:
|
def apply(self, **kwargs: Any) -> None:
|
||||||
for node in self.document.traverse(AliasNode):
|
for node in self.document.findall(AliasNode):
|
||||||
node = cast(AliasNode, node)
|
node = cast(AliasNode, node)
|
||||||
sig = node.sig
|
sig = node.sig
|
||||||
parentKey = node.parentKey
|
parentKey = node.parentKey
|
||||||
@ -7495,7 +7612,7 @@ class CPPAliasObject(ObjectDescription):
|
|||||||
" need 'maxdepth' 0 for infinite or at least 2.",
|
" need 'maxdepth' 0 for infinite or at least 2.",
|
||||||
location=self.get_location())
|
location=self.get_location())
|
||||||
signatures = self.get_signatures()
|
signatures = self.get_signatures()
|
||||||
for i, sig in enumerate(signatures):
|
for sig in signatures:
|
||||||
node.append(AliasNode(sig, aliasOptions, env=self.env))
|
node.append(AliasNode(sig, aliasOptions, env=self.env))
|
||||||
|
|
||||||
contentnode = addnodes.desc_content()
|
contentnode = addnodes.desc_content()
|
||||||
@ -7697,7 +7814,7 @@ class CPPDomain(Domain):
|
|||||||
typ: str, target: str, node: pending_xref,
|
typ: str, target: str, node: pending_xref,
|
||||||
contnode: Element) -> Tuple[Optional[Element], Optional[str]]:
|
contnode: Element) -> Tuple[Optional[Element], Optional[str]]:
|
||||||
# add parens again for those that could be functions
|
# add parens again for those that could be functions
|
||||||
if typ == 'any' or typ == 'func':
|
if typ in ('any', 'func'):
|
||||||
target += '()'
|
target += '()'
|
||||||
parser = DefinitionParser(target, location=node, config=env.config)
|
parser = DefinitionParser(target, location=node, config=env.config)
|
||||||
try:
|
try:
|
||||||
@ -7818,7 +7935,7 @@ class CPPDomain(Domain):
|
|||||||
if (env.config.add_function_parentheses and typ == 'func' and
|
if (env.config.add_function_parentheses and typ == 'func' and
|
||||||
title.endswith('operator()')):
|
title.endswith('operator()')):
|
||||||
addParen += 1
|
addParen += 1
|
||||||
if ((typ == 'any' or typ == 'func') and
|
if (typ in ('any', 'func') and
|
||||||
title.endswith('operator') and
|
title.endswith('operator') and
|
||||||
displayName.endswith('operator()')):
|
displayName.endswith('operator()')):
|
||||||
addParen += 1
|
addParen += 1
|
||||||
@ -7908,7 +8025,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
'version': 'builtin',
|
'version': 'builtin',
|
||||||
'env_version': 4,
|
'env_version': 5,
|
||||||
'parallel_read_safe': True,
|
'parallel_read_safe': True,
|
||||||
'parallel_write_safe': True,
|
'parallel_write_safe': True,
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""The index domain."""
|
||||||
sphinx.domains.index
|
|
||||||
~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The index domain.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Tuple
|
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Tuple
|
||||||
|
|
||||||
@ -48,7 +40,7 @@ class IndexDomain(Domain):
|
|||||||
def process_doc(self, env: BuildEnvironment, docname: str, document: Node) -> None:
|
def process_doc(self, env: BuildEnvironment, docname: str, document: Node) -> None:
|
||||||
"""Process a document after it is read by the environment."""
|
"""Process a document after it is read by the environment."""
|
||||||
entries = self.entries.setdefault(env.docname, [])
|
entries = self.entries.setdefault(env.docname, [])
|
||||||
for node in list(document.traverse(addnodes.index)):
|
for node in list(document.findall(addnodes.index)):
|
||||||
try:
|
try:
|
||||||
for entry in node['entries']:
|
for entry in node['entries']:
|
||||||
split_index_msg(entry[0], entry[1])
|
split_index_msg(entry[0], entry[1])
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""The JavaScript domain."""
|
||||||
sphinx.domains.javascript
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The JavaScript domain.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import Any, Dict, Iterator, List, Optional, Tuple, cast
|
from typing import Any, Dict, Iterator, List, Optional, Tuple, cast
|
||||||
|
|
||||||
@ -385,10 +377,10 @@ class JavaScriptDomain(Domain):
|
|||||||
self.modules[modname] = (self.env.docname, node_id)
|
self.modules[modname] = (self.env.docname, node_id)
|
||||||
|
|
||||||
def clear_doc(self, docname: str) -> None:
|
def clear_doc(self, docname: str) -> None:
|
||||||
for fullname, (pkg_docname, node_id, _l) in list(self.objects.items()):
|
for fullname, (pkg_docname, _node_id, _l) in list(self.objects.items()):
|
||||||
if pkg_docname == docname:
|
if pkg_docname == docname:
|
||||||
del self.objects[fullname]
|
del self.objects[fullname]
|
||||||
for modname, (pkg_docname, node_id) in list(self.modules.items()):
|
for modname, (pkg_docname, _node_id) in list(self.modules.items()):
|
||||||
if pkg_docname == docname:
|
if pkg_docname == docname:
|
||||||
del self.modules[modname]
|
del self.modules[modname]
|
||||||
|
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""The math domain."""
|
||||||
sphinx.domains.math
|
|
||||||
~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The math domain.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple
|
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple
|
||||||
|
|
||||||
@ -78,10 +70,10 @@ class MathDomain(Domain):
|
|||||||
def math_node(node: Node) -> bool:
|
def math_node(node: Node) -> bool:
|
||||||
return isinstance(node, (nodes.math, nodes.math_block))
|
return isinstance(node, (nodes.math, nodes.math_block))
|
||||||
|
|
||||||
self.data['has_equations'][docname] = any(document.traverse(math_node))
|
self.data['has_equations'][docname] = any(document.findall(math_node))
|
||||||
|
|
||||||
def clear_doc(self, docname: str) -> None:
|
def clear_doc(self, docname: str) -> None:
|
||||||
for equation_id, (doc, eqno) in list(self.equations.items()):
|
for equation_id, (doc, _eqno) in list(self.equations.items()):
|
||||||
if doc == docname:
|
if doc == docname:
|
||||||
del self.equations[equation_id]
|
del self.equations[equation_id]
|
||||||
|
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""The Python domain."""
|
||||||
sphinx.domains.python
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The Python domain.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import builtins
|
import builtins
|
||||||
import inspect
|
import inspect
|
||||||
@ -26,7 +18,7 @@ from sphinx import addnodes
|
|||||||
from sphinx.addnodes import desc_signature, pending_xref, pending_xref_condition
|
from sphinx.addnodes import desc_signature, pending_xref, pending_xref_condition
|
||||||
from sphinx.application import Sphinx
|
from sphinx.application import Sphinx
|
||||||
from sphinx.builders import Builder
|
from sphinx.builders import Builder
|
||||||
from sphinx.deprecation import RemovedInSphinx50Warning, RemovedInSphinx60Warning
|
from sphinx.deprecation import RemovedInSphinx60Warning
|
||||||
from sphinx.directives import ObjectDescription
|
from sphinx.directives import ObjectDescription
|
||||||
from sphinx.domains import Domain, Index, IndexEntry, ObjType
|
from sphinx.domains import Domain, Index, IndexEntry, ObjType
|
||||||
from sphinx.environment import BuildEnvironment
|
from sphinx.environment import BuildEnvironment
|
||||||
@ -80,46 +72,60 @@ class ModuleEntry(NamedTuple):
|
|||||||
deprecated: bool
|
deprecated: bool
|
||||||
|
|
||||||
|
|
||||||
def type_to_xref(target: str, env: BuildEnvironment = None) -> addnodes.pending_xref:
|
def parse_reftarget(reftarget: str, suppress_prefix: bool = False
|
||||||
"""Convert a type string to a cross reference node."""
|
) -> Tuple[str, str, str, bool]:
|
||||||
if target == 'None':
|
"""Parse a type string and return (reftype, reftarget, title, refspecific flag)"""
|
||||||
|
refspecific = False
|
||||||
|
if reftarget.startswith('.'):
|
||||||
|
reftarget = reftarget[1:]
|
||||||
|
title = reftarget
|
||||||
|
refspecific = True
|
||||||
|
elif reftarget.startswith('~'):
|
||||||
|
reftarget = reftarget[1:]
|
||||||
|
title = reftarget.split('.')[-1]
|
||||||
|
elif suppress_prefix:
|
||||||
|
title = reftarget.split('.')[-1]
|
||||||
|
elif reftarget.startswith('typing.'):
|
||||||
|
title = reftarget[7:]
|
||||||
|
else:
|
||||||
|
title = reftarget
|
||||||
|
|
||||||
|
if reftarget == 'None' or reftarget.startswith('typing.'):
|
||||||
|
# typing module provides non-class types. Obj reference is good to refer them.
|
||||||
reftype = 'obj'
|
reftype = 'obj'
|
||||||
else:
|
else:
|
||||||
reftype = 'class'
|
reftype = 'class'
|
||||||
|
|
||||||
|
return reftype, reftarget, title, refspecific
|
||||||
|
|
||||||
|
|
||||||
|
def type_to_xref(target: str, env: BuildEnvironment = None, suppress_prefix: bool = False
|
||||||
|
) -> addnodes.pending_xref:
|
||||||
|
"""Convert a type string to a cross reference node."""
|
||||||
if env:
|
if env:
|
||||||
kwargs = {'py:module': env.ref_context.get('py:module'),
|
kwargs = {'py:module': env.ref_context.get('py:module'),
|
||||||
'py:class': env.ref_context.get('py:class')}
|
'py:class': env.ref_context.get('py:class')}
|
||||||
else:
|
else:
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
|
|
||||||
refspecific = False
|
reftype, target, title, refspecific = parse_reftarget(target, suppress_prefix)
|
||||||
if target.startswith('.'):
|
|
||||||
target = target[1:]
|
|
||||||
text = target
|
|
||||||
refspecific = True
|
|
||||||
elif target.startswith('~'):
|
|
||||||
target = target[1:]
|
|
||||||
text = target.split('.')[-1]
|
|
||||||
else:
|
|
||||||
text = target
|
|
||||||
|
|
||||||
if env.config.python_use_unqualified_type_names:
|
if env.config.python_use_unqualified_type_names:
|
||||||
# Note: It would be better to use qualname to describe the object to support support
|
# Note: It would be better to use qualname to describe the object to support support
|
||||||
# nested classes. But python domain can't access the real python object because this
|
# nested classes. But python domain can't access the real python object because this
|
||||||
# module should work not-dynamically.
|
# module should work not-dynamically.
|
||||||
shortname = text.split('.')[-1]
|
shortname = title.split('.')[-1]
|
||||||
contnodes: List[Node] = [pending_xref_condition('', shortname, condition='resolved'),
|
contnodes: List[Node] = [pending_xref_condition('', shortname, condition='resolved'),
|
||||||
pending_xref_condition('', text, condition='*')]
|
pending_xref_condition('', title, condition='*')]
|
||||||
else:
|
else:
|
||||||
contnodes = [nodes.Text(text)]
|
contnodes = [nodes.Text(title)]
|
||||||
|
|
||||||
return pending_xref('', *contnodes,
|
return pending_xref('', *contnodes,
|
||||||
refdomain='py', reftype=reftype, reftarget=target,
|
refdomain='py', reftype=reftype, reftarget=target,
|
||||||
refspecific=refspecific, **kwargs)
|
refspecific=refspecific, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def _parse_annotation(annotation: str, env: BuildEnvironment = None) -> List[Node]:
|
def _parse_annotation(annotation: str, env: BuildEnvironment) -> List[Node]:
|
||||||
"""Parse type annotation."""
|
"""Parse type annotation."""
|
||||||
def unparse(node: ast.AST) -> List[Node]:
|
def unparse(node: ast.AST) -> List[Node]:
|
||||||
if isinstance(node, ast.Attribute):
|
if isinstance(node, ast.Attribute):
|
||||||
@ -150,6 +156,8 @@ def _parse_annotation(annotation: str, env: BuildEnvironment = None) -> List[Nod
|
|||||||
return unparse(node.value)
|
return unparse(node.value)
|
||||||
elif isinstance(node, ast.Index):
|
elif isinstance(node, ast.Index):
|
||||||
return unparse(node.value)
|
return unparse(node.value)
|
||||||
|
elif isinstance(node, ast.Invert):
|
||||||
|
return [addnodes.desc_sig_punctuation('', '~')]
|
||||||
elif isinstance(node, ast.List):
|
elif isinstance(node, ast.List):
|
||||||
result = [addnodes.desc_sig_punctuation('', '[')]
|
result = [addnodes.desc_sig_punctuation('', '[')]
|
||||||
if node.elts:
|
if node.elts:
|
||||||
@ -180,6 +188,8 @@ def _parse_annotation(annotation: str, env: BuildEnvironment = None) -> List[Nod
|
|||||||
if isinstance(subnode, nodes.Text):
|
if isinstance(subnode, nodes.Text):
|
||||||
result[i] = nodes.literal('', '', subnode)
|
result[i] = nodes.literal('', '', subnode)
|
||||||
return result
|
return result
|
||||||
|
elif isinstance(node, ast.UnaryOp):
|
||||||
|
return unparse(node.op) + unparse(node.operand)
|
||||||
elif isinstance(node, ast.Tuple):
|
elif isinstance(node, ast.Tuple):
|
||||||
if node.elts:
|
if node.elts:
|
||||||
result = []
|
result = []
|
||||||
@ -196,25 +206,34 @@ def _parse_annotation(annotation: str, env: BuildEnvironment = None) -> List[Nod
|
|||||||
return result
|
return result
|
||||||
else:
|
else:
|
||||||
if sys.version_info < (3, 8):
|
if sys.version_info < (3, 8):
|
||||||
if isinstance(node, ast.Ellipsis):
|
if isinstance(node, ast.Bytes):
|
||||||
|
return [addnodes.desc_sig_literal_string('', repr(node.s))]
|
||||||
|
elif isinstance(node, ast.Ellipsis):
|
||||||
return [addnodes.desc_sig_punctuation('', "...")]
|
return [addnodes.desc_sig_punctuation('', "...")]
|
||||||
elif isinstance(node, ast.NameConstant):
|
elif isinstance(node, ast.NameConstant):
|
||||||
return [nodes.Text(node.value)]
|
return [nodes.Text(node.value)]
|
||||||
|
elif isinstance(node, ast.Num):
|
||||||
|
return [addnodes.desc_sig_literal_string('', repr(node.n))]
|
||||||
|
elif isinstance(node, ast.Str):
|
||||||
|
return [addnodes.desc_sig_literal_string('', repr(node.s))]
|
||||||
|
|
||||||
raise SyntaxError # unsupported syntax
|
raise SyntaxError # unsupported syntax
|
||||||
|
|
||||||
if env is None:
|
|
||||||
warnings.warn("The env parameter for _parse_annotation becomes required now.",
|
|
||||||
RemovedInSphinx50Warning, stacklevel=2)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tree = ast_parse(annotation)
|
tree = ast_parse(annotation)
|
||||||
result = unparse(tree)
|
result: List[Node] = []
|
||||||
for i, node in enumerate(result):
|
for node in unparse(tree):
|
||||||
if isinstance(node, nodes.literal):
|
if isinstance(node, nodes.literal):
|
||||||
result[i] = node[0]
|
result.append(node[0])
|
||||||
elif isinstance(node, nodes.Text) and node.strip():
|
elif isinstance(node, nodes.Text) and node.strip():
|
||||||
result[i] = type_to_xref(str(node), env)
|
if (result and isinstance(result[-1], addnodes.desc_sig_punctuation) and
|
||||||
|
result[-1].astext() == '~'):
|
||||||
|
result.pop()
|
||||||
|
result.append(type_to_xref(str(node), env, suppress_prefix=True))
|
||||||
|
else:
|
||||||
|
result.append(type_to_xref(str(node), env))
|
||||||
|
else:
|
||||||
|
result.append(node)
|
||||||
return result
|
return result
|
||||||
except SyntaxError:
|
except SyntaxError:
|
||||||
return [type_to_xref(annotation, env)]
|
return [type_to_xref(annotation, env)]
|
||||||
@ -331,27 +350,27 @@ class PyXrefMixin:
|
|||||||
result = super().make_xref(rolename, domain, target, # type: ignore
|
result = super().make_xref(rolename, domain, target, # type: ignore
|
||||||
innernode, contnode,
|
innernode, contnode,
|
||||||
env, inliner=None, location=None)
|
env, inliner=None, location=None)
|
||||||
result['refspecific'] = True
|
if isinstance(result, pending_xref):
|
||||||
result['py:module'] = env.ref_context.get('py:module')
|
result['refspecific'] = True
|
||||||
result['py:class'] = env.ref_context.get('py:class')
|
result['py:module'] = env.ref_context.get('py:module')
|
||||||
if target.startswith(('.', '~')):
|
result['py:class'] = env.ref_context.get('py:class')
|
||||||
prefix, result['reftarget'] = target[0], target[1:]
|
|
||||||
if prefix == '.':
|
|
||||||
text = target[1:]
|
|
||||||
elif prefix == '~':
|
|
||||||
text = target.split('.')[-1]
|
|
||||||
for node in list(result.traverse(nodes.Text)):
|
|
||||||
node.parent[node.parent.index(node)] = nodes.Text(text)
|
|
||||||
break
|
|
||||||
elif isinstance(result, pending_xref) and env.config.python_use_unqualified_type_names:
|
|
||||||
children = result.children
|
|
||||||
result.clear()
|
|
||||||
|
|
||||||
shortname = target.split('.')[-1]
|
reftype, reftarget, reftitle, _ = parse_reftarget(target)
|
||||||
textnode = innernode('', shortname)
|
if reftarget != reftitle:
|
||||||
contnodes = [pending_xref_condition('', '', textnode, condition='resolved'),
|
result['reftype'] = reftype
|
||||||
pending_xref_condition('', '', *children, condition='*')]
|
result['reftarget'] = reftarget
|
||||||
result.extend(contnodes)
|
|
||||||
|
result.clear()
|
||||||
|
result += innernode(reftitle, reftitle)
|
||||||
|
elif env.config.python_use_unqualified_type_names:
|
||||||
|
children = result.children
|
||||||
|
result.clear()
|
||||||
|
|
||||||
|
shortname = target.split('.')[-1]
|
||||||
|
textnode = innernode('', shortname)
|
||||||
|
contnodes = [pending_xref_condition('', '', textnode, condition='resolved'),
|
||||||
|
pending_xref_condition('', '', *children, condition='*')]
|
||||||
|
result.extend(contnodes)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@ -384,16 +403,7 @@ class PyXrefMixin:
|
|||||||
|
|
||||||
|
|
||||||
class PyField(PyXrefMixin, Field):
|
class PyField(PyXrefMixin, Field):
|
||||||
def make_xref(self, rolename: str, domain: str, target: str,
|
pass
|
||||||
innernode: Type[TextlikeNode] = nodes.emphasis,
|
|
||||||
contnode: Node = None, env: BuildEnvironment = None,
|
|
||||||
inliner: Inliner = None, location: Node = None) -> Node:
|
|
||||||
if rolename == 'class' and target == 'None':
|
|
||||||
# None is not a type, so use obj role instead.
|
|
||||||
rolename = 'obj'
|
|
||||||
|
|
||||||
return super().make_xref(rolename, domain, target, innernode, contnode,
|
|
||||||
env, inliner, location)
|
|
||||||
|
|
||||||
|
|
||||||
class PyGroupedField(PyXrefMixin, GroupedField):
|
class PyGroupedField(PyXrefMixin, GroupedField):
|
||||||
@ -401,16 +411,7 @@ class PyGroupedField(PyXrefMixin, GroupedField):
|
|||||||
|
|
||||||
|
|
||||||
class PyTypedField(PyXrefMixin, TypedField):
|
class PyTypedField(PyXrefMixin, TypedField):
|
||||||
def make_xref(self, rolename: str, domain: str, target: str,
|
pass
|
||||||
innernode: Type[TextlikeNode] = nodes.emphasis,
|
|
||||||
contnode: Node = None, env: BuildEnvironment = None,
|
|
||||||
inliner: Inliner = None, location: Node = None) -> Node:
|
|
||||||
if rolename == 'class' and target == 'None':
|
|
||||||
# None is not a type, so use obj role instead.
|
|
||||||
rolename = 'obj'
|
|
||||||
|
|
||||||
return super().make_xref(rolename, domain, target, innernode, contnode,
|
|
||||||
env, inliner, location)
|
|
||||||
|
|
||||||
|
|
||||||
class PyObject(ObjectDescription[Tuple[str, str]]):
|
class PyObject(ObjectDescription[Tuple[str, str]]):
|
||||||
@ -965,29 +966,6 @@ class PyProperty(PyObject):
|
|||||||
return _('%s (%s property)') % (attrname, clsname)
|
return _('%s (%s property)') % (attrname, clsname)
|
||||||
|
|
||||||
|
|
||||||
class PyDecoratorMixin:
|
|
||||||
"""
|
|
||||||
Mixin for decorator directives.
|
|
||||||
"""
|
|
||||||
def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]:
|
|
||||||
for cls in self.__class__.__mro__:
|
|
||||||
if cls.__name__ != 'DirectiveAdapter':
|
|
||||||
warnings.warn('PyDecoratorMixin is deprecated. '
|
|
||||||
'Please check the implementation of %s' % cls,
|
|
||||||
RemovedInSphinx50Warning, stacklevel=2)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
warnings.warn('PyDecoratorMixin is deprecated',
|
|
||||||
RemovedInSphinx50Warning, stacklevel=2)
|
|
||||||
|
|
||||||
ret = super().handle_signature(sig, signode) # type: ignore
|
|
||||||
signode.insert(0, addnodes.desc_addname('@', '@'))
|
|
||||||
return ret
|
|
||||||
|
|
||||||
def needs_arglist(self) -> bool:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class PyModule(SphinxDirective):
|
class PyModule(SphinxDirective):
|
||||||
"""
|
"""
|
||||||
Directive to mark description of a new module.
|
Directive to mark description of a new module.
|
||||||
@ -1467,7 +1445,7 @@ def builtin_resolver(app: Sphinx, env: BuildEnvironment,
|
|||||||
return None
|
return None
|
||||||
elif node.get('reftype') in ('class', 'obj') and node.get('reftarget') == 'None':
|
elif node.get('reftype') in ('class', 'obj') and node.get('reftarget') == 'None':
|
||||||
return contnode
|
return contnode
|
||||||
elif node.get('reftype') in ('class', 'exc'):
|
elif node.get('reftype') in ('class', 'obj', 'exc'):
|
||||||
reftarget = node.get('reftarget')
|
reftarget = node.get('reftarget')
|
||||||
if inspect.isclass(getattr(builtins, reftarget, None)):
|
if inspect.isclass(getattr(builtins, reftarget, None)):
|
||||||
# built-in class
|
# built-in class
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""The reStructuredText domain."""
|
||||||
sphinx.domains.rst
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The reStructuredText domain.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import Any, Dict, Iterator, List, Optional, Tuple, cast
|
from typing import Any, Dict, Iterator, List, Optional, Tuple, cast
|
||||||
@ -235,7 +227,7 @@ class ReSTDomain(Domain):
|
|||||||
self.objects[objtype, name] = (self.env.docname, node_id)
|
self.objects[objtype, name] = (self.env.docname, node_id)
|
||||||
|
|
||||||
def clear_doc(self, docname: str) -> None:
|
def clear_doc(self, docname: str) -> None:
|
||||||
for (typ, name), (doc, node_id) in list(self.objects.items()):
|
for (typ, name), (doc, _node_id) in list(self.objects.items()):
|
||||||
if doc == docname:
|
if doc == docname:
|
||||||
del self.objects[typ, name]
|
del self.objects[typ, name]
|
||||||
|
|
||||||
|
@ -1,16 +1,6 @@
|
|||||||
"""
|
"""The standard domain."""
|
||||||
sphinx.domains.std
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
The standard domain.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import unicodedata
|
|
||||||
import warnings
|
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from typing import (TYPE_CHECKING, Any, Callable, Dict, Iterable, Iterator, List, Optional,
|
from typing import (TYPE_CHECKING, Any, Callable, Dict, Iterable, Iterator, List, Optional,
|
||||||
Tuple, Type, Union, cast)
|
Tuple, Type, Union, cast)
|
||||||
@ -22,7 +12,6 @@ from docutils.statemachine import StringList
|
|||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.addnodes import desc_signature, pending_xref
|
from sphinx.addnodes import desc_signature, pending_xref
|
||||||
from sphinx.deprecation import RemovedInSphinx50Warning
|
|
||||||
from sphinx.directives import ObjectDescription
|
from sphinx.directives import ObjectDescription
|
||||||
from sphinx.domains import Domain, ObjType
|
from sphinx.domains import Domain, ObjType
|
||||||
from sphinx.locale import _, __
|
from sphinx.locale import _, __
|
||||||
@ -243,7 +232,7 @@ class Cmdoption(ObjectDescription[str]):
|
|||||||
descr = _('%s command line option') % currprogram
|
descr = _('%s command line option') % currprogram
|
||||||
else:
|
else:
|
||||||
descr = _('command line option')
|
descr = _('command line option')
|
||||||
for option in sig.split(', '):
|
for option in signode.get('allnames', []):
|
||||||
entry = '; '.join([descr, option])
|
entry = '; '.join([descr, option])
|
||||||
self.indexnode['entries'].append(('pair', entry, signode['ids'][0], '', None))
|
self.indexnode['entries'].append(('pair', entry, signode['ids'][0], '', None))
|
||||||
|
|
||||||
@ -336,6 +325,7 @@ class Glossary(SphinxDirective):
|
|||||||
def run(self) -> List[Node]:
|
def run(self) -> List[Node]:
|
||||||
node = addnodes.glossary()
|
node = addnodes.glossary()
|
||||||
node.document = self.state.document
|
node.document = self.state.document
|
||||||
|
node['sorted'] = ('sorted' in self.options)
|
||||||
|
|
||||||
# This directive implements a custom format of the reST definition list
|
# This directive implements a custom format of the reST definition list
|
||||||
# that allows multiple lines of terms before the definition. This is
|
# that allows multiple lines of terms before the definition. This is
|
||||||
@ -400,9 +390,8 @@ class Glossary(SphinxDirective):
|
|||||||
was_empty = False
|
was_empty = False
|
||||||
|
|
||||||
# now, parse all the entries into a big definition list
|
# now, parse all the entries into a big definition list
|
||||||
items = []
|
items: List[nodes.definition_list_item] = []
|
||||||
for terms, definition in entries:
|
for terms, definition in entries:
|
||||||
termtexts: List[str] = []
|
|
||||||
termnodes: List[Node] = []
|
termnodes: List[Node] = []
|
||||||
system_messages: List[Node] = []
|
system_messages: List[Node] = []
|
||||||
for line, source, lineno in terms:
|
for line, source, lineno in terms:
|
||||||
@ -416,7 +405,6 @@ class Glossary(SphinxDirective):
|
|||||||
node_id=None, document=self.state.document)
|
node_id=None, document=self.state.document)
|
||||||
term.rawsource = line
|
term.rawsource = line
|
||||||
system_messages.extend(sysmsg)
|
system_messages.extend(sysmsg)
|
||||||
termtexts.append(term.astext())
|
|
||||||
termnodes.append(term)
|
termnodes.append(term)
|
||||||
|
|
||||||
termnodes.extend(system_messages)
|
termnodes.extend(system_messages)
|
||||||
@ -426,16 +414,10 @@ class Glossary(SphinxDirective):
|
|||||||
self.state.nested_parse(definition, definition.items[0][1],
|
self.state.nested_parse(definition, definition.items[0][1],
|
||||||
defnode)
|
defnode)
|
||||||
termnodes.append(defnode)
|
termnodes.append(defnode)
|
||||||
items.append((termtexts,
|
items.append(nodes.definition_list_item('', *termnodes))
|
||||||
nodes.definition_list_item('', *termnodes)))
|
|
||||||
|
|
||||||
if 'sorted' in self.options:
|
dlist = nodes.definition_list('', *items)
|
||||||
items.sort(key=lambda x:
|
|
||||||
unicodedata.normalize('NFD', x[0][0].lower()))
|
|
||||||
|
|
||||||
dlist = nodes.definition_list()
|
|
||||||
dlist['classes'].append('glossary')
|
dlist['classes'].append('glossary')
|
||||||
dlist.extend(item[1] for item in items)
|
|
||||||
node += dlist
|
node += dlist
|
||||||
return messages + [node]
|
return messages + [node]
|
||||||
|
|
||||||
@ -675,11 +657,6 @@ class StandardDomain(Domain):
|
|||||||
objtype, name, docname, location=location)
|
objtype, name, docname, location=location)
|
||||||
self.objects[objtype, name] = (self.env.docname, labelid)
|
self.objects[objtype, name] = (self.env.docname, labelid)
|
||||||
|
|
||||||
def add_object(self, objtype: str, name: str, docname: str, labelid: str) -> None:
|
|
||||||
warnings.warn('StandardDomain.add_object() is deprecated.',
|
|
||||||
RemovedInSphinx50Warning, stacklevel=2)
|
|
||||||
self.objects[objtype, name] = (docname, labelid)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _terms(self) -> Dict[str, Tuple[str, str]]:
|
def _terms(self) -> Dict[str, Tuple[str, str]]:
|
||||||
""".. note:: Will be removed soon. internal use only."""
|
""".. note:: Will be removed soon. internal use only."""
|
||||||
@ -775,7 +752,7 @@ class StandardDomain(Domain):
|
|||||||
if not sectname:
|
if not sectname:
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
toctree = next(iter(node.traverse(addnodes.toctree)), None)
|
toctree = next(node.findall(addnodes.toctree), None)
|
||||||
if toctree and toctree.get('caption'):
|
if toctree and toctree.get('caption'):
|
||||||
sectname = toctree.get('caption')
|
sectname = toctree.get('caption')
|
||||||
else:
|
else:
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Global creation environment."""
|
||||||
sphinx.environment
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Global creation environment.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import pickle
|
import pickle
|
||||||
@ -49,7 +41,7 @@ default_settings: Dict[str, Any] = {
|
|||||||
'embed_images': False,
|
'embed_images': False,
|
||||||
'embed_stylesheet': False,
|
'embed_stylesheet': False,
|
||||||
'cloak_email_addresses': True,
|
'cloak_email_addresses': True,
|
||||||
'pep_base_url': 'https://www.python.org/dev/peps/',
|
'pep_base_url': 'https://peps.python.org/',
|
||||||
'pep_references': None,
|
'pep_references': None,
|
||||||
'rfc_base_url': 'https://datatracker.ietf.org/doc/html/',
|
'rfc_base_url': 'https://datatracker.ietf.org/doc/html/',
|
||||||
'rfc_references': None,
|
'rfc_references': None,
|
||||||
@ -261,7 +253,7 @@ class BuildEnvironment:
|
|||||||
"""Update settings by new config."""
|
"""Update settings by new config."""
|
||||||
self.settings['input_encoding'] = config.source_encoding
|
self.settings['input_encoding'] = config.source_encoding
|
||||||
self.settings['trim_footnote_reference_space'] = config.trim_footnote_reference_space
|
self.settings['trim_footnote_reference_space'] = config.trim_footnote_reference_space
|
||||||
self.settings['language_code'] = config.language or 'en'
|
self.settings['language_code'] = config.language
|
||||||
|
|
||||||
# Allow to disable by 3rd party extension (workaround)
|
# Allow to disable by 3rd party extension (workaround)
|
||||||
self.settings.setdefault('smart_quotes', True)
|
self.settings.setdefault('smart_quotes', True)
|
||||||
@ -535,7 +527,7 @@ class BuildEnvironment:
|
|||||||
self.apply_post_transforms(doctree, docname)
|
self.apply_post_transforms(doctree, docname)
|
||||||
|
|
||||||
# now, resolve all toctree nodes
|
# now, resolve all toctree nodes
|
||||||
for toctreenode in doctree.traverse(addnodes.toctree):
|
for toctreenode in doctree.findall(addnodes.toctree):
|
||||||
result = TocTree(self).resolve(docname, builder, toctreenode,
|
result = TocTree(self).resolve(docname, builder, toctreenode,
|
||||||
prune=prune_toctrees,
|
prune=prune_toctrees,
|
||||||
includehidden=includehidden)
|
includehidden=includehidden)
|
||||||
@ -621,7 +613,7 @@ class BuildEnvironment:
|
|||||||
|
|
||||||
def check_consistency(self) -> None:
|
def check_consistency(self) -> None:
|
||||||
"""Do consistency checks."""
|
"""Do consistency checks."""
|
||||||
included = set().union(*self.included.values()) # type: ignore
|
included = set().union(*self.included.values())
|
||||||
for docname in sorted(self.all_docs):
|
for docname in sorted(self.all_docs):
|
||||||
if docname not in self.files_to_rebuild:
|
if docname not in self.files_to_rebuild:
|
||||||
if docname == self.config.root_doc:
|
if docname == self.config.root_doc:
|
||||||
|
@ -1,9 +1 @@
|
|||||||
"""
|
"""Sphinx environment adapters"""
|
||||||
sphinx.environment.adapters
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Sphinx environment adapters
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
"""
|
"""Assets adapter for sphinx.environment."""
|
||||||
sphinx.environment.adapters.asset
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
Assets adapter for sphinx.environment.
|
|
||||||
|
|
||||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
|
||||||
:license: BSD, see LICENSE for details.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from sphinx.environment import BuildEnvironment
|
from sphinx.environment import BuildEnvironment
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user