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:
|
||||
test:
|
||||
if: github.repository_owner == 'sphinx-doc'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
1
.github/workflows/lock.yml
vendored
1
.github/workflows/lock.yml
vendored
@ -10,6 +10,7 @@ permissions:
|
||||
|
||||
jobs:
|
||||
action:
|
||||
if: github.repository_owner == 'sphinx-doc'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- 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
|
||||
|
||||
windows:
|
||||
runs-on: windows-latest
|
||||
runs-on: windows-2019
|
||||
strategy:
|
||||
matrix:
|
||||
architecture: [x86, x64]
|
||||
|
5
.github/workflows/nodejs.yml
vendored
5
.github/workflows/nodejs.yml
vendored
@ -6,14 +6,15 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
node-version: 10.7
|
||||
node-version: 16
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ env.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: ${{ env.node-version }}
|
||||
cache: "npm"
|
||||
- run: npm install
|
||||
- name: Run headless test
|
||||
uses: GabrielBB/xvfb-action@v1
|
||||
|
6
.github/workflows/transifex.yml
vendored
6
.github/workflows/transifex.yml
vendored
@ -7,12 +7,13 @@ on:
|
||||
|
||||
jobs:
|
||||
push:
|
||||
if: github.repository_owner == 'sphinx-doc'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: 4.x
|
||||
ref: 5.x
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
@ -27,12 +28,13 @@ jobs:
|
||||
TX_TOKEN: ${{ secrets.TX_TOKEN }}
|
||||
|
||||
pull:
|
||||
if: github.repository_owner == 'sphinx-doc'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: 4.x
|
||||
ref: 5.x
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
|
2
AUTHORS
2
AUTHORS
@ -18,6 +18,7 @@ Other co-maintainers:
|
||||
|
||||
Other contributors, listed alphabetically, are:
|
||||
|
||||
* Adam Turner -- JavaScript improvements
|
||||
* Alastair Houghton -- Apple Help builder
|
||||
* Alexander Todorov -- inheritance_diagram tests and improvements
|
||||
* Andi Albrecht -- agogo theme
|
||||
@ -73,6 +74,7 @@ Other contributors, listed alphabetically, are:
|
||||
* Pauli Virtanen -- autodoc improvements, autosummary extension
|
||||
* Eric N. Vander Weele -- autodoc improvements
|
||||
* Stefan van der Walt -- autosummary extension
|
||||
* Hugo van Kemenade -- support FORCE_COLOR and NO_COLOR
|
||||
* Thomas Waldmann -- apidoc module fixes
|
||||
* John Waltman -- Texinfo builder
|
||||
* 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
|
||||
@ -13,18 +103,118 @@ Deprecated
|
||||
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
|
||||
``__all__`` attribute if :confval:`autosummary_ignore_module_all` is set to
|
||||
``False``. The default behaviour is unchanged. Autogen also now supports
|
||||
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
|
||||
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
|
||||
layout via CSS
|
||||
* #9827: i18n: Sort items in glossary by translated terms
|
||||
* #9899: py domain: Allows to specify cross-reference specifier (``.`` and
|
||||
``~``) as ``:type:`` option
|
||||
* #9792: autodoc: Add new option for ``autodoc_typehints_description_target`` to
|
||||
include undocumented return values but not undocumented parameters.
|
||||
* #9894: linkcheck: add option ``linkcheck_exclude_documents`` to disable link
|
||||
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
|
||||
----------
|
||||
@ -33,32 +223,42 @@ Bugs fixed
|
||||
* #9883: autodoc: doccomment for the alias to mocked object was ignored
|
||||
* #9908: autodoc: debug message is shown on building document using NewTypes
|
||||
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
|
||||
* #9932: napoleon: empty "returns" section is generated even if no description
|
||||
* #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 (in development)
|
||||
==============================
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Incompatible changes
|
||||
--------------------
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
Features added
|
||||
--------------
|
||||
Release 4.3.2 (released Dec 19, 2021)
|
||||
=====================================
|
||||
|
||||
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)
|
||||
=====================================
|
||||
@ -75,7 +275,7 @@ Bugs fixed
|
||||
* #9838: autodoc: AttributeError is raised on building document for functions
|
||||
decorated by functools.lru_cache
|
||||
* #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
|
||||
:confval:`autodoc_preserve_defaults` enabled
|
||||
* #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
|
||||
* #9756: autodoc: Crashed if classmethod does not have __func__ attribute
|
||||
* #9757: autodoc: :confval:`autodoc_inherit_docstrings` does not effect to
|
||||
overriden classmethods
|
||||
overridden classmethods
|
||||
* #9781: autodoc: :confval:`autodoc_preserve_defaults` does not support
|
||||
hexadecimal numeric
|
||||
* #9630: autosummary: Failed to build summary table if :confval:`primary_domain`
|
||||
|
88
EXAMPLES
88
EXAMPLES
@ -15,9 +15,11 @@ Documentation using the alabaster theme
|
||||
* `Alabaster <https://alabaster.readthedocs.io/>`__
|
||||
* `Blinker <https://pythonhosted.org/blinker/>`__
|
||||
* `Calibre <https://manual.calibre-ebook.com/>`__
|
||||
* `CherryPy <https://cherrypy.readthedocs.io/>`__
|
||||
* `Click <https://click.palletsprojects.com/>`__ (customized)
|
||||
* `coala <https://docs.coala.io/>`__ (customized)
|
||||
* `CodePy <https://documen.tician.de/codepy/>`__
|
||||
* `Django Q <https://django-q.readthedocs.io/>`__
|
||||
* `Eve <https://docs.python-eve.org/>`__ (Python REST API framework)
|
||||
* `Fabric <https://docs.fabfile.org/>`__
|
||||
* `Fityk <https://fityk.nieto.pl/>`__
|
||||
@ -30,19 +32,21 @@ Documentation using the alabaster theme
|
||||
* `MDAnalysis <https://www.mdanalysis.org/docs/>`__ (customized)
|
||||
* `MeshPy <https://documen.tician.de/meshpy/>`__
|
||||
* `Molecule <https://molecule.readthedocs.io/>`__
|
||||
* `Momotor LTI <https://momotor.org/doc/lti/canvas/>`__
|
||||
* `Podman <https://docs.podman.io/>`__
|
||||
* `PyCUDA <https://documen.tician.de/pycuda/>`__
|
||||
* `PyOpenCL <https://documen.tician.de/pyopencl/>`__
|
||||
* `PyLangAcq <https://pylangacq.org/>`__
|
||||
* `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/>`__
|
||||
* `Requests <http://www.python-requests.org/>`__
|
||||
* `Requests <https://docs.python-requests.org/>`__
|
||||
* `searx <https://asciimoo.github.io/searx/>`__
|
||||
* `Spyder <https://docs.spyder-ide.org/>`__ (customized)
|
||||
* `Tablib <http://docs.python-tablib.org/>`__
|
||||
* `urllib3 <https://urllib3.readthedocs.io/>`__ (customized)
|
||||
* `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
|
||||
-------------------------------------
|
||||
@ -58,8 +62,6 @@ Documentation using the classic theme
|
||||
* `Buildbot <https://docs.buildbot.net/latest/>`__
|
||||
* `CMake <https://cmake.org/documentation/>`__ (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/>`__
|
||||
* `DEAP <https://deap.readthedocs.io/>`__ (customized)
|
||||
* `Director <https://pythonhosted.org/director/>`__
|
||||
@ -67,27 +69,26 @@ Documentation using the classic theme
|
||||
* `F2py <http://f2py.sourceforge.net/docs/>`__
|
||||
* `Generic Mapping Tools (GMT) <https://gmt.soest.hawaii.edu/doc/latest/>`__ (customized)
|
||||
* `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)
|
||||
* `Grok <http://grok.zope.org/doc/current/>`__ (customized)
|
||||
* `GROMACS <https://manual.gromacs.org/documentation/>`__
|
||||
* `GSL Shell <https://www.nongnu.org/gsl-shell/>`__
|
||||
* `Hands-on Python Tutorial <https://anh.cs.luc.edu/python/hands-on/3.1/handsonHtml/>`__
|
||||
* `Kaa <https://api.freevo.org/kaa-base/>`__ (customized)
|
||||
* `Leo <https://leoeditor.com/>`__
|
||||
* `LEPL <http://www.acooke.org/lepl/>`__ (customized)
|
||||
* `Hands-on Python Tutorial <http://anh.cs.luc.edu/python/hands-on/3.1/handsonHtml/>`__
|
||||
* `Kaa <https://freevo.github.io/kaa-base/>`__ (customized)
|
||||
* `Leo <https://leoeditor.com/>`__ (customized)
|
||||
* `Mayavi <https://docs.enthought.com/mayavi/mayavi/>`__ (customized)
|
||||
* `MediaGoblin <https://mediagoblin.readthedocs.io/>`__ (customized)
|
||||
* `mpmath <https://mpmath.org/doc/current/>`__
|
||||
* `OpenCV <https://docs.opencv.org/>`__ (customized)
|
||||
* `OpenEXR <https://excamera.com/articles/26/doc/index.html>`__
|
||||
* `OpenGDA <http://www.opengda.org/gdadoc/html/>`__
|
||||
* `Peach^3 <https://peach3.nl/doc/latest/userdoc/>`__ (customized)
|
||||
* `OpenGDA <http://www.opengda.org/documentation/>`__
|
||||
* `phpDocumentor <https://docs.phpdoc.org/>`__ (customized)
|
||||
* `Plone <https://docs.plone.org/>`__ (customized)
|
||||
* `PyEMD <https://pyemd.readthedocs.io/>`__
|
||||
* `Pyevolve <http://pyevolve.sourceforge.net/>`__
|
||||
* `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)
|
||||
* `PyQt5 <http://pyqt.sourceforge.net/Docs/PyQt5/>`__ (customized)
|
||||
* `Python 2 <https://docs.python.org/2/>`__
|
||||
@ -120,7 +121,8 @@ Documentation using the sphinxdoc theme
|
||||
* `MDAnalysis Tutorial <https://www.mdanalysis.org/MDAnalysisTutorial/>`__
|
||||
* `NetworkX <https://networkx.github.io/>`__
|
||||
* `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/>`__
|
||||
* `Pysparse <http://pysparse.sourceforge.net/>`__
|
||||
* `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/>`__
|
||||
* `Cython <https://docs.cython.org/>`__
|
||||
* `easybuild <https://easybuild.readthedocs.io/>`__
|
||||
* `jsFiddle <http://doc.jsfiddle.net/>`__
|
||||
* `libLAS <https://www.liblas.org/>`__ (customized)
|
||||
* `libLAS <https://liblas.org/>`__ (customized)
|
||||
* `Lmod <https://lmod.readthedocs.io/>`__
|
||||
* `MapServer <https://mapserver.org/>`__ (customized)
|
||||
* `Pandas <https://pandas.pydata.org/pandas-docs/stable/>`__
|
||||
@ -154,11 +155,10 @@ Documentation using another builtin theme
|
||||
* `Breathe <https://breathe.readthedocs.io/>`__ (haiku)
|
||||
* `MPipe <https://vmlaker.github.io/mpipe/>`__ (sphinx13)
|
||||
* `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)
|
||||
* `Pylons <https://docs.pylonsproject.org/projects/pylons-webframework/>`__ (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) :-)
|
||||
* `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/>`__
|
||||
* `Blocks <https://blocks.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)
|
||||
* `CherryPy <https://docs.cherrypy.org/>`__
|
||||
* `citeproc-js <https://citeproc-js.readthedocs.io/>`__
|
||||
* `cloud-init <https://cloudinit.readthedocs.io/>`__
|
||||
* `CodeIgniter <https://www.codeigniter.com/user_guide/>`__
|
||||
* `Conda <https://conda.io/docs/>`__
|
||||
@ -187,7 +190,9 @@ Documentation using sphinx_rtd_theme
|
||||
* `Databricks <https://docs.databricks.com/>`__ (customized)
|
||||
* `Dataiku DSS <https://doc.dataiku.com/>`__
|
||||
* `DNF <https://dnf.readthedocs.io/>`__
|
||||
* `Distro Tracker <https://qa.pages.debian.net/distro-tracker/>`__
|
||||
* `Django-cas-ng <https://djangocas.dev/docs/>`__
|
||||
* `dj-stripe <https://dj-stripe.readthedocs.io/>`__
|
||||
* `edX <https://docs.edx.org/>`__
|
||||
* `Electrum <https://docs.electrum.org/>`__
|
||||
* `Elemental <https://libelemental.org/documentation/dev/>`__
|
||||
@ -207,13 +212,15 @@ Documentation using sphinx_rtd_theme
|
||||
* `Graylog <https://docs.graylog.org/>`__
|
||||
* `GPAW <https://wiki.fysik.dtu.dk/gpaw/>`__ (customized)
|
||||
* `HDF5 for Python (h5py) <https://docs.h5py.org/>`__
|
||||
* `HyperKitty <https://hyperkitty.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/>`__
|
||||
* `Idris <https://docs.idris-lang.org/>`__
|
||||
* `Inkscape <https://inkscape-manuals.readthedocs.io/>`__ (customized)
|
||||
* `javasphinx <https://bronto-javasphinx.readthedocs.io/>`__
|
||||
* `Julia <https://julia.readthedocs.io/>`__
|
||||
* `Jupyter Notebook <https://jupyter-notebook.readthedocs.io/>`__
|
||||
* `Kanboard <https://docs.kanboard.org/>`__
|
||||
* `Lasagne <https://lasagne.readthedocs.io/>`__
|
||||
* `latexindent.pl <https://latexindentpl.readthedocs.io/>`__
|
||||
* `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/>`__
|
||||
* `micca - MICrobial Community Analysis <https://micca.readthedocs.io/>`__
|
||||
* `MicroPython <https://docs.micropython.org/>`__
|
||||
* `Minds <https://www.minds.org/docs/>`__ (customized)
|
||||
* `Mink <https://mink.behat.org/>`__
|
||||
* `Mockery <https://docs.mockery.io/>`__
|
||||
* `mod_wsgi <https://modwsgi.readthedocs.io/>`__
|
||||
@ -234,9 +240,14 @@ Documentation using sphinx_rtd_theme
|
||||
* `Mopidy <https://docs.mopidy.com/>`__
|
||||
* `mpi4py <https://mpi4py.readthedocs.io/>`__
|
||||
* `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>`__
|
||||
* `nghttp2 <https://nghttp2.org/documentation/>`__
|
||||
* `NICOS <https://forge.frm2.tum.de/nicos/doc/nicos-master/>`__ (customized)
|
||||
* `OpenFAST <https://openfast.readthedocs.io/>`__
|
||||
* `Panda3D <https://docs.panda3d.org/>`__ (customized)
|
||||
* `Pelican <https://docs.getpelican.com/>`__
|
||||
* `picamera <https://picamera.readthedocs.io/>`__
|
||||
* `Pillow <https://pillow.readthedocs.io/>`__
|
||||
@ -245,15 +256,21 @@ Documentation using sphinx_rtd_theme
|
||||
* `peewee <https://docs.peewee-orm.com/>`__
|
||||
* `Phinx <https://docs.phinx.org/>`__
|
||||
* `phpMyAdmin <https://docs.phpmyadmin.net/>`__
|
||||
* `PHPUnit <https://phpunit.readthedocs.io/>`__
|
||||
* `PHPWord <https://phpword.readthedocs.io/>`__
|
||||
* `PROS <https://pros.cs.purdue.edu/v5/>`__ (customized)
|
||||
* `Pushkin <http://docs.pushkin.io/>`__
|
||||
* `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/>`__
|
||||
* `python-sqlparse <https://sqlparse.readthedocs.io/>`__
|
||||
* `PyVISA <https://pyvisa.readthedocs.io/>`__
|
||||
* `pyvista <https://docs.pyvista.org/>`__
|
||||
* `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)
|
||||
* `Releases Sphinx extension <https://releases.readthedocs.io/>`__
|
||||
* `Qtile <https://docs.qtile.org/>`__
|
||||
@ -269,6 +286,7 @@ Documentation using sphinx_rtd_theme
|
||||
* `Sonos Controller (SoCo) <https://docs.python-soco.com/>`__
|
||||
* `Sphinx AutoAPI <https://sphinx-autoapi.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 with Github Webpages <https://runawayhorse001.github.io/SphinxGithub>`__
|
||||
* `SpotBugs <https://spotbugs.readthedocs.io/>`__
|
||||
@ -281,15 +299,18 @@ Documentation using sphinx_rtd_theme
|
||||
* `Topshelf <https://docs.topshelf-project.com/>`__
|
||||
* `Theano <http://www.deeplearning.net/software/theano/>`__
|
||||
* `ThreatConnect <https://docs.threatconnect.com/>`__
|
||||
* `TrueNAS <https://www.ixsystems.com/documentation/truenas/>`__ (customized)
|
||||
* `Tuleap <https://tuleap.net/doc/en/>`__
|
||||
* `TYPO3 <https://docs.typo3.org/>`__ (customized)
|
||||
* `Veyon <https://docs.veyon.io/>`__
|
||||
* `Ubiquity <https://micro-framework.readthedocs.io/>`__
|
||||
* `uWSGI <https://uwsgi-docs.readthedocs.io/>`__
|
||||
* `virtualenv <https://virtualenv.readthedocs.io/>`__
|
||||
* `Wagtail <https://docs.wagtail.io/>`__
|
||||
* `Web Application Attack and Audit Framework (w3af) <https://docs.w3af.org/>`__
|
||||
* `Weblate <https://docs.weblate.org/>`__
|
||||
* `x265 <https://x265.readthedocs.io/>`__
|
||||
* `Zeek <https://docs.zeek.org/>`__
|
||||
* `Zulip <https://zulip.readthedocs.io/>`__
|
||||
|
||||
Documentation using sphinx_bootstrap_theme
|
||||
@ -317,12 +338,12 @@ Documentation using a custom theme or integrated in a website
|
||||
* `Bokeh <https://bokeh.pydata.org/>`__
|
||||
* `Boto 3 <https://boto3.readthedocs.io/>`__
|
||||
* `CakePHP <https://book.cakephp.org/>`__
|
||||
* `CasperJS <http://docs.casperjs.org/>`__
|
||||
* `Ceph <https://docs.ceph.com/docs/master/>`__
|
||||
* `Chef <https://docs.chef.io/>`__
|
||||
* `CKAN <https://docs.ckan.org/>`__
|
||||
* `Confluent Platform <https://docs.confluent.io/>`__
|
||||
* `Django <https://docs.djangoproject.com/>`__
|
||||
* `django CMS <https://docs.django-cms.org/>`__
|
||||
* `Doctrine <https://www.doctrine-project.org/>`__
|
||||
* `Enterprise Toolkit for Acrobat products <https://www.adobe.com/devnet-docs/acrobatetk/>`__
|
||||
* `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/>`__
|
||||
* `H2O.ai <https://docs.h2o.ai/>`__
|
||||
* `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/>`__
|
||||
* `Kombu <http://docs.kombu.me/>`__
|
||||
* `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/>`__
|
||||
* `Open vSwitch <https://docs.openvswitch.org/>`__
|
||||
* `PlatformIO <https://docs.platformio.org/>`__
|
||||
* `Psycopg <https://www.psycopg.org/docs/>`__
|
||||
* `PyEphem <https://rhodesmill.org/pyephem/>`__
|
||||
* `Pygments <https://pygments.org/docs/>`__
|
||||
* `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
|
||||
-------------------------------------------
|
||||
|
||||
* `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)
|
||||
* `Benoit Boissinot <https://bboissin.appspot.com/>`__ (classic, customized)
|
||||
* `Computer Networks, Parallelization, and Simulation Laboratory (CNPSLab) <https://lab.miletic.net/>`__ (sphinx_rtd_theme)
|
||||
* `Deep Learning Tutorials <http://www.deeplearning.net/tutorial/>`__ (sphinxdoc)
|
||||
* `EBI Cloud Consultancy Team <https://tsi-ccdoc.readthedocs.io/>`__ (sphinx_rtd_theme)
|
||||
* `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)
|
||||
* `Loyola University Chicago COMP 339-439 Distributed Systems course <https://books.cs.luc.edu/distributedsystems/>`__ (sphinx_bootstrap_theme)
|
||||
* `Pylearn2 <http://www.deeplearning.net/software/pylearn2/>`__ (sphinxdoc, customized)
|
||||
* `Loyola University Chicago CS Academic Programs <https://academics.cs.luc.edu/index.html>`__ (sphinx_rtd_theme, customized)
|
||||
* `PyXLL <https://www.pyxll.com/>`__ (sphinx_bootstrap_theme, customized)
|
||||
* `SciPy Cookbook <https://scipy-cookbook.readthedocs.io/>`__ (sphinx_rtd_theme)
|
||||
* `Tech writer at work blog <https://blog.documatt.com/>`__ (custom theme)
|
||||
@ -444,6 +468,6 @@ Projects integrating Sphinx functionality
|
||||
* `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.
|
||||
|
||||
* `Spyder <https://docs.spyder-ide.org/help.html>`__, the Scientific Python Development Environment, uses Sphinx in its
|
||||
help pane to render rich documentation for functions, classes and methods
|
||||
* `Spyder <https://docs.spyder-ide.org/current/panes/help.html>`__, the Scientific Python Development
|
||||
Environment, uses Sphinx in its help pane to render rich documentation for functions, classes and methods
|
||||
automatically or on-demand.
|
||||
|
5
LICENSE
5
LICENSE
@ -1,7 +1,10 @@
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
# If false, do not generate in manual @ref nodes.
|
||||
#
|
||||
# texinfo_cross_references = False
|
||||
|
||||
# -- A random example -----------------------------------------------------
|
||||
|
||||
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"
|
||||
class="subscribeform">
|
||||
<input type="text" name="email" value="your@email"
|
||||
onfocus="$(this).val('');" />
|
||||
onfocus="this.value = ''" />
|
||||
<input type="submit" name="sub" value="Subscribe" />
|
||||
</form>
|
||||
</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
|
||||
<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>
|
||||
<script>
|
||||
// intelligent scrolling of the sidebar content
|
||||
$(window).scroll(function() {
|
||||
var sb = $('.sphinxsidebarwrapper');
|
||||
var win = $(window);
|
||||
var sbh = sb.height();
|
||||
var offset = $('.sphinxsidebar').position()['top'];
|
||||
var wintop = win.scrollTop();
|
||||
var winbot = wintop + win.innerHeight();
|
||||
var curtop = sb.position()['top'];
|
||||
var curbot = curtop + sbh;
|
||||
window.onscroll = () => {
|
||||
const sb = document.getElementsByClassName('sphinxsidebarwrapper')[0]
|
||||
const sbh = sb.offsetHeight
|
||||
const offset = document.getElementsByClassName('sphinxsidebar')[0].offsetTop;
|
||||
const wintop = window.scrollTop;
|
||||
const winbot = wintop + window.offsetHeight
|
||||
const curtop = sb.offsetTop;
|
||||
const curbot = curtop + sbh;
|
||||
// does sidebar fit in window?
|
||||
if (sbh < win.innerHeight()) {
|
||||
if (sbh < window.offsetHeight) {
|
||||
// yes: easy case -- always keep at the top
|
||||
sb.css('top', $u.min([$u.max([0, wintop - offset - 10]),
|
||||
$(document).height() - sbh - 200]));
|
||||
sb.style.top = Math.min(Math.max(0, wintop - offset - 10), window.innerHeight - sbh - 200)
|
||||
} else {
|
||||
// no: only scroll if top/bottom edge of sidebar is at
|
||||
// top/bottom edge of window
|
||||
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) {
|
||||
sb.css('top', $u.min([winbot - sbh - offset - 20,
|
||||
$(document).height() - sbh - 200]));
|
||||
sb.style.top = Math.min(winbot - sbh - offset - 20, window.innerHeight - sbh - 200)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
{%- endif %}
|
||||
{% endblock %}
|
||||
|
2
doc/_themes/sphinx13/theme.conf
vendored
2
doc/_themes/sphinx13/theme.conf
vendored
@ -1,4 +1,4 @@
|
||||
[theme]
|
||||
inherit = basic
|
||||
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
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
import sphinx
|
||||
@ -14,7 +15,7 @@ templates_path = ['_templates']
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
project = 'Sphinx'
|
||||
copyright = '2007-2021, Georg Brandl and the Sphinx team'
|
||||
copyright = '2007-2022, Georg Brandl and the Sphinx team'
|
||||
version = sphinx.__display_version__
|
||||
release = version
|
||||
show_authors = True
|
||||
@ -81,11 +82,11 @@ autodoc_member_order = 'groupwise'
|
||||
autosummary_generate = False
|
||||
todo_include_todos = True
|
||||
extlinks = {'duref': ('https://docutils.sourceforge.io/docs/ref/rst/'
|
||||
'restructuredtext.html#%s', ''),
|
||||
'restructuredtext.html#%s', '%s'),
|
||||
'durole': ('https://docutils.sourceforge.io/docs/ref/rst/'
|
||||
'roles.html#%s', ''),
|
||||
'roles.html#%s', '%s'),
|
||||
'dudir': ('https://docutils.sourceforge.io/docs/ref/rst/'
|
||||
'directives.html#%s', '')}
|
||||
'directives.html#%s', '%s')}
|
||||
|
||||
man_pages = [
|
||||
('contents', 'sphinx-all', 'Sphinx documentation generator system manual',
|
||||
@ -108,7 +109,8 @@ texinfo_documents = [
|
||||
|
||||
intersphinx_mapping = {
|
||||
'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:
|
||||
@ -138,10 +140,33 @@ def parse_event(env, sig, signode):
|
||||
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):
|
||||
from sphinx.ext.autodoc import cut_lines
|
||||
from sphinx.util.docfields import GroupedField
|
||||
app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
|
||||
app.connect('source-read', linkify_issues_in_changelog)
|
||||
app.add_object_type('confval', 'confval',
|
||||
objname='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
|
||||
-----------------------------------------
|
||||
|
||||
As a way to distribute your theme, you can use Python package. Python package
|
||||
brings to users easy setting up ways.
|
||||
As a way to distribute your theme, you can use a Python package. This makes it
|
||||
easier for users to set up your theme.
|
||||
|
||||
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()``
|
||||
@ -285,7 +285,7 @@ engine, allowing you to embed variables and control behavior.
|
||||
|
||||
For example, the following JavaScript structure:
|
||||
|
||||
.. code-block:: bash
|
||||
.. code-block:: none
|
||||
|
||||
mymodule/
|
||||
├── _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:
|
||||
|
||||
.. code-block:: bash
|
||||
.. code-block:: none
|
||||
|
||||
_build/
|
||||
└── html
|
||||
|
@ -9,7 +9,7 @@ from sphinx.ext.autodoc import ClassDocumenter, bool_option
|
||||
|
||||
class IntEnumDocumenter(ClassDocumenter):
|
||||
objtype = 'intenum'
|
||||
directivetype = 'class'
|
||||
directivetype = ClassDocumenter.objtype
|
||||
priority = 10 + ClassDocumenter.priority
|
||||
option_spec = dict(ClassDocumenter.option_spec)
|
||||
option_spec['hex'] = bool_option
|
||||
@ -18,7 +18,10 @@ class IntEnumDocumenter(ClassDocumenter):
|
||||
def can_document_member(cls,
|
||||
member: Any, membername: str,
|
||||
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:
|
||||
super().add_directive_header(sig)
|
||||
@ -36,14 +39,13 @@ class IntEnumDocumenter(ClassDocumenter):
|
||||
use_hex = self.options.hex
|
||||
self.add_line('', source_name)
|
||||
|
||||
for enum_value in enum_object:
|
||||
the_value_name = enum_value.name
|
||||
the_value_value = enum_value.value
|
||||
for the_member_name, enum_member in enum_object.__members__.items():
|
||||
the_member_value = enum_member.value
|
||||
if use_hex:
|
||||
the_value_value = hex(the_value_value)
|
||||
the_member_value = hex(the_member_value)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
|
@ -87,7 +87,7 @@ class RecipeIndex(Index):
|
||||
# first letter of the recipe as a key to group thing
|
||||
#
|
||||
# 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(
|
||||
(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
|
||||
: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
|
||||
|
||||
|
@ -22,6 +22,31 @@ The following is a list of deprecated interfaces.
|
||||
- (will be) Removed
|
||||
- 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``
|
||||
- 4.3
|
||||
- 6.0
|
||||
|
@ -35,3 +35,4 @@ to configure their settings appropriately.
|
||||
.. module:: sphinx.parsers
|
||||
|
||||
.. 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`
|
||||
|
||||
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
|
||||
``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
|
||||
@ -346,19 +350,3 @@ The following notes may be helpful if you want to create Texinfo files:
|
||||
scheme ``info``. For example::
|
||||
|
||||
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>
|
||||
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.
|
||||
|
||||
.. _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
|
||||
<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
|
||||
------------------
|
||||
|
||||
|
@ -75,7 +75,7 @@ and assuming ``docs/index.rst`` contained the following:
|
||||
|
||||
If you run the following:
|
||||
|
||||
.. code-block:: bash
|
||||
.. code-block:: console
|
||||
|
||||
$ PYTHONPATH=. sphinx-autogen docs/index.rst
|
||||
|
||||
|
@ -304,6 +304,22 @@ variables to customize behavior:
|
||||
Additional options for :program:`sphinx-build`. These options can
|
||||
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:
|
||||
|
||||
Deprecation Warnings
|
||||
|
@ -4,10 +4,9 @@ Automatic documentation generation from code
|
||||
In the :ref:`previous section <tutorial-describing-objects>` of the tutorial
|
||||
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
|
||||
the same. Besides, it would be nice to reuse `Python
|
||||
docstrings <https://www.python.org/dev/peps/pep-0257/#what-is-a-docstring>`_
|
||||
in the documentation, rather than having to write the information in two
|
||||
places.
|
||||
the same. Besides, it would be nice to reuse :pep:`Python docstrings
|
||||
<257#what-is-a-docstring>` in the documentation, rather than having to write
|
||||
the information in two places.
|
||||
|
||||
Fortunately, :doc:`the autodoc extension </usage/extensions/autodoc>` provides this
|
||||
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
|
||||
highlighted the module, the function name, and the parameters appropriately.
|
||||
- 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.
|
||||
|
||||
.. note::
|
||||
|
@ -35,4 +35,5 @@ project.
|
||||
narrative-documentation
|
||||
describing-code
|
||||
automatic-doc-generation
|
||||
deploying
|
||||
end
|
||||
|
@ -68,6 +68,24 @@ be translated you need to follow these instructions:
|
||||
* 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
|
||||
----------------------------
|
||||
|
||||
|
@ -6,6 +6,10 @@ Setuptools integration
|
||||
Sphinx supports integration with setuptools and distutils through a custom
|
||||
command - :class:`~sphinx.setup_command.BuildDoc`.
|
||||
|
||||
.. deprecated:: 5.0
|
||||
|
||||
This feature will be removed in v7.0.
|
||||
|
||||
Using setuptools integration
|
||||
----------------------------
|
||||
|
||||
@ -64,7 +68,7 @@ Options for setuptools integration
|
||||
|
||||
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
|
||||
|
||||
@ -75,7 +79,7 @@ Options for setuptools integration
|
||||
|
||||
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
|
||||
|
||||
@ -88,7 +92,7 @@ Options for setuptools integration
|
||||
|
||||
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
|
||||
|
||||
@ -105,7 +109,7 @@ Options for setuptools integration
|
||||
|
||||
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
|
||||
|
||||
@ -117,7 +121,7 @@ Options for setuptools integration
|
||||
|
||||
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
|
||||
|
||||
@ -131,7 +135,7 @@ Options for setuptools integration
|
||||
|
||||
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
|
||||
|
||||
@ -169,7 +173,7 @@ Options for setuptools integration
|
||||
|
||||
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
|
||||
|
||||
|
@ -316,7 +316,11 @@ General configuration
|
||||
* ``app.add_role``
|
||||
* ``app.add_generic_role``
|
||||
* ``app.add_source_parser``
|
||||
* ``autosectionlabel.*``
|
||||
* ``download.not_readable``
|
||||
* ``epub.unknown_project_files``
|
||||
* ``epub.duplicated_toc_entry``
|
||||
* ``i18n.inconsistent_references``
|
||||
* ``image.not_readable``
|
||||
* ``ref.term``
|
||||
* ``ref.ref``
|
||||
@ -332,11 +336,9 @@ General configuration
|
||||
* ``toc.excluded``
|
||||
* ``toc.not_readable``
|
||||
* ``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*.
|
||||
|
||||
@ -366,6 +368,10 @@ General configuration
|
||||
|
||||
Added ``toc.excluded`` and ``toc.not_readable``
|
||||
|
||||
.. versionadded:: 4.5
|
||||
|
||||
Added ``i18n.inconsistent_references``
|
||||
|
||||
.. confval:: needs_sphinx
|
||||
|
||||
If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will
|
||||
@ -392,7 +398,7 @@ General configuration
|
||||
|
||||
.. 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
|
||||
:literal:`:manpage:`man(1)`` role will link to
|
||||
<https://manpages.debian.org/man(1)>. The patterns available are:
|
||||
@ -1351,6 +1357,13 @@ that use Sphinx's HTMLWriter class.
|
||||
|
||||
.. 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
|
||||
|
||||
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
|
||||
|
||||
.. 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:
|
||||
|
||||
@ -2683,6 +2703,19 @@ Options for the linkcheck builder
|
||||
|
||||
.. 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
|
||||
---------------------------
|
||||
|
@ -41,7 +41,7 @@ you can also enable the :mod:`napoleon <sphinx.ext.napoleon>` extension.
|
||||
docstrings to correct reStructuredText before :mod:`autodoc` processes them.
|
||||
|
||||
.. _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
|
||||
@ -468,7 +468,7 @@ There are also config values that you can set:
|
||||
|
||||
.. 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:
|
||||
|
||||
``"mixed"``
|
||||
@ -528,7 +528,8 @@ There are also config values that you can set:
|
||||
The supported options are ``'members'``, ``'member-order'``,
|
||||
``'undoc-members'``, ``'private-members'``, ``'special-members'``,
|
||||
``'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
|
||||
|
||||
@ -541,6 +542,9 @@ There are also config values that you can set:
|
||||
.. versionchanged:: 4.1
|
||||
Added ``'class-doc-from'``.
|
||||
|
||||
.. versionchanged:: 4.5
|
||||
Added ``'no-value'``.
|
||||
|
||||
.. confval:: autodoc_docstring_signature
|
||||
|
||||
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
|
||||
the document. Defaults to empty (``{}``).
|
||||
|
||||
The type aliases are only available if your program enables `Postponed
|
||||
Evaluation of Annotations (PEP 563)`__ feature via ``from __future__ import
|
||||
The type aliases are only available if your program enables :pep:`Postponed
|
||||
Evaluation of Annotations (PEP 563) <563>` feature via ``from __future__ import
|
||||
annotations``.
|
||||
|
||||
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
|
||||
.. 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
|
||||
|
||||
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/method.rst` -- template for class methods
|
||||
|
||||
The following variables available in the templates:
|
||||
The following variables are available in the templates:
|
||||
|
||||
.. currentmodule:: None
|
||||
|
||||
@ -300,7 +300,7 @@ The following variables available in the templates:
|
||||
.. data:: functions
|
||||
|
||||
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.
|
||||
|
||||
.. data:: classes
|
||||
|
@ -93,8 +93,8 @@ a comma-separated list of group names.
|
||||
* ``<``, ``>``: Exclusive ordered comparison clause
|
||||
* ``===``: Arbitrary equality clause.
|
||||
|
||||
``pyversion`` option is followed `PEP-440: Version Specifiers
|
||||
<https://www.python.org/dev/peps/pep-0440/#version-specifiers>`__.
|
||||
``pyversion`` option is followed :pep:`PEP-440: Version Specifiers
|
||||
<440#version-specifiers>`.
|
||||
|
||||
.. versionadded:: 1.6
|
||||
|
||||
|
@ -45,7 +45,7 @@ on the first line, separated by a colon.
|
||||
def function_with_types_in_docstring(param1, param2):
|
||||
"""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
|
||||
included in the docstring:
|
||||
|
||||
@ -55,10 +55,6 @@ def function_with_types_in_docstring(param1, param2):
|
||||
|
||||
Returns:
|
||||
bool: The return value. True for success, False otherwise.
|
||||
|
||||
.. _PEP 484:
|
||||
https://www.python.org/dev/peps/pep-0484/
|
||||
|
||||
"""
|
||||
|
||||
|
||||
|
@ -37,8 +37,8 @@ module_level_variable1 : int
|
||||
with it.
|
||||
|
||||
|
||||
.. _NumPy Documentation HOWTO:
|
||||
https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
|
||||
.. _NumPy docstring standard:
|
||||
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):
|
||||
"""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
|
||||
included in the docstring:
|
||||
|
||||
@ -70,10 +70,6 @@ def function_with_types_in_docstring(param1, param2):
|
||||
-------
|
||||
bool
|
||||
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
|
||||
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
|
||||
|
||||
This extension can generate automatic links to the documentation of objects in
|
||||
other projects.
|
||||
This extension can generate links to the documentation of objects in external
|
||||
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
|
||||
matching target in the current documentation set, it looks for targets in the
|
||||
documentation sets configured in :confval:`intersphinx_mapping`. A reference
|
||||
like ``:py:class:`zipfile.ZipFile``` can then link to the Python documentation
|
||||
Usage for fallback resolution is simple: whenever Sphinx encounters a
|
||||
cross-reference that has no matching target in the current documentation set,
|
||||
it looks for targets in the external documentation sets configured in
|
||||
: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
|
||||
exactly.
|
||||
|
||||
When using the "new" format (see below), you can even force lookup in a foreign
|
||||
set by prefixing the link target appropriately. A link like ``:ref:`comparison
|
||||
manual <python:comparisons>``` will then link to the label "comparisons" in the
|
||||
doc set "python", if it exists.
|
||||
When using the :rst:role:`external` role, you can force lookup to any external
|
||||
projects, and optionally to a specific external project.
|
||||
A link like ``:external:ref:`comparison manual <comparisons>``` will then link
|
||||
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:
|
||||
|
||||
@ -30,8 +35,8 @@ Behind the scenes, this works as follows:
|
||||
|
||||
* Projects using the Intersphinx extension can specify the location of such
|
||||
mapping files in the :confval:`intersphinx_mapping` config value. The mapping
|
||||
will then be used to resolve otherwise missing references to objects into
|
||||
links to the other documentation.
|
||||
will then be used to resolve both :rst:role:`external` references, and also
|
||||
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
|
||||
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
|
||||
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
|
||||
``:ref:`comparison manual <python:comparisons>``` will link to the label
|
||||
"comparisons" in the doc set "python", if it exists.
|
||||
``external:python+ref:`comparison manual <comparisons>``` will link to the
|
||||
label "comparisons" in the doc set "python", if it exists.
|
||||
|
||||
**Example**
|
||||
|
||||
@ -152,6 +157,10 @@ linking:
|
||||
|
||||
.. versionadded:: 4.3
|
||||
|
||||
.. versionchanged:: 5.0
|
||||
|
||||
Changed default value from an empty list to ``['std:doc']``.
|
||||
|
||||
A list of strings being either:
|
||||
|
||||
- the name of a specific reference type in a domain,
|
||||
@ -160,23 +169,52 @@ linking:
|
||||
``std:*``, ``py:*``, or ``cpp:*``, or
|
||||
- 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
|
||||
resolved by intersphinx, skip resolution if it matches one of the
|
||||
specifications in this list.
|
||||
When a non-:rst:role:`external` cross-reference is being resolved by
|
||||
intersphinx, skip resolution if it matches one of the specifications in this
|
||||
list.
|
||||
|
||||
For example, with ``intersphinx_disabled_reftypes = ['std:doc']``
|
||||
a cross-reference ``:doc:`installation``` will not be attempted to be
|
||||
resolved by intersphinx, but ``:doc:`otherbook:installation``` will be
|
||||
attempted to be resolved in the inventory named ``otherbook`` in
|
||||
resolved by intersphinx, but ``:external+otherbook:doc:`installation``` will
|
||||
be attempted to be resolved in the inventory named ``otherbook`` in
|
||||
:confval:`intersphinx_mapping`.
|
||||
At the same time, all cross-references generated in, e.g., Python,
|
||||
declarations will still be attempted to be resolved by intersphinx.
|
||||
|
||||
If ``*`` is in the list of domains, then no references without an explicit
|
||||
inventory will be resolved by intersphinx.
|
||||
If ``*`` is in the list of domains, then no non-:rst:role:`external`
|
||||
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
|
||||
------------------------------------------------
|
||||
|
@ -26,7 +26,7 @@ Are you tired of writing docstrings that look like this::
|
||||
:rtype: BufferedFileStorage
|
||||
|
||||
`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`_::
|
||||
|
||||
Args:
|
||||
@ -50,7 +50,6 @@ the documentation, so it doesn't modify any of the docstrings in your actual
|
||||
source code files.
|
||||
|
||||
.. _ReStructuredText: https://docutils.sourceforge.io/rst.html
|
||||
.. _docstrings: https://www.python.org/dev/peps/pep-0287/
|
||||
.. _Google Python Style Guide:
|
||||
https://google.github.io/styleguide/pyguide.html
|
||||
.. _Google:
|
||||
@ -199,11 +198,11 @@ not be mixed. Choose one style for your project and be consistent with it.
|
||||
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.
|
||||
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
|
||||
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).
|
||||
|
||||
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
|
||||
supported by Sphinx and won't show up in the docs.
|
||||
|
||||
.. _PEP 484: https://www.python.org/dev/peps/pep-0484/
|
||||
.. _PEP 526: https://www.python.org/dev/peps/pep-0526/
|
||||
.. _Python 2/3 compatible annotations: https://www.python.org/dev/peps/pep-0484/#suggested-syntax-for-python-2-7-and-straddling-code
|
||||
.. _Python 2/3 compatible annotations: https://peps.python.org/pep-0484/#suggested-syntax-for-python-2-7-and-straddling-code
|
||||
|
||||
|
||||
Configuration
|
||||
@ -548,7 +545,7 @@ sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
|
||||
|
||||
.. 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
|
||||
has an annotation in the class body, that type is used.
|
||||
|
||||
|
@ -222,8 +222,8 @@ of images:
|
||||
- `sphinxdoc/sphinx-latexpdf`_
|
||||
|
||||
.. _Docker Hub: https://hub.docker.com/
|
||||
.. _sphinxdoc/sphinx: https://hub.docker.com/repository/docker/sphinxdoc/sphinx
|
||||
.. _sphinxdoc/sphinx-latexpdf: https://hub.docker.com/repository/docker/sphinxdoc/sphinx-latexpdf
|
||||
.. _sphinxdoc/sphinx: https://hub.docker.com/r/sphinxdoc/sphinx
|
||||
.. _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
|
||||
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
|
||||
project:
|
||||
|
||||
.. code-block:: bash
|
||||
.. code-block:: console
|
||||
|
||||
$ 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
|
||||
|
||||
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
|
||||
|
@ -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
|
||||
configuration values from a few questions it asks you. To use this, run:
|
||||
|
||||
.. code-block:: shell
|
||||
.. code-block:: console
|
||||
|
||||
$ 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
|
||||
docs. A build is started with the :program:`sphinx-build` program:
|
||||
|
||||
.. code-block:: shell
|
||||
.. code-block:: console
|
||||
|
||||
$ 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
|
||||
running :command:`make` with the name of the builder. For example.
|
||||
|
||||
.. code-block:: shell
|
||||
.. code-block:: console
|
||||
|
||||
$ make html
|
||||
|
||||
|
@ -245,10 +245,10 @@ follow:
|
||||
|
||||
* ``#`` with overline, for parts
|
||||
* ``*`` with overline, for chapters
|
||||
* ``=``, for sections
|
||||
* ``-``, for subsections
|
||||
* ``^``, for subsubsections
|
||||
* ``"``, for paragraphs
|
||||
* ``=`` for sections
|
||||
* ``-`` for subsections
|
||||
* ``^`` for subsubsections
|
||||
* ``"`` for paragraphs
|
||||
|
||||
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
|
||||
|
@ -598,6 +598,7 @@ __ https://pygments.org/docs/lexers
|
||||
are removed via :func:`textwrap.dedent()`. For example::
|
||||
|
||||
.. code-block:: ruby
|
||||
:linenos:
|
||||
:dedent: 4
|
||||
|
||||
some ruby code
|
||||
@ -831,6 +832,9 @@ Glossary
|
||||
.. versionchanged:: 1.4
|
||||
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
|
||||
-----------------------
|
||||
|
@ -211,6 +211,12 @@ The following directives are provided for module and class contents:
|
||||
|
||||
.. 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
|
||||
|
||||
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
|
||||
|
||||
.. 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
|
||||
|
||||
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
|
||||
|
||||
.. 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
|
||||
.. py:class:: name(parameters)
|
||||
|
||||
@ -291,6 +309,12 @@ The following directives are provided for module and class contents:
|
||||
|
||||
.. 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
|
||||
|
||||
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
|
||||
|
||||
.. 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
|
||||
|
||||
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
|
||||
: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)
|
||||
|
||||
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
|
||||
|
||||
.. 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
|
||||
: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
|
||||
as a Python package, you can use it after installing
|
||||
|
||||
.. code-block:: bash
|
||||
.. code-block:: console
|
||||
|
||||
# installing theme package
|
||||
$ 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
|
||||
want a width limit. Defaults may depend on the theme (often 800px).
|
||||
|
||||
- **navigation_with_keys** (true or false): Allow navigating to the
|
||||
previous/next page using the keyboard's left and right arrows. Defaults to
|
||||
``False``.
|
||||
- **navigation_with_keys** (true or false): Allow navigating
|
||||
with the following keyboard shortcuts:
|
||||
|
||||
- :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
|
||||
of the current document in ``globaltoc.html``
|
||||
|
@ -15,8 +15,6 @@ module.exports = function(config) {
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: [
|
||||
'sphinx/themes/basic/static/underscore.js',
|
||||
'sphinx/themes/basic/static/jquery.js',
|
||||
'sphinx/themes/basic/static/doctools.js',
|
||||
'sphinx/themes/basic/static/searchtools.js',
|
||||
'tests/js/*.js'
|
||||
@ -59,7 +57,7 @@ module.exports = function(config) {
|
||||
|
||||
// start these browsers
|
||||
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
||||
browsers: ['Chrome', 'Firefox'],
|
||||
browsers: ["Firefox"],
|
||||
|
||||
|
||||
// Continuous Integration mode
|
||||
|
2569
package-lock.json
generated
2569
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -12,9 +12,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"jasmine-core": "^3.4.0",
|
||||
"karma": "^4.0.0",
|
||||
"karma-chrome-launcher": "^3.0.0",
|
||||
"karma-firefox-launcher": "^1.1.0",
|
||||
"karma-jasmine": "^2.0.0"
|
||||
"karma": "^6.3.16",
|
||||
"karma-firefox-launcher": "^2.0.0",
|
||||
"karma-jasmine": "^4.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
[metadata]
|
||||
license_file = LICENSE
|
||||
license_files = LICENSE
|
||||
|
||||
[egg_info]
|
||||
tag_build = .dev
|
||||
@ -35,12 +35,6 @@ import-order-style = smarkets
|
||||
per-file-ignores =
|
||||
tests/*: E501
|
||||
|
||||
[flake8:local-plugins]
|
||||
extension =
|
||||
X101 = utils.checks:sphinx_has_header
|
||||
paths =
|
||||
.
|
||||
|
||||
[isort]
|
||||
line_length = 95
|
||||
|
||||
|
8
setup.py
8
setup.py
@ -1,6 +1,5 @@
|
||||
import os
|
||||
import sys
|
||||
from distutils import log
|
||||
from io import StringIO
|
||||
|
||||
from setuptools import find_packages, setup
|
||||
@ -29,8 +28,8 @@ install_requires = [
|
||||
'alabaster>=0.7,<0.8',
|
||||
'imagesize',
|
||||
'requests>=2.5.0',
|
||||
'setuptools',
|
||||
'packaging',
|
||||
"importlib-metadata>=4.4; python_version < '3.10'",
|
||||
]
|
||||
|
||||
extras_require = {
|
||||
@ -44,10 +43,9 @@ extras_require = {
|
||||
'lint': [
|
||||
'flake8>=3.5.0',
|
||||
'isort',
|
||||
'mypy>=0.900',
|
||||
'mypy>=0.931',
|
||||
'docutils-stubs',
|
||||
"types-typed-ast",
|
||||
"types-pkg_resources",
|
||||
"types-requests",
|
||||
],
|
||||
'test': [
|
||||
@ -149,7 +147,7 @@ else:
|
||||
if catalog.fuzzy and not self.use_fuzzy:
|
||||
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)
|
||||
|
||||
jscatalog = {}
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
Sphinx
|
||||
~~~~~~
|
||||
|
||||
The Sphinx documentation toolchain.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""The Sphinx documentation toolchain."""
|
||||
|
||||
# Keep this file executable as-is in Python 3!
|
||||
# (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",
|
||||
DeprecationWarning, module='docutils.io')
|
||||
|
||||
__version__ = '4.4.0+'
|
||||
__released__ = '4.4.0' # used when Sphinx builds its own docs
|
||||
__version__ = '5.0.0+'
|
||||
__released__ = '5.0.0' # used when Sphinx builds its own docs
|
||||
|
||||
#: Version info for better programmatic use.
|
||||
#:
|
||||
@ -38,7 +30,7 @@ __released__ = '4.4.0' # used when Sphinx builds its own docs
|
||||
#:
|
||||
#: .. versionadded:: 1.2
|
||||
#: 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__))
|
||||
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.__main__
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The Sphinx documentation toolchain.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""The Sphinx documentation toolchain."""
|
||||
|
||||
import sys
|
||||
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.addnodes
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Additional docutils nodes.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Additional docutils nodes."""
|
||||
|
||||
from typing import TYPE_CHECKING, Any, Dict, List, Sequence
|
||||
|
||||
@ -16,6 +8,13 @@ from docutils.nodes import Element
|
||||
if TYPE_CHECKING:
|
||||
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):
|
||||
"""The document root element patched by Sphinx.
|
||||
@ -85,7 +84,7 @@ class toctree(nodes.General, nodes.Element, translatable):
|
||||
def preserve_original_messages(self) -> None:
|
||||
# toctree entries
|
||||
rawentries = self.setdefault('rawentries', [])
|
||||
for title, docname in self['entries']:
|
||||
for title, _docname in self['entries']:
|
||||
if title:
|
||||
rawentries.append(title)
|
||||
|
||||
|
@ -1,18 +1,10 @@
|
||||
"""
|
||||
sphinx.application
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
"""Sphinx application class and extensibility interface.
|
||||
|
||||
Sphinx application class and extensibility interface.
|
||||
|
||||
Gracefully adapted from the TextPress system by Armin.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
Gracefully adapted from the TextPress system by Armin.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pickle
|
||||
import platform
|
||||
import sys
|
||||
import warnings
|
||||
from collections import deque
|
||||
@ -195,12 +187,6 @@ class Sphinx:
|
||||
# say hello to the world
|
||||
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
|
||||
self.statuscode = 0
|
||||
|
||||
@ -273,7 +259,7 @@ class Sphinx:
|
||||
"""Load translated strings from the configured localedirs if enabled in
|
||||
the configuration.
|
||||
"""
|
||||
if self.config.language is None:
|
||||
if self.config.language == 'en':
|
||||
self.translator, has_translation = locale.init([], None)
|
||||
else:
|
||||
logger.info(bold(__('loading translations [%s]... ') % self.config.language),
|
||||
@ -292,8 +278,7 @@ class Sphinx:
|
||||
locale_dirs += [path.join(package_dir, 'locale')]
|
||||
|
||||
self.translator, has_translation = locale.init(locale_dirs, self.config.language)
|
||||
if has_translation or self.config.language == 'en':
|
||||
# "en" never needs to be translated
|
||||
if has_translation:
|
||||
logger.info(__('done'))
|
||||
else:
|
||||
logger.info(__('not available for built-in messages'))
|
||||
@ -937,24 +922,31 @@ class Sphinx:
|
||||
"""
|
||||
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.
|
||||
|
||||
Add *filename* to the list of JavaScript files that the default HTML
|
||||
template will include in order of *priority* (ascending). The filename
|
||||
must be relative to the HTML static path , or a full URI with scheme.
|
||||
If the priority of the JavaScript file is the same as others, the JavaScript
|
||||
files will be included in order of registration. If the keyword
|
||||
argument ``body`` is given, its value will be added between the
|
||||
``<script>`` tags. Extra keyword arguments are included as attributes of
|
||||
the ``<script>`` tag.
|
||||
:param filename: The filename of the JavaScript file. It must be relative to the HTML
|
||||
static path, a full URI with scheme, or ``None`` value. The ``None``
|
||||
value is used to create inline ``<script>`` tag. See the description
|
||||
of *kwargs* below.
|
||||
:param priority: The priority to determine the order of ``<script>`` tag for
|
||||
JavaScript files. See list of "prority range for JavaScript
|
||||
files" below. If the priority of the JavaScript files it the same
|
||||
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::
|
||||
|
||||
app.add_js_file('example.js')
|
||||
# => <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>
|
||||
|
||||
app.add_js_file(None, body="var myVariable = 'foo';")
|
||||
@ -983,7 +975,15 @@ class Sphinx:
|
||||
|
||||
.. versionchanged:: 3.5
|
||||
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)
|
||||
if hasattr(self.builder, 'add_js_file'):
|
||||
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:
|
||||
"""Register a stylesheet to include in the HTML output.
|
||||
|
||||
Add *filename* to the list of CSS files that the default HTML template
|
||||
will include in order of *priority* (ascending). The filename must be
|
||||
relative to the HTML static path, or a full URI with scheme. If the
|
||||
priority of the CSS file is the same as others, the CSS files will be
|
||||
included in order of registration. The keyword arguments are also
|
||||
accepted for attributes of ``<link>`` tag.
|
||||
:param filename: The filename of the CSS file. It must be relative to the HTML
|
||||
static path, or a full URI with scheme.
|
||||
:param priority: The priority to determine the order of ``<link>`` tag for the
|
||||
CSS files. See list of "prority range for CSS files" below.
|
||||
If the priority of the CSS files it the same as others, the
|
||||
CSS files will be loaded in order of registration.
|
||||
:param kwargs: Extra keyword arguments are included as attributes of the ``<link>``
|
||||
tag.
|
||||
|
||||
Example::
|
||||
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.builders
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Builder superclass for all builders.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Builder superclass for all builders."""
|
||||
|
||||
import pickle
|
||||
import time
|
||||
@ -176,7 +168,7 @@ class Builder:
|
||||
def post_process_images(self, doctree: Node) -> None:
|
||||
"""Pick the best candidate for all image URIs."""
|
||||
images = ImageAdapter(self.env)
|
||||
for node in doctree.traverse(nodes.image):
|
||||
for node in doctree.findall(nodes.image):
|
||||
if '?' in node['candidates']:
|
||||
# don't rewrite nonlocal image URIs
|
||||
continue
|
||||
@ -562,7 +554,7 @@ class Builder:
|
||||
for chunk in status_iterator(chunks, __('writing output... '), "darkgreen",
|
||||
len(chunks), self.app.verbosity):
|
||||
arg = []
|
||||
for i, docname in enumerate(chunk):
|
||||
for docname in chunk:
|
||||
doctree = self.env.get_and_resolve_doctree(docname, self)
|
||||
self.write_doc_serialized(docname, doctree)
|
||||
arg.append((docname, doctree))
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
"""Base class of epub2/epub3 builders."""
|
||||
|
||||
import html
|
||||
import os
|
||||
@ -277,7 +269,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
new_ids.append(new_id)
|
||||
node['ids'] = new_ids
|
||||
|
||||
for reference in tree.traverse(nodes.reference):
|
||||
for reference in tree.findall(nodes.reference):
|
||||
if 'refuri' in reference:
|
||||
m = self.refuri_re.match(reference['refuri'])
|
||||
if m:
|
||||
@ -285,14 +277,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
if 'refid' in reference:
|
||||
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)
|
||||
|
||||
next_node: Node = target.next_node(ascend=True)
|
||||
if isinstance(next_node, nodes.Element):
|
||||
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)
|
||||
|
||||
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
|
||||
# b) place them after an (empty) Footnotes rubric
|
||||
# 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:
|
||||
fn = fns[-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:
|
||||
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.append(nodes.Text(FOOTNOTES_RUBRIC_NAME))
|
||||
doc.append(rub)
|
||||
@ -339,10 +331,10 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
if show_urls == 'no':
|
||||
return
|
||||
if show_urls == 'footnote':
|
||||
doc = list(tree.traverse(nodes.document))[0]
|
||||
doc = next(tree.findall(nodes.document))
|
||||
fn_spot, fn_idx = footnote_spot(tree)
|
||||
nr = 1
|
||||
for node in list(tree.traverse(nodes.reference)):
|
||||
for node in list(tree.findall(nodes.reference)):
|
||||
uri = node.get('refuri', '')
|
||||
if (uri.startswith('http:') or uri.startswith('https:') or
|
||||
uri.startswith('ftp:')) and uri not in node.astext():
|
||||
@ -377,14 +369,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
"""Fix href attributes for genindex pages."""
|
||||
# XXX: modifies tree inline
|
||||
# Logic modeled from themes/basic/genindex.html
|
||||
for key, columns in tree:
|
||||
for entryname, (links, subitems, key_) in columns:
|
||||
for _key, columns in tree:
|
||||
for _entryname, (links, subitems, _key) in columns:
|
||||
for (i, (ismain, link)) in enumerate(links):
|
||||
m = self.refuri_re.match(link)
|
||||
if m:
|
||||
links[i] = (ismain,
|
||||
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):
|
||||
m = self.refuri_re.match(link)
|
||||
if m:
|
||||
@ -703,7 +695,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
epub_filename = path.join(self.outdir, outname)
|
||||
with ZipFile(epub_filename, 'w', ZIP_DEFLATED) as epub:
|
||||
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)
|
||||
for filename in self.files:
|
||||
epub.write(path.join(self.outdir, filename), filename, ZIP_DEFLATED)
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.builders.changes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Changelog builder.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Changelog builder."""
|
||||
|
||||
import html
|
||||
from os import path
|
||||
@ -148,7 +140,7 @@ class ChangesBuilder(Builder):
|
||||
|
||||
def hl(self, text: str, version: str) -> str:
|
||||
text = html.escape(text)
|
||||
for directive in ['versionchanged', 'versionadded', 'deprecated']:
|
||||
for directive in ('versionchanged', 'versionadded', 'deprecated'):
|
||||
text = text.replace('.. %s:: %s' % (directive, version),
|
||||
'<b>.. %s:: %s</b>' % (directive, version))
|
||||
return text
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.builders.dirhtml
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Directory HTML builders.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Directory HTML builders."""
|
||||
|
||||
from os import path
|
||||
from typing import Any, Dict
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
"""Do syntax checks, but no writing."""
|
||||
|
||||
from typing import Any, Dict, Set
|
||||
|
||||
|
@ -1,12 +1,6 @@
|
||||
"""
|
||||
sphinx.builders.epub3
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
"""Build epub3 files.
|
||||
|
||||
Build epub3 files.
|
||||
Originally derived from epub.py.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
Originally derived from epub.py.
|
||||
"""
|
||||
|
||||
import html
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.builders.gettext
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The MessageCatalogBuilder class.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""The MessageCatalogBuilder class."""
|
||||
|
||||
from codecs import open
|
||||
from collections import OrderedDict, defaultdict
|
||||
@ -146,7 +138,7 @@ class I18nBuilder(Builder):
|
||||
def write_doc(self, docname: str, doctree: nodes.document) -> None:
|
||||
catalog = self.catalogs[docname_to_domain(docname, self.config.gettext_compact)]
|
||||
|
||||
for toctree in self.env.tocs[docname].traverse(addnodes.toctree):
|
||||
for toctree in self.env.tocs[docname].findall(addnodes.toctree):
|
||||
for node, msg in extract_messages(toctree):
|
||||
node.uid = '' # type: ignore # Hack UUID model
|
||||
catalog.add(msg, node)
|
||||
@ -157,7 +149,7 @@ class I18nBuilder(Builder):
|
||||
if 'index' in self.env.config.gettext_additional_targets:
|
||||
# Extract translatable messages from index entries.
|
||||
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):
|
||||
if typ == 'pair' and m in pairindextypes.values():
|
||||
# avoid built-in translated message was incorporated
|
||||
@ -180,7 +172,7 @@ if source_date_epoch is not None:
|
||||
|
||||
class LocalTimeZone(tzinfo):
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||
super().__init__(*args, **kwargs) # type: ignore
|
||||
super().__init__(*args, **kwargs)
|
||||
self.tzdelta = tzdelta
|
||||
|
||||
def utcoffset(self, dt: datetime) -> timedelta:
|
||||
@ -227,7 +219,7 @@ class MessageCatalogBuilder(I18nBuilder):
|
||||
template_files = set()
|
||||
for template_path in self.config.templates_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:
|
||||
if fn.endswith('.html'):
|
||||
filename = canon_path(path.join(dirpath, fn))
|
||||
@ -247,7 +239,7 @@ class MessageCatalogBuilder(I18nBuilder):
|
||||
try:
|
||||
with open(template, encoding='utf-8') as f:
|
||||
context = f.read()
|
||||
for line, meth, msg in extract_translations(context):
|
||||
for line, _meth, msg in extract_translations(context):
|
||||
origin = MsgOrigin(template, line)
|
||||
self.catalogs['sphinx'].add(msg, origin)
|
||||
except Exception as exc:
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.builders.html
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Several HTML builders.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Several HTML builders."""
|
||||
|
||||
import html
|
||||
import os
|
||||
@ -15,7 +7,7 @@ import re
|
||||
import sys
|
||||
from datetime import datetime
|
||||
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 docutils import nodes
|
||||
@ -76,6 +68,17 @@ def get_stable_hash(obj: Any) -> str:
|
||||
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):
|
||||
"""A metadata of stylesheet.
|
||||
|
||||
@ -315,8 +318,11 @@ class StandaloneHTMLBuilder(Builder):
|
||||
self.script_files = []
|
||||
self.add_js_file('documentation_options.js', id="documentation_options",
|
||||
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('underscore.js', priority=200)
|
||||
self.add_js_file('_sphinx_javascript_frameworks_compat.js', priority=200)
|
||||
self.add_js_file('doctools.js', priority=200)
|
||||
|
||||
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'
|
||||
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')
|
||||
|
||||
def add_js_file(self, filename: str, **kwargs: Any) -> None:
|
||||
@ -431,8 +437,6 @@ class StandaloneHTMLBuilder(Builder):
|
||||
if self.search:
|
||||
from sphinx.search import IndexBuilder
|
||||
lang = self.config.html_search_language or self.config.language
|
||||
if not lang:
|
||||
lang = 'en'
|
||||
self.indexer = IndexBuilder(self.env, lang,
|
||||
self.config.html_search_options,
|
||||
self.config.html_search_scorer)
|
||||
@ -486,7 +490,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
rellinks: List[Tuple[str, str, str, str]] = []
|
||||
if self.use_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 indexcls.shortname:
|
||||
rellinks.append((indexname, indexcls.localname,
|
||||
@ -509,6 +513,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
'docstitle': self.config.html_title,
|
||||
'shorttitle': self.config.html_short_title,
|
||||
'show_copyright': self.config.html_show_copyright,
|
||||
'show_search_summary': self.config.html_show_search_summary,
|
||||
'show_sphinx': self.config.html_show_sphinx,
|
||||
'has_source': self.config.html_copy_source,
|
||||
'show_source': self.config.html_show_sourcelink,
|
||||
@ -516,7 +521,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
'file_suffix': self.out_suffix,
|
||||
'link_suffix': self.link_suffix,
|
||||
'script_files': self.script_files,
|
||||
'language': self.config.language,
|
||||
'language': convert_locale_to_language_tag(self.config.language),
|
||||
'css_files': self.css_files,
|
||||
'sphinx_version': __display_version__,
|
||||
'sphinx_version_tuple': sphinx_version,
|
||||
@ -767,7 +772,6 @@ class StandaloneHTMLBuilder(Builder):
|
||||
|
||||
def copy_translation_js(self) -> None:
|
||||
"""Copy a JavaScript file for translations."""
|
||||
if self.config.language is not None:
|
||||
jsfile = self._get_translations_js()
|
||||
if jsfile:
|
||||
copyfile(jsfile, path.join(self.outdir, '_static', 'translations.js'))
|
||||
@ -866,7 +870,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
Builder.post_process_images(self, doctree)
|
||||
|
||||
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']):
|
||||
# resizing options are not given. scaled image link is available
|
||||
# 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_link_suffix', None, 'html', [str])
|
||||
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_context', {}, 'html')
|
||||
app.add_config_value('html_output_encoding', 'utf-8', 'html')
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.builders.html.transforms
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Transforms for HTML builder.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Transforms for HTML builder."""
|
||||
|
||||
import re
|
||||
from typing import Any, Dict, List
|
||||
@ -36,7 +28,7 @@ class KeyboardTransform(SphinxPostTransform):
|
||||
x
|
||||
"""
|
||||
default_priority = 400
|
||||
builders = ('html',)
|
||||
formats = ('html',)
|
||||
pattern = re.compile(r'(?<=.)(-|\+|\^|\s+)(?=.)')
|
||||
multiwords_keys = (('caps', 'lock'),
|
||||
('page' 'down'),
|
||||
@ -48,7 +40,7 @@ class KeyboardTransform(SphinxPostTransform):
|
||||
|
||||
def run(self, **kwargs: Any) -> None:
|
||||
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())
|
||||
if len(parts) == 1 or self.is_multiwords_key(parts):
|
||||
continue
|
||||
|
@ -1,15 +1,6 @@
|
||||
"""
|
||||
sphinx.builders.latex
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
LaTeX builder.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""LaTeX builder."""
|
||||
|
||||
import os
|
||||
import warnings
|
||||
from os import path
|
||||
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.util import ExtBabel
|
||||
from sphinx.config import ENUM, Config
|
||||
from sphinx.deprecation import RemovedInSphinx50Warning
|
||||
from sphinx.environment.adapters.asset import ImageAdapter
|
||||
from sphinx.errors import NoUri, SphinxError
|
||||
from sphinx.locale import _, __
|
||||
@ -172,7 +162,6 @@ class LaTeXBuilder(Builder):
|
||||
self.context.update(ADDITIONAL_SETTINGS.get(self.config.latex_engine, {}))
|
||||
|
||||
# Add special settings for (latex_engine, language_code)
|
||||
if self.config.language:
|
||||
key = (self.config.latex_engine, self.config.language[:2])
|
||||
self.context.update(ADDITIONAL_SETTINGS.get(key, {}))
|
||||
|
||||
@ -205,7 +194,7 @@ class LaTeXBuilder(Builder):
|
||||
|
||||
def init_babel(self) -> None:
|
||||
self.babel = ExtBabel(self.config.language, not self.context['babel'])
|
||||
if self.config.language and not self.babel.is_supported_language():
|
||||
if not self.babel.is_supported_language():
|
||||
# emit warning if specified language is invalid
|
||||
# (only emitting, nothing changed to processing)
|
||||
logger.warning(__('no Babel option known for language %r'),
|
||||
@ -234,7 +223,6 @@ class LaTeXBuilder(Builder):
|
||||
self.context['classoptions'] += ',' + self.babel.get_language()
|
||||
# this branch is not taken for xelatex/lualatex if default settings
|
||||
self.context['multilingual'] = self.context['babel']
|
||||
if self.config.language:
|
||||
self.context['shorthandoff'] = SHORTHANDOFF
|
||||
|
||||
# Times fonts don't work with Cyrillic languages
|
||||
@ -280,7 +268,7 @@ class LaTeXBuilder(Builder):
|
||||
encoding='utf-8', overwrite_if_changed=True)
|
||||
with progress_message(__("processing %s") % targetname):
|
||||
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:
|
||||
tocdepth = toctree.get('maxdepth')
|
||||
else:
|
||||
@ -310,7 +298,7 @@ class LaTeXBuilder(Builder):
|
||||
def get_contentsname(self, indexfile: str) -> str:
|
||||
tree = self.env.get_doctree(indexfile)
|
||||
contentsname = None
|
||||
for toctree in tree.traverse(addnodes.toctree):
|
||||
for toctree in tree.findall(addnodes.toctree):
|
||||
if 'caption' in toctree:
|
||||
contentsname = toctree['caption']
|
||||
break
|
||||
@ -338,7 +326,7 @@ class LaTeXBuilder(Builder):
|
||||
new_sect += nodes.title('<Set title in conf.py>',
|
||||
'<Set title in conf.py>')
|
||||
new_tree += new_sect
|
||||
for node in tree.traverse(addnodes.toctree):
|
||||
for node in tree.findall(addnodes.toctree):
|
||||
new_sect += node
|
||||
tree = new_tree
|
||||
largetree = inline_all_toctrees(self, self.docnames, indexfile, tree,
|
||||
@ -353,7 +341,7 @@ class LaTeXBuilder(Builder):
|
||||
self.env.resolve_references(largetree, indexfile, self)
|
||||
# resolve :ref:s to distant tex files -- we can't add a cross-reference,
|
||||
# but append the document name
|
||||
for pendingnode in largetree.traverse(addnodes.pending_xref):
|
||||
for pendingnode in largetree.findall(addnodes.pending_xref):
|
||||
docname = pendingnode['refdocname']
|
||||
sectname = pendingnode['refsectname']
|
||||
newnodes: List[Node] = [nodes.emphasis(sectname, sectname)]
|
||||
@ -382,14 +370,10 @@ class LaTeXBuilder(Builder):
|
||||
# configure usage of xindy (impacts Makefile and latexmkrc)
|
||||
# FIXME: convert this rather to a confval with suitable default
|
||||
# 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 = XINDY_LANG_OPTIONS.get(self.config.language[:2],
|
||||
'-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 = {
|
||||
'latex_engine': self.config.latex_engine,
|
||||
'xindy_use': self.config.latex_use_xindy,
|
||||
@ -449,18 +433,6 @@ class LaTeXBuilder(Builder):
|
||||
filename = path.join(package_dir, 'templates', 'latex', 'sphinxmessages.sty_t')
|
||||
copy_asset_file(filename, self.outdir, context=context, renderer=LaTeXRenderer())
|
||||
|
||||
@property
|
||||
def usepackages(self) -> List[Tuple[str, str]]:
|
||||
warnings.warn('LaTeXBuilder.usepackages is deprecated.',
|
||||
RemovedInSphinx50Warning, stacklevel=2)
|
||||
return self.app.registry.latex_packages
|
||||
|
||||
@property
|
||||
def usepackages_after_hyperref(self) -> List[Tuple[str, str]]:
|
||||
warnings.warn('LaTeXBuilder.usepackages_after_hyperref is deprecated.',
|
||||
RemovedInSphinx50Warning, stacklevel=2)
|
||||
return self.app.registry.latex_packages_after_hyperref
|
||||
|
||||
|
||||
def validate_config_values(app: Sphinx, config: Config) -> None:
|
||||
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. """
|
||||
if config.language == 'ja':
|
||||
return 'uplatex'
|
||||
elif (config.language or '').startswith('zh'):
|
||||
elif config.language.startswith('zh'):
|
||||
return 'xelatex'
|
||||
elif config.language == 'el':
|
||||
return 'xelatex'
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.builders.latex.constants
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
consntants for LaTeX builder.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""consntants for LaTeX builder."""
|
||||
|
||||
from typing import Any, Dict
|
||||
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
"""Additional nodes for LaTeX writer."""
|
||||
|
||||
from docutils import nodes
|
||||
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
"""Theming support for LaTeX builder."""
|
||||
|
||||
import configparser
|
||||
from os import path
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.builders.latex.transforms
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Transforms for LaTeX builder.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Transforms for LaTeX builder."""
|
||||
|
||||
from typing import Any, Dict, List, Set, Tuple, cast
|
||||
|
||||
@ -33,7 +25,7 @@ class FootnoteDocnameUpdater(SphinxTransform):
|
||||
|
||||
def apply(self, **kwargs: Any) -> None:
|
||||
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
|
||||
|
||||
|
||||
@ -45,7 +37,7 @@ class SubstitutionDefinitionsRemover(SphinxPostTransform):
|
||||
formats = ('latex',)
|
||||
|
||||
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)
|
||||
|
||||
|
||||
@ -81,7 +73,7 @@ class ShowUrlsTransform(SphinxPostTransform):
|
||||
if show_urls is False or show_urls == 'no':
|
||||
return
|
||||
|
||||
for node in list(self.document.traverse(nodes.reference)):
|
||||
for node in list(self.document.findall(nodes.reference)):
|
||||
uri = node.get('refuri', '')
|
||||
if uri.startswith(URI_SCHEMES):
|
||||
if uri.startswith('mailto:'):
|
||||
@ -237,7 +229,8 @@ class LaTeXFootnoteTransform(SphinxPostTransform):
|
||||
blah blah blah ...
|
||||
|
||||
* 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::
|
||||
|
||||
@ -258,7 +251,7 @@ class LaTeXFootnoteTransform(SphinxPostTransform):
|
||||
After::
|
||||
|
||||
blah blah blah
|
||||
<footnote ids="id1">
|
||||
<footnote ids="id1" referred=True>
|
||||
<label>
|
||||
1
|
||||
<paragraph>
|
||||
@ -348,7 +341,7 @@ class LaTeXFootnoteTransform(SphinxPostTransform):
|
||||
formats = ('latex',)
|
||||
|
||||
def run(self, **kwargs: Any) -> None:
|
||||
footnotes = list(self.document.traverse(nodes.footnote))
|
||||
footnotes = list(self.document.findall(nodes.footnote))
|
||||
for node in footnotes:
|
||||
node.parent.remove(node)
|
||||
|
||||
@ -358,7 +351,7 @@ class LaTeXFootnoteTransform(SphinxPostTransform):
|
||||
|
||||
class LaTeXFootnoteVisitor(nodes.NodeVisitor):
|
||||
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.pendings: List[nodes.footnote] = []
|
||||
self.table_footnotes: List[nodes.footnote] = []
|
||||
@ -423,7 +416,7 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
|
||||
self.unrestrict(node)
|
||||
|
||||
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):
|
||||
fntext = footnotetext('', *footnote.children, ids=footnote['ids'])
|
||||
tbody.insert(0, fntext)
|
||||
@ -439,22 +432,24 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
|
||||
def visit_footnote_reference(self, node: nodes.footnote_reference) -> None:
|
||||
number = node.astext().strip()
|
||||
docname = node['docname']
|
||||
if self.restricted:
|
||||
mark = footnotemark('', number, refid=node['refid'])
|
||||
node.replace_self(mark)
|
||||
if (docname, number) not in self.appeared:
|
||||
footnote = self.get_footnote_by_reference(node)
|
||||
self.pendings.append(footnote)
|
||||
elif (docname, number) in self.appeared:
|
||||
if (docname, number) in self.appeared:
|
||||
footnote = self.appeared.get((docname, number))
|
||||
footnote["referred"] = True
|
||||
|
||||
mark = footnotemark('', number, refid=node['refid'])
|
||||
node.replace_self(mark)
|
||||
else:
|
||||
footnote = self.get_footnote_by_reference(node)
|
||||
if self.restricted:
|
||||
mark = footnotemark('', number, refid=node['refid'])
|
||||
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
|
||||
|
||||
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:
|
||||
citations = thebibliography()
|
||||
for node in list(self.document.traverse(nodes.citation)):
|
||||
for node in list(self.document.findall(nodes.citation)):
|
||||
node.parent.remove(node)
|
||||
citations += node
|
||||
|
||||
@ -521,7 +516,7 @@ class CitationReferenceTransform(SphinxPostTransform):
|
||||
def run(self, **kwargs: Any) -> None:
|
||||
domain = cast(CitationDomain, self.env.get_domain('citation'))
|
||||
matcher = NodeMatcher(addnodes.pending_xref, refdomain='citation', reftype='ref')
|
||||
for node in self.document.traverse(matcher): # type: addnodes.pending_xref
|
||||
for node in self.document.findall(matcher): # type: addnodes.pending_xref
|
||||
docname, labelid, _ = domain.citations.get(node['reftarget'], ('', '', 0))
|
||||
if docname:
|
||||
citation_ref = nodes.citation_reference('', '', *node.children,
|
||||
@ -540,7 +535,7 @@ class MathReferenceTransform(SphinxPostTransform):
|
||||
|
||||
def run(self, **kwargs: Any) -> None:
|
||||
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'):
|
||||
docname, _ = equations.get(node['reftarget'], (None, None))
|
||||
if docname:
|
||||
@ -555,7 +550,7 @@ class LiteralBlockTransform(SphinxPostTransform):
|
||||
|
||||
def run(self, **kwargs: Any) -> None:
|
||||
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)
|
||||
node.replace_self(newnode)
|
||||
|
||||
@ -566,7 +561,7 @@ class DocumentTargetTransform(SphinxPostTransform):
|
||||
formats = ('latex',)
|
||||
|
||||
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)
|
||||
if section:
|
||||
section['ids'].append(':doc') # special label for :doc:
|
||||
@ -602,9 +597,9 @@ class IndexInSectionTitleTransform(SphinxPostTransform):
|
||||
formats = ('latex',)
|
||||
|
||||
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):
|
||||
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
|
||||
node.remove(index)
|
||||
node.parent.insert(i + 1, index)
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.builders.latex.util
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Utilities for LaTeX builder.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Utilities for LaTeX builder."""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
@ -20,7 +12,7 @@ class ExtBabel(Babel):
|
||||
self.language_code = language_code
|
||||
self.use_polyglossia = use_polyglossia
|
||||
self.supported = True
|
||||
super().__init__(language_code or '')
|
||||
super().__init__(language_code)
|
||||
|
||||
def uses_cyrillic(self) -> bool:
|
||||
return self.language in self.cyrillic_languages
|
||||
|
@ -1,37 +1,25 @@
|
||||
"""
|
||||
sphinx.builders.linkcheck
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The CheckExternalLinksBuilder class.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""The CheckExternalLinksBuilder class."""
|
||||
|
||||
import json
|
||||
import re
|
||||
import socket
|
||||
import time
|
||||
import warnings
|
||||
from datetime import datetime, timezone
|
||||
from email.utils import parsedate_to_datetime
|
||||
from html.parser import HTMLParser
|
||||
from os import path
|
||||
from queue import PriorityQueue, Queue
|
||||
from threading import Thread
|
||||
from typing import (Any, Dict, Generator, List, NamedTuple, Optional, Pattern, Set, Tuple,
|
||||
Union, cast)
|
||||
from typing import Any, Dict, Generator, List, NamedTuple, Optional, Tuple, Union, cast
|
||||
from urllib.parse import unquote, urlparse, urlunparse
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.nodes import Element
|
||||
from requests import Response
|
||||
from requests.exceptions import ConnectionError, HTTPError, TooManyRedirects
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders.dummy import DummyBuilder
|
||||
from sphinx.config import Config
|
||||
from sphinx.deprecation import RemovedInSphinx50Warning
|
||||
from sphinx.environment import BuildEnvironment
|
||||
from sphinx.locale import __
|
||||
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)
|
||||
|
||||
Hyperlink = NamedTuple('Hyperlink', (('uri', str),
|
||||
('docname', str),
|
||||
('lineno', Optional[int])))
|
||||
CheckRequest = NamedTuple('CheckRequest', (('next_check', float),
|
||||
('hyperlink', Optional[Hyperlink])))
|
||||
CheckResult = NamedTuple('CheckResult', (('uri', str),
|
||||
('docname', str),
|
||||
('lineno', int),
|
||||
('status', str),
|
||||
('message', str),
|
||||
('code', int)))
|
||||
RateLimit = NamedTuple('RateLimit', (('delay', float), ('next_check', float)))
|
||||
|
||||
class Hyperlink(NamedTuple):
|
||||
uri: str
|
||||
docname: str
|
||||
lineno: Optional[int]
|
||||
|
||||
|
||||
class CheckRequest(NamedTuple):
|
||||
next_check: float
|
||||
hyperlink: Optional[Hyperlink]
|
||||
|
||||
|
||||
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
|
||||
CheckRequestType = Union[CheckRequest, Tuple[float, str, str, int]]
|
||||
@ -67,16 +68,6 @@ QUEUE_POLL_SECS = 1
|
||||
DEFAULT_DELAY = 60.0
|
||||
|
||||
|
||||
def node_line_or_0(node: Element) -> int:
|
||||
"""
|
||||
PriorityQueue items must be comparable. The line number is part of the
|
||||
tuple used by the PriorityQueue, keep an homogeneous type for comparison.
|
||||
"""
|
||||
warnings.warn('node_line_or_0() is deprecated.',
|
||||
RemovedInSphinx50Warning, stacklevel=2)
|
||||
return get_node_line(node) or 0
|
||||
|
||||
|
||||
class AnchorCheckParser(HTMLParser):
|
||||
"""Specialized HTML parser that looks for a specific anchor."""
|
||||
|
||||
@ -120,114 +111,11 @@ class CheckExternalLinksBuilder(DummyBuilder):
|
||||
'%(outdir)s/output.txt')
|
||||
|
||||
def init(self) -> None:
|
||||
self.broken_hyperlinks = 0
|
||||
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
|
||||
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:
|
||||
filename = self.env.doc2path(result.docname, None)
|
||||
|
||||
@ -260,6 +148,7 @@ class CheckExternalLinksBuilder(DummyBuilder):
|
||||
logger.info(red('broken ') + result.uri + red(' - ' + result.message))
|
||||
self.write_entry('broken', result.docname, filename, result.lineno,
|
||||
result.uri + ': ' + result.message)
|
||||
self.broken_hyperlinks += 1
|
||||
elif result.status == 'redirected':
|
||||
try:
|
||||
text, color = {
|
||||
@ -292,7 +181,7 @@ class CheckExternalLinksBuilder(DummyBuilder):
|
||||
self.json_outfile.write('\n')
|
||||
|
||||
def finish(self) -> None:
|
||||
checker = HyperlinkAvailabilityChecker(self.env, self.config, self)
|
||||
checker = HyperlinkAvailabilityChecker(self.env, self.config)
|
||||
logger.info('')
|
||||
|
||||
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):
|
||||
self.process_result(result)
|
||||
|
||||
if self._broken:
|
||||
if self.broken_hyperlinks:
|
||||
self.app.statuscode = 1
|
||||
|
||||
|
||||
class HyperlinkAvailabilityChecker:
|
||||
def __init__(self, env: BuildEnvironment, config: Config,
|
||||
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
|
||||
def __init__(self, env: BuildEnvironment, config: Config) -> None:
|
||||
self.config = config
|
||||
self.env = env
|
||||
self.rate_limits: Dict[str, RateLimit] = {}
|
||||
self.rqueue: Queue = Queue()
|
||||
self.workers: List[Thread] = []
|
||||
self.wqueue: PriorityQueue = PriorityQueue()
|
||||
|
||||
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:
|
||||
for i in range(self.config.linkcheck_workers):
|
||||
for _i in range(self.config.linkcheck_workers):
|
||||
thread = HyperlinkAvailabilityCheckWorker(self.env, self.config,
|
||||
self.rqueue, self.wqueue,
|
||||
self.rate_limits, self.builder)
|
||||
self.rate_limits)
|
||||
thread.start()
|
||||
self.workers.append(thread)
|
||||
|
||||
def shutdown_threads(self) -> None:
|
||||
self.wqueue.join()
|
||||
for worker in self.workers:
|
||||
for _worker in self.workers:
|
||||
self.wqueue.put(CheckRequest(CHECK_IMMEDIATELY, None), False)
|
||||
|
||||
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."""
|
||||
|
||||
def __init__(self, env: BuildEnvironment, config: Config, rqueue: Queue,
|
||||
wqueue: Queue, rate_limits: Dict[str, RateLimit],
|
||||
builder: CheckExternalLinksBuilder = None) -> None:
|
||||
# Warning: builder argument will be removed in the sphinx-5.0.
|
||||
# Don't use it from extensions.
|
||||
# tag: RemovedInSphinx50Warning
|
||||
wqueue: Queue, rate_limits: Dict[str, RateLimit]) -> None:
|
||||
self.config = config
|
||||
self.env = env
|
||||
self.rate_limits = rate_limits
|
||||
@ -378,20 +253,11 @@ class HyperlinkAvailabilityCheckWorker(Thread):
|
||||
|
||||
self.anchors_ignore = [re.compile(x)
|
||||
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
|
||||
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)
|
||||
|
||||
def run(self) -> None:
|
||||
@ -519,6 +385,15 @@ class HyperlinkAvailabilityCheckWorker(Thread):
|
||||
|
||||
def check(docname: str) -> Tuple[str, str, int]:
|
||||
# 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:')):
|
||||
return 'unchecked', '', 0
|
||||
elif not uri.startswith(('http:', 'https:')):
|
||||
@ -530,14 +405,7 @@ class HyperlinkAvailabilityCheckWorker(Thread):
|
||||
if path.exists(path.join(srcdir, uri)):
|
||||
return 'working', '', 0
|
||||
else:
|
||||
self._broken[uri] = ''
|
||||
return 'broken', '', 0
|
||||
elif uri in self._good:
|
||||
return 'working', 'old', 0
|
||||
elif uri in self._broken:
|
||||
return 'broken', self._broken[uri], 0
|
||||
elif uri in self._redirected:
|
||||
return 'redirected', self._redirected[uri][0], self._redirected[uri][1]
|
||||
|
||||
# need to actually check the URI
|
||||
for _ in range(self.config.linkcheck_retries):
|
||||
@ -545,13 +413,6 @@ class HyperlinkAvailabilityCheckWorker(Thread):
|
||||
if status != "broken":
|
||||
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)
|
||||
|
||||
while True:
|
||||
@ -639,7 +500,7 @@ class HyperlinkCollector(SphinxPostTransform):
|
||||
hyperlinks = builder.hyperlinks
|
||||
|
||||
# reference nodes
|
||||
for refnode in self.document.traverse(nodes.reference):
|
||||
for refnode in self.document.findall(nodes.reference):
|
||||
if 'refuri' not in refnode:
|
||||
continue
|
||||
uri = refnode['refuri']
|
||||
@ -653,7 +514,7 @@ class HyperlinkCollector(SphinxPostTransform):
|
||||
hyperlinks[uri] = uri_info
|
||||
|
||||
# image nodes
|
||||
for imgnode in self.document.traverse(nodes.image):
|
||||
for imgnode in self.document.findall(nodes.image):
|
||||
uri = imgnode['candidates'].get('?')
|
||||
if uri and '://' in 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_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_auth', [], None)
|
||||
app.add_config_value('linkcheck_request_headers', {}, None)
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.builders.manpage
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Manual pages builder.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Manual pages builder."""
|
||||
|
||||
from os import path
|
||||
from typing import Any, Dict, List, Set, Tuple, Union
|
||||
@ -18,7 +10,6 @@ from sphinx import addnodes
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.config import Config
|
||||
from sphinx.errors import NoUri
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import logging, progress_message
|
||||
from sphinx.util.console import darkgreen # type: ignore
|
||||
@ -49,9 +40,7 @@ class ManualPageBuilder(Builder):
|
||||
return 'all manpages' # for now
|
||||
|
||||
def get_target_uri(self, docname: str, typ: str = None) -> str:
|
||||
if typ == 'token':
|
||||
return ''
|
||||
raise NoUri(docname, typ)
|
||||
|
||||
@progress_message(__('writing'))
|
||||
def write(self, *ignored: Any) -> None:
|
||||
@ -98,7 +87,7 @@ class ManualPageBuilder(Builder):
|
||||
logger.info('} ', nonl=True)
|
||||
self.env.resolve_references(largetree, docname, self)
|
||||
# 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)
|
||||
|
||||
docwriter.write(largetree, destination)
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.builders.singlehtml
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Single HTML builders.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Single HTML builders."""
|
||||
|
||||
from os import path
|
||||
from typing import Any, Dict, List, Tuple, Union
|
||||
@ -54,7 +46,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
def fix_refuris(self, tree: Node) -> None:
|
||||
# fix refuris with double anchor
|
||||
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:
|
||||
continue
|
||||
refuri = refnode['refuri']
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.builders.texinfo
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Texinfo builder.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Texinfo builder."""
|
||||
|
||||
import os
|
||||
from os import path
|
||||
@ -138,7 +130,7 @@ class TexinfoBuilder(Builder):
|
||||
new_sect += nodes.title('<Set title in conf.py>',
|
||||
'<Set title in conf.py>')
|
||||
new_tree += new_sect
|
||||
for node in tree.traverse(addnodes.toctree):
|
||||
for node in tree.findall(addnodes.toctree):
|
||||
new_sect += node
|
||||
tree = new_tree
|
||||
largetree = inline_all_toctrees(self, self.docnames, indexfile, tree,
|
||||
@ -152,7 +144,7 @@ class TexinfoBuilder(Builder):
|
||||
logger.info(__("resolving references..."))
|
||||
self.env.resolve_references(largetree, indexfile, self)
|
||||
# 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']
|
||||
sectname = pendingnode['refsectname']
|
||||
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_show_urls', 'footnote', None)
|
||||
app.add_config_value('texinfo_no_detailmenu', False, None)
|
||||
app.add_config_value('texinfo_cross_references', True, None)
|
||||
|
||||
return {
|
||||
'version': 'builtin',
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.builders.text
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Plain-text Sphinx builder.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Plain-text Sphinx builder."""
|
||||
|
||||
from os import path
|
||||
from typing import Any, Dict, Iterator, Set, Tuple
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
"""Docutils-native XML and pseudo-XML builders."""
|
||||
|
||||
from os import path
|
||||
from typing import Any, Dict, Iterator, Set, Type, Union
|
||||
@ -71,7 +63,10 @@ class XMLBuilder(Builder):
|
||||
# work around multiple string % tuple issues in docutils;
|
||||
# replace tuples in attribute values with lists
|
||||
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():
|
||||
if isinstance(value, tuple):
|
||||
node.attributes[att] = list(value)
|
||||
|
@ -1,9 +1 @@
|
||||
"""
|
||||
sphinx.cmd
|
||||
~~~~~~~~~~
|
||||
|
||||
Modules for command line executables.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Modules for command line executables."""
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
"""Build documentation from a provided source."""
|
||||
|
||||
import argparse
|
||||
import bdb
|
||||
@ -16,6 +8,7 @@ import os
|
||||
import pdb
|
||||
import sys
|
||||
import traceback
|
||||
from os import path
|
||||
from typing import IO, Any, List
|
||||
|
||||
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.console import color_terminal, nocolor, red, terminal_safe # type: ignore
|
||||
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
|
||||
@ -240,6 +234,8 @@ def build_main(argv: List[str] = sys.argv[1:]) -> int:
|
||||
|
||||
if warning and args.warnfile:
|
||||
try:
|
||||
warnfile = abspath(args.warnfile)
|
||||
ensuredir(path.dirname(warnfile))
|
||||
warnfp = open(args.warnfile, 'w')
|
||||
except Exception as exc:
|
||||
parser.error(__('cannot open warning file %r: %s') % (
|
||||
|
@ -1,17 +1,10 @@
|
||||
"""
|
||||
sphinx.cmd.make_mode
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
"""sphinx-build -M command-line handling.
|
||||
|
||||
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
|
||||
of Makefile / make.bat.
|
||||
|
||||
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.
|
||||
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).
|
||||
"""
|
||||
|
||||
import os
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
"""Quickly setup documentation source to work with Sphinx."""
|
||||
|
||||
import argparse
|
||||
import locale
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.config
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Build configuration file handling.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Build configuration file handling."""
|
||||
|
||||
import re
|
||||
import traceback
|
||||
@ -100,7 +92,7 @@ class Config:
|
||||
# the real default is locale-dependent
|
||||
'today_fmt': (None, 'env', [str]),
|
||||
|
||||
'language': (None, 'env', [str]),
|
||||
'language': ('en', 'env', [str]),
|
||||
'locale_dirs': (['locales'], 'env', []),
|
||||
'figure_language_filename': ('{root}.{language}{ext}', 'env', [str]),
|
||||
'gettext_allow_fuzzy_translations': (False, 'gettext', []),
|
||||
@ -206,7 +198,7 @@ class Config:
|
||||
except ValueError as exc:
|
||||
raise ValueError(__('invalid number %r for config value %r, ignoring') %
|
||||
(value, name)) from exc
|
||||
elif hasattr(defvalue, '__call__'):
|
||||
elif callable(defvalue):
|
||||
return value
|
||||
elif defvalue is not None and not isinstance(defvalue, str):
|
||||
raise ValueError(__('cannot override config setting %r with unsupported '
|
||||
@ -251,13 +243,24 @@ class Config:
|
||||
if name in self.values:
|
||||
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:
|
||||
if name.startswith('_'):
|
||||
raise AttributeError(name)
|
||||
if name not in self.values:
|
||||
raise AttributeError(__('No such config value: %s') % name)
|
||||
default = self.values[name][0]
|
||||
if hasattr(default, '__call__'):
|
||||
if callable(default):
|
||||
return default(self)
|
||||
return default
|
||||
|
||||
@ -413,7 +416,7 @@ def check_confval_types(app: "Sphinx", config: Config) -> None:
|
||||
for confval in config:
|
||||
default, rebuild, annotations = config.values[confval.name]
|
||||
|
||||
if hasattr(default, '__call__'):
|
||||
if callable(default):
|
||||
default = default(config) # evaluate default value
|
||||
if default is None and not annotations:
|
||||
continue # neither inferable nor expliclitly annotated types
|
||||
@ -427,7 +430,7 @@ def check_confval_types(app: "Sphinx", config: Config) -> None:
|
||||
"but `{current}` is given.")
|
||||
logger.warning(msg.format(name=confval.name,
|
||||
current=confval.value,
|
||||
candidates=annotations.candidates))
|
||||
candidates=annotations.candidates), once=True)
|
||||
else:
|
||||
if type(confval.value) is type(default):
|
||||
continue
|
||||
@ -452,13 +455,13 @@ def check_confval_types(app: "Sphinx", config: Config) -> None:
|
||||
permitted = " or ".join(wrapped_annotations)
|
||||
logger.warning(msg.format(name=confval.name,
|
||||
current=type(confval.value),
|
||||
permitted=permitted))
|
||||
permitted=permitted), once=True)
|
||||
else:
|
||||
msg = __("The config value `{name}' has type `{current.__name__}', "
|
||||
"defaults to `{default.__name__}'.")
|
||||
logger.warning(msg.format(name=confval.name,
|
||||
current=type(confval.value),
|
||||
default=type(default)))
|
||||
default=type(default)), once=True)
|
||||
|
||||
|
||||
def check_primary_domain(app: "Sphinx", config: Config) -> None:
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.deprecation
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sphinx deprecation classes and utilities.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Sphinx deprecation classes and utilities."""
|
||||
|
||||
import sys
|
||||
import warnings
|
||||
@ -22,6 +14,10 @@ class RemovedInSphinx60Warning(PendingDeprecationWarning):
|
||||
pass
|
||||
|
||||
|
||||
class RemovedInSphinx70Warning(PendingDeprecationWarning):
|
||||
pass
|
||||
|
||||
|
||||
RemovedInNextVersionWarning = RemovedInSphinx50Warning
|
||||
|
||||
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.directives
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Handlers for additional ReST directives.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Handlers for additional ReST directives."""
|
||||
|
||||
import re
|
||||
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.addnodes import desc_signature
|
||||
from sphinx.deprecation import RemovedInSphinx50Warning, deprecated_alias
|
||||
from sphinx.util import docutils
|
||||
from sphinx.util.docfields import DocFieldTransformer, Field, TypedField
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
@ -176,7 +167,7 @@ class ObjectDescription(SphinxDirective, Generic[T]):
|
||||
|
||||
self.names: List[T] = []
|
||||
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
|
||||
# and add a reference target for it
|
||||
signode = addnodes.desc_signature(sig, '')
|
||||
@ -266,16 +257,6 @@ class DefaultDomain(SphinxDirective):
|
||||
return []
|
||||
|
||||
|
||||
deprecated_alias('sphinx.directives',
|
||||
{
|
||||
'DescDirective': ObjectDescription,
|
||||
},
|
||||
RemovedInSphinx50Warning,
|
||||
{
|
||||
'DescDirective': 'sphinx.directives.ObjectDescription',
|
||||
})
|
||||
|
||||
|
||||
def setup(app: "Sphinx") -> Dict[str, Any]:
|
||||
app.add_config_value("strip_signature_backslash", False, 'env')
|
||||
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 textwrap
|
||||
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]:
|
||||
if not dedent:
|
||||
if dedent is None:
|
||||
return textwrap.dedent(''.join(lines)).splitlines(True)
|
||||
|
||||
if any(s[:dedent].strip() for s in lines):
|
||||
@ -138,9 +130,9 @@ class CodeBlock(SphinxDirective):
|
||||
|
||||
if 'dedent' in self.options:
|
||||
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)
|
||||
code = '\n'.join(lines)
|
||||
code = ''.join(lines)
|
||||
|
||||
literal: Element = nodes.literal_block(code, code)
|
||||
if 'linenos' in self.options or 'lineno-start' in self.options:
|
||||
@ -232,9 +224,9 @@ class LiteralIncludeReader:
|
||||
self.start_filter,
|
||||
self.end_filter,
|
||||
self.lines_filter,
|
||||
self.dedent_filter,
|
||||
self.prepend_filter,
|
||||
self.append_filter,
|
||||
self.dedent_filter]
|
||||
self.append_filter]
|
||||
lines = self.read_file(self.filename, location=location)
|
||||
for func in filters:
|
||||
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
|
||||
from typing import TYPE_CHECKING, Any, Dict, List, cast
|
||||
|
||||
@ -342,7 +334,7 @@ class Only(SphinxDirective):
|
||||
# be placed in the doctree.
|
||||
n_sects_to_raise = current_depth - nested_depth + 1
|
||||
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:
|
||||
parent = parent.parent
|
||||
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 warnings
|
||||
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.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
|
||||
|
||||
try:
|
||||
from docutils.nodes import meta as meta_node # type: ignore
|
||||
from docutils.parsers.rst.directives.misc import Meta as MetaBase # type: ignore
|
||||
except ImportError:
|
||||
# docutils-0.17 or older
|
||||
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:
|
||||
from sphinx.application import Sphinx
|
||||
@ -71,11 +60,13 @@ class Figure(images.Figure):
|
||||
|
||||
|
||||
class Meta(MetaBase, SphinxDirective):
|
||||
def run(self) -> List[Node]:
|
||||
def run(self) -> Sequence[Node]:
|
||||
result = super().run()
|
||||
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
|
||||
isinstance(node.details['nodes'][0], meta_node)):
|
||||
isinstance(node.details['nodes'][0], addnodes.docutils_meta)):
|
||||
meta = node.details['nodes'][0]
|
||||
meta.source = self.env.doc2path(self.env.docname)
|
||||
meta.line = self.lineno
|
||||
|
@ -1,12 +1,7 @@
|
||||
"""
|
||||
sphinx.domains
|
||||
~~~~~~~~~~~~~~
|
||||
"""Support for domains.
|
||||
|
||||
Support for domains, which are groupings of description directives
|
||||
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.
|
||||
Domains are groupings of description directives
|
||||
and roles describing e.g. constructs of one programming language.
|
||||
"""
|
||||
|
||||
import copy
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.domains.c
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
The C language domain.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""The C language domain."""
|
||||
|
||||
import re
|
||||
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.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.deprecation import RemovedInSphinx50Warning
|
||||
from sphinx.deprecation import RemovedInSphinx60Warning
|
||||
from sphinx.directives import ObjectDescription
|
||||
from sphinx.domains import Domain, ObjType
|
||||
from sphinx.environment import BuildEnvironment
|
||||
@ -92,31 +84,22 @@ _id_prefix = [None, 'c.', 'Cv2.']
|
||||
_string_re = re.compile(r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'"
|
||||
r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
|
||||
|
||||
# bool, complex, and imaginary are macro "keywords", so they are handled seperately
|
||||
_simple_type_specifiers_re = re.compile(r"""(?x)
|
||||
\b(
|
||||
void|_Bool|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)
|
||||
void|_Bool
|
||||
|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
|
||||
""")
|
||||
|
||||
@ -226,7 +209,7 @@ class ASTNestedName(ASTBase):
|
||||
assert not self.rooted, str(self)
|
||||
assert len(self.names) == 1
|
||||
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
|
||||
# prefix.
|
||||
prefix = ''
|
||||
@ -636,8 +619,9 @@ class ASTTrailingTypeSpec(ASTBase):
|
||||
|
||||
|
||||
class ASTTrailingTypeSpecFundamental(ASTTrailingTypeSpec):
|
||||
def __init__(self, name: str) -> None:
|
||||
self.names = name.split()
|
||||
def __init__(self, names: List[str]) -> None:
|
||||
assert len(names) != 0
|
||||
self.names = names
|
||||
|
||||
def _stringify(self, transform: StringifyTransform) -> str:
|
||||
return ' '.join(self.names)
|
||||
@ -2580,12 +2564,36 @@ class DefinitionParser(BaseParser):
|
||||
break
|
||||
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:
|
||||
# fundamental types, https://en.cppreference.com/w/c/language/type
|
||||
# and extensions
|
||||
self.skip_ws()
|
||||
if self.match(_simple_type_specifiers_re):
|
||||
return ASTTrailingTypeSpecFundamental(self.matched_text)
|
||||
res = self._parse_simple_type_specifiers()
|
||||
if res is not None:
|
||||
return res
|
||||
|
||||
# prefixed
|
||||
prefix = None
|
||||
@ -3260,7 +3268,7 @@ class CObject(ObjectDescription[ASTDeclaration]):
|
||||
msg = "{}: Pre-v3 C type directive '.. c:type:: {}' converted to " \
|
||||
"'.. c:{}:: {}'." \
|
||||
"\nThe original parsing error was:\n{}"
|
||||
msg = msg.format(RemovedInSphinx50Warning.__name__,
|
||||
msg = msg.format(RemovedInSphinx60Warning.__name__,
|
||||
sig, ast.objectType, ast, eOrig)
|
||||
logger.warning(msg, location=signode)
|
||||
except DefinitionError as e:
|
||||
@ -3540,7 +3548,7 @@ class AliasTransform(SphinxTransform):
|
||||
return nodes
|
||||
|
||||
def apply(self, **kwargs: Any) -> None:
|
||||
for node in self.document.traverse(AliasNode):
|
||||
for node in self.document.findall(AliasNode):
|
||||
node = cast(AliasNode, node)
|
||||
sig = node.sig
|
||||
parentKey = node.parentKey
|
||||
@ -3638,8 +3646,7 @@ class CAliasObject(ObjectDescription):
|
||||
" When skipping the root declaration,"
|
||||
" need 'maxdepth' 0 for infinite or at least 2.",
|
||||
location=self.get_location())
|
||||
signatures = self.get_signatures()
|
||||
for i, sig in enumerate(signatures):
|
||||
for sig in self.get_signatures():
|
||||
node.append(AliasNode(sig, aliasOptions, self.state.document, env=self.env))
|
||||
return [node]
|
||||
|
||||
@ -3694,7 +3701,7 @@ class CXRefRole(XRefRole):
|
||||
if self.env.config['c_warn_on_allowed_pre_v3']:
|
||||
msg = "{}: Pre-v3 C type role ':c:type:`{}`' converted to ':c:expr:`{}`'."
|
||||
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())
|
||||
return [signode], []
|
||||
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.domains.changeset
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The changeset domain.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""The changeset domain."""
|
||||
|
||||
from typing import TYPE_CHECKING, Any, Dict, List, NamedTuple, cast
|
||||
|
||||
@ -130,7 +122,7 @@ class ChangeSetDomain(Domain):
|
||||
self.changesets.setdefault(version, []).append(changeset)
|
||||
|
||||
def clear_doc(self, docname: str) -> None:
|
||||
for version, changes in self.changesets.items():
|
||||
for changes in self.changesets.values():
|
||||
for changeset in changes[:]:
|
||||
if changeset.docname == docname:
|
||||
changes.remove(changeset)
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.domains.citation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The citation domain.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""The citation domain."""
|
||||
|
||||
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', {})
|
||||
|
||||
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:
|
||||
del self.citations[key]
|
||||
for key, docnames in list(self.citation_refs.items()):
|
||||
@ -81,7 +73,7 @@ class CitationDomain(Domain):
|
||||
docnames.add(self.env.docname)
|
||||
|
||||
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:
|
||||
logger.warning(__('Citation [%s] is not referenced.'), name,
|
||||
type='ref', subtype='citation', location=(docname, lineno))
|
||||
@ -112,7 +104,7 @@ class CitationDefinitionTransform(SphinxTransform):
|
||||
|
||||
def apply(self, **kwargs: Any) -> None:
|
||||
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
|
||||
node['docname'] = self.env.docname
|
||||
domain.note_citation(node)
|
||||
@ -131,7 +123,7 @@ class CitationReferenceTransform(SphinxTransform):
|
||||
|
||||
def apply(self, **kwargs: Any) -> None:
|
||||
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()
|
||||
ref = pending_xref(target, refdomain='citation', reftype='ref',
|
||||
reftarget=target, refwarn=True,
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.domains.cpp
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The C++ language domain.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""The C++ language domain."""
|
||||
|
||||
import re
|
||||
from typing import (Any, Callable, Dict, Generator, Iterator, List, Optional, Tuple, TypeVar,
|
||||
@ -267,6 +259,7 @@ T = TypeVar('T')
|
||||
class_object:
|
||||
goal: a class declaration, but with specification of a base class
|
||||
grammar:
|
||||
attribute-specifier-seq[opt]
|
||||
nested-name "final"[opt] (":" base-specifier-list)[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
|
||||
type specified
|
||||
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:
|
||||
goal: an element in a scoped or unscoped enum. The name should be
|
||||
injected according to the scopedness.
|
||||
@ -338,24 +332,14 @@ _keywords = [
|
||||
_simple_type_specifiers_re = re.compile(r"""(?x)
|
||||
\b(
|
||||
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
|
||||
|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
|
||||
""")
|
||||
|
||||
@ -485,12 +469,12 @@ _id_fundamental_v2 = {
|
||||
'long double': 'e',
|
||||
'__float80': 'e', '_Float64x': 'e',
|
||||
'__float128': 'g', '_Float128': 'g',
|
||||
'float _Complex': 'Cf', '_Complex float': 'Cf',
|
||||
'double _Complex': 'Cd', '_Complex double': 'Cd',
|
||||
'long double _Complex': 'Ce', '_Complex long double': 'Ce',
|
||||
'float _Imaginary': 'f', '_Imaginary float': 'f',
|
||||
'double _Imaginary': 'd', '_Imaginary double': 'd',
|
||||
'long double _Imaginary': 'e', '_Imaginary long double': 'e',
|
||||
'_Complex float': 'Cf',
|
||||
'_Complex double': 'Cd',
|
||||
'_Complex long double': 'Ce',
|
||||
'_Imaginary float': 'f',
|
||||
'_Imaginary double': 'd',
|
||||
'_Imaginary long double': 'e',
|
||||
'auto': 'Da',
|
||||
'decltype(auto)': 'Dc',
|
||||
'std::nullptr_t': 'Dn'
|
||||
@ -786,7 +770,7 @@ class ASTNestedName(ASTBase):
|
||||
assert len(self.names) == 1
|
||||
assert not self.templates[0]
|
||||
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
|
||||
# prefix. however, only the identifier part should be a link, such
|
||||
# that template args can be a link as well.
|
||||
@ -1853,8 +1837,12 @@ class ASTTrailingTypeSpec(ASTBase):
|
||||
|
||||
|
||||
class ASTTrailingTypeSpecFundamental(ASTTrailingTypeSpec):
|
||||
def __init__(self, name: str) -> None:
|
||||
self.names = name.split()
|
||||
def __init__(self, names: List[str], canonNames: List[str]) -> None:
|
||||
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:
|
||||
return ' '.join(self.names)
|
||||
@ -1862,14 +1850,14 @@ class ASTTrailingTypeSpecFundamental(ASTTrailingTypeSpec):
|
||||
def get_id(self, version: int) -> str:
|
||||
if version == 1:
|
||||
res = []
|
||||
for a in self.names:
|
||||
for a in self.canonNames:
|
||||
if a in _id_fundamental_v1:
|
||||
res.append(_id_fundamental_v1[a])
|
||||
else:
|
||||
res.append(a)
|
||||
return '-'.join(res)
|
||||
|
||||
txt = str(self)
|
||||
txt = ' '.join(self.canonNames)
|
||||
if txt not in _id_fundamental_v2:
|
||||
raise Exception(
|
||||
'Semi-internal error: Fundamental type "%s" can not be mapped '
|
||||
@ -3324,16 +3312,20 @@ class ASTBaseClass(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.final = final
|
||||
self.bases = bases
|
||||
self.attrs = attrs
|
||||
|
||||
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
|
||||
return symbol.get_full_nested_name().get_id(version)
|
||||
|
||||
def _stringify(self, transform: StringifyTransform) -> str:
|
||||
res = []
|
||||
for attr in self.attrs:
|
||||
res.append(transform(attr) + ' ')
|
||||
res.append(transform(self.name))
|
||||
if self.final:
|
||||
res.append(' final')
|
||||
@ -3350,6 +3342,9 @@ class ASTClass(ASTBase):
|
||||
def describe_signature(self, signode: TextElement, mode: str,
|
||||
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
||||
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)
|
||||
if self.final:
|
||||
signode += addnodes.desc_sig_space()
|
||||
@ -3367,8 +3362,9 @@ class ASTClass(ASTBase):
|
||||
|
||||
|
||||
class ASTUnion(ASTBase):
|
||||
def __init__(self, name: ASTNestedName) -> None:
|
||||
def __init__(self, name: ASTNestedName, attrs: List[ASTAttribute]) -> None:
|
||||
self.name = name
|
||||
self.attrs = attrs
|
||||
|
||||
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
|
||||
if version == 1:
|
||||
@ -3376,20 +3372,28 @@ class ASTUnion(ASTBase):
|
||||
return symbol.get_full_nested_name().get_id(version)
|
||||
|
||||
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,
|
||||
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
||||
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)
|
||||
|
||||
|
||||
class ASTEnum(ASTBase):
|
||||
def __init__(self, name: ASTNestedName, scoped: str,
|
||||
underlyingType: ASTType) -> None:
|
||||
def __init__(self, name: ASTNestedName, scoped: str, underlyingType: ASTType,
|
||||
attrs: List[ASTAttribute]) -> None:
|
||||
self.name = name
|
||||
self.scoped = scoped
|
||||
self.underlyingType = underlyingType
|
||||
self.attrs = attrs
|
||||
|
||||
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
|
||||
if version == 1:
|
||||
@ -3401,6 +3405,8 @@ class ASTEnum(ASTBase):
|
||||
if self.scoped:
|
||||
res.append(self.scoped)
|
||||
res.append(' ')
|
||||
for attr in self.attrs:
|
||||
res.append(transform(attr) + ' ')
|
||||
res.append(transform(self.name))
|
||||
if self.underlyingType:
|
||||
res.append(' : ')
|
||||
@ -3411,6 +3417,9 @@ class ASTEnum(ASTBase):
|
||||
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
||||
verify_description_mode(mode)
|
||||
# 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)
|
||||
if self.underlyingType:
|
||||
signode += addnodes.desc_sig_space()
|
||||
@ -5391,7 +5400,7 @@ class DefinitionParser(BaseParser):
|
||||
postFixes: List[ASTPostfixOp] = []
|
||||
while True:
|
||||
self.skip_ws()
|
||||
if prefixType in ['expr', 'cast', 'typeid']:
|
||||
if prefixType in ('expr', 'cast', 'typeid'):
|
||||
if self.skip_string_and_ws('['):
|
||||
expr = self._parse_expression()
|
||||
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:
|
||||
# fundamental types, https://en.cppreference.com/w/cpp/language/type
|
||||
# and extensions
|
||||
self.skip_ws()
|
||||
if self.match(_simple_type_specifiers_re):
|
||||
return ASTTrailingTypeSpecFundamental(self.matched_text)
|
||||
res = self._parse_simple_type_specifiers()
|
||||
if res is not None:
|
||||
return res
|
||||
|
||||
# decltype
|
||||
self.skip_ws()
|
||||
@ -6483,6 +6582,12 @@ class DefinitionParser(BaseParser):
|
||||
return ASTConcept(nestedName, initializer)
|
||||
|
||||
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()
|
||||
self.skip_ws()
|
||||
final = self.skip_word_and_ws('final')
|
||||
@ -6510,21 +6615,33 @@ class DefinitionParser(BaseParser):
|
||||
continue
|
||||
else:
|
||||
break
|
||||
return ASTClass(name, final, bases)
|
||||
return ASTClass(name, final, bases, attrs)
|
||||
|
||||
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()
|
||||
return ASTUnion(name)
|
||||
return ASTUnion(name, attrs)
|
||||
|
||||
def _parse_enum(self) -> ASTEnum:
|
||||
scoped = None # is set by CPPEnumObject
|
||||
attrs = []
|
||||
while 1:
|
||||
attr = self._parse_attribute()
|
||||
if attr is None:
|
||||
break
|
||||
attrs.append(attr)
|
||||
self.skip_ws()
|
||||
name = self._parse_nested_name()
|
||||
self.skip_ws()
|
||||
underlyingType = None
|
||||
if self.skip_string(':'):
|
||||
underlyingType = self._parse_type(named=False)
|
||||
return ASTEnum(name, scoped, underlyingType)
|
||||
return ASTEnum(name, scoped, underlyingType, attrs)
|
||||
|
||||
def _parse_enumerator(self) -> ASTEnumerator:
|
||||
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()
|
||||
if self.skip_word('template'):
|
||||
# declare a tenplate template parameter
|
||||
@ -6613,7 +6730,7 @@ class DefinitionParser(BaseParser):
|
||||
pos = self.pos
|
||||
err = None
|
||||
try:
|
||||
param = self._parse_template_paramter()
|
||||
param = self._parse_template_parameter()
|
||||
templateParams.append(param)
|
||||
except DefinitionError as eParam:
|
||||
self.pos = pos
|
||||
@ -6789,7 +6906,7 @@ class DefinitionParser(BaseParser):
|
||||
self.warn(msg)
|
||||
|
||||
newTemplates: List[Union[ASTTemplateParams, ASTTemplateIntroduction]] = []
|
||||
for i in range(numExtra):
|
||||
for _i in range(numExtra):
|
||||
newTemplates.append(ASTTemplateParams([]))
|
||||
if templatePrefix and not isMemberInstantiation:
|
||||
newTemplates.extend(templatePrefix.templates)
|
||||
@ -7375,7 +7492,7 @@ class AliasTransform(SphinxTransform):
|
||||
return nodes
|
||||
|
||||
def apply(self, **kwargs: Any) -> None:
|
||||
for node in self.document.traverse(AliasNode):
|
||||
for node in self.document.findall(AliasNode):
|
||||
node = cast(AliasNode, node)
|
||||
sig = node.sig
|
||||
parentKey = node.parentKey
|
||||
@ -7495,7 +7612,7 @@ class CPPAliasObject(ObjectDescription):
|
||||
" need 'maxdepth' 0 for infinite or at least 2.",
|
||||
location=self.get_location())
|
||||
signatures = self.get_signatures()
|
||||
for i, sig in enumerate(signatures):
|
||||
for sig in signatures:
|
||||
node.append(AliasNode(sig, aliasOptions, env=self.env))
|
||||
|
||||
contentnode = addnodes.desc_content()
|
||||
@ -7697,7 +7814,7 @@ class CPPDomain(Domain):
|
||||
typ: str, target: str, node: pending_xref,
|
||||
contnode: Element) -> Tuple[Optional[Element], Optional[str]]:
|
||||
# add parens again for those that could be functions
|
||||
if typ == 'any' or typ == 'func':
|
||||
if typ in ('any', 'func'):
|
||||
target += '()'
|
||||
parser = DefinitionParser(target, location=node, config=env.config)
|
||||
try:
|
||||
@ -7818,7 +7935,7 @@ class CPPDomain(Domain):
|
||||
if (env.config.add_function_parentheses and typ == 'func' and
|
||||
title.endswith('operator()')):
|
||||
addParen += 1
|
||||
if ((typ == 'any' or typ == 'func') and
|
||||
if (typ in ('any', 'func') and
|
||||
title.endswith('operator') and
|
||||
displayName.endswith('operator()')):
|
||||
addParen += 1
|
||||
@ -7908,7 +8025,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
|
||||
return {
|
||||
'version': 'builtin',
|
||||
'env_version': 4,
|
||||
'env_version': 5,
|
||||
'parallel_read_safe': True,
|
||||
'parallel_write_safe': True,
|
||||
}
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.domains.index
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The index domain.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""The index domain."""
|
||||
|
||||
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:
|
||||
"""Process a document after it is read by the environment."""
|
||||
entries = self.entries.setdefault(env.docname, [])
|
||||
for node in list(document.traverse(addnodes.index)):
|
||||
for node in list(document.findall(addnodes.index)):
|
||||
try:
|
||||
for entry in node['entries']:
|
||||
split_index_msg(entry[0], entry[1])
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.domains.javascript
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The JavaScript domain.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""The JavaScript domain."""
|
||||
|
||||
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)
|
||||
|
||||
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:
|
||||
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:
|
||||
del self.modules[modname]
|
||||
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.domains.math
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The math domain.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""The math domain."""
|
||||
|
||||
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple
|
||||
|
||||
@ -78,10 +70,10 @@ class MathDomain(Domain):
|
||||
def math_node(node: Node) -> bool:
|
||||
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:
|
||||
for equation_id, (doc, eqno) in list(self.equations.items()):
|
||||
for equation_id, (doc, _eqno) in list(self.equations.items()):
|
||||
if doc == docname:
|
||||
del self.equations[equation_id]
|
||||
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.domains.python
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The Python domain.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""The Python domain."""
|
||||
|
||||
import builtins
|
||||
import inspect
|
||||
@ -26,7 +18,7 @@ from sphinx import addnodes
|
||||
from sphinx.addnodes import desc_signature, pending_xref, pending_xref_condition
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.deprecation import RemovedInSphinx50Warning, RemovedInSphinx60Warning
|
||||
from sphinx.deprecation import RemovedInSphinx60Warning
|
||||
from sphinx.directives import ObjectDescription
|
||||
from sphinx.domains import Domain, Index, IndexEntry, ObjType
|
||||
from sphinx.environment import BuildEnvironment
|
||||
@ -80,46 +72,60 @@ class ModuleEntry(NamedTuple):
|
||||
deprecated: bool
|
||||
|
||||
|
||||
def type_to_xref(target: str, env: BuildEnvironment = None) -> addnodes.pending_xref:
|
||||
"""Convert a type string to a cross reference node."""
|
||||
if target == 'None':
|
||||
def parse_reftarget(reftarget: str, suppress_prefix: bool = False
|
||||
) -> Tuple[str, str, str, bool]:
|
||||
"""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'
|
||||
else:
|
||||
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:
|
||||
kwargs = {'py:module': env.ref_context.get('py:module'),
|
||||
'py:class': env.ref_context.get('py:class')}
|
||||
else:
|
||||
kwargs = {}
|
||||
|
||||
refspecific = False
|
||||
if target.startswith('.'):
|
||||
target = target[1:]
|
||||
text = target
|
||||
refspecific = True
|
||||
elif target.startswith('~'):
|
||||
target = target[1:]
|
||||
text = target.split('.')[-1]
|
||||
else:
|
||||
text = target
|
||||
reftype, target, title, refspecific = parse_reftarget(target, suppress_prefix)
|
||||
|
||||
if env.config.python_use_unqualified_type_names:
|
||||
# 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
|
||||
# module should work not-dynamically.
|
||||
shortname = text.split('.')[-1]
|
||||
shortname = title.split('.')[-1]
|
||||
contnodes: List[Node] = [pending_xref_condition('', shortname, condition='resolved'),
|
||||
pending_xref_condition('', text, condition='*')]
|
||||
pending_xref_condition('', title, condition='*')]
|
||||
else:
|
||||
contnodes = [nodes.Text(text)]
|
||||
contnodes = [nodes.Text(title)]
|
||||
|
||||
return pending_xref('', *contnodes,
|
||||
refdomain='py', reftype=reftype, reftarget=target,
|
||||
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."""
|
||||
def unparse(node: ast.AST) -> List[Node]:
|
||||
if isinstance(node, ast.Attribute):
|
||||
@ -150,6 +156,8 @@ def _parse_annotation(annotation: str, env: BuildEnvironment = None) -> List[Nod
|
||||
return unparse(node.value)
|
||||
elif isinstance(node, ast.Index):
|
||||
return unparse(node.value)
|
||||
elif isinstance(node, ast.Invert):
|
||||
return [addnodes.desc_sig_punctuation('', '~')]
|
||||
elif isinstance(node, ast.List):
|
||||
result = [addnodes.desc_sig_punctuation('', '[')]
|
||||
if node.elts:
|
||||
@ -180,6 +188,8 @@ def _parse_annotation(annotation: str, env: BuildEnvironment = None) -> List[Nod
|
||||
if isinstance(subnode, nodes.Text):
|
||||
result[i] = nodes.literal('', '', subnode)
|
||||
return result
|
||||
elif isinstance(node, ast.UnaryOp):
|
||||
return unparse(node.op) + unparse(node.operand)
|
||||
elif isinstance(node, ast.Tuple):
|
||||
if node.elts:
|
||||
result = []
|
||||
@ -196,25 +206,34 @@ def _parse_annotation(annotation: str, env: BuildEnvironment = None) -> List[Nod
|
||||
return result
|
||||
else:
|
||||
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('', "...")]
|
||||
elif isinstance(node, ast.NameConstant):
|
||||
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
|
||||
|
||||
if env is None:
|
||||
warnings.warn("The env parameter for _parse_annotation becomes required now.",
|
||||
RemovedInSphinx50Warning, stacklevel=2)
|
||||
|
||||
try:
|
||||
tree = ast_parse(annotation)
|
||||
result = unparse(tree)
|
||||
for i, node in enumerate(result):
|
||||
result: List[Node] = []
|
||||
for node in unparse(tree):
|
||||
if isinstance(node, nodes.literal):
|
||||
result[i] = node[0]
|
||||
result.append(node[0])
|
||||
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
|
||||
except SyntaxError:
|
||||
return [type_to_xref(annotation, env)]
|
||||
@ -331,19 +350,19 @@ class PyXrefMixin:
|
||||
result = super().make_xref(rolename, domain, target, # type: ignore
|
||||
innernode, contnode,
|
||||
env, inliner=None, location=None)
|
||||
if isinstance(result, pending_xref):
|
||||
result['refspecific'] = True
|
||||
result['py:module'] = env.ref_context.get('py:module')
|
||||
result['py:class'] = env.ref_context.get('py:class')
|
||||
if target.startswith(('.', '~')):
|
||||
prefix, result['reftarget'] = target[0], target[1:]
|
||||
if prefix == '.':
|
||||
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:
|
||||
|
||||
reftype, reftarget, reftitle, _ = parse_reftarget(target)
|
||||
if reftarget != reftitle:
|
||||
result['reftype'] = reftype
|
||||
result['reftarget'] = reftarget
|
||||
|
||||
result.clear()
|
||||
result += innernode(reftitle, reftitle)
|
||||
elif env.config.python_use_unqualified_type_names:
|
||||
children = result.children
|
||||
result.clear()
|
||||
|
||||
@ -384,16 +403,7 @@ class PyXrefMixin:
|
||||
|
||||
|
||||
class PyField(PyXrefMixin, Field):
|
||||
def make_xref(self, rolename: str, domain: str, target: str,
|
||||
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)
|
||||
pass
|
||||
|
||||
|
||||
class PyGroupedField(PyXrefMixin, GroupedField):
|
||||
@ -401,16 +411,7 @@ class PyGroupedField(PyXrefMixin, GroupedField):
|
||||
|
||||
|
||||
class PyTypedField(PyXrefMixin, TypedField):
|
||||
def make_xref(self, rolename: str, domain: str, target: str,
|
||||
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)
|
||||
pass
|
||||
|
||||
|
||||
class PyObject(ObjectDescription[Tuple[str, str]]):
|
||||
@ -965,29 +966,6 @@ class PyProperty(PyObject):
|
||||
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):
|
||||
"""
|
||||
Directive to mark description of a new module.
|
||||
@ -1467,7 +1445,7 @@ def builtin_resolver(app: Sphinx, env: BuildEnvironment,
|
||||
return None
|
||||
elif node.get('reftype') in ('class', 'obj') and node.get('reftarget') == 'None':
|
||||
return contnode
|
||||
elif node.get('reftype') in ('class', 'exc'):
|
||||
elif node.get('reftype') in ('class', 'obj', 'exc'):
|
||||
reftarget = node.get('reftarget')
|
||||
if inspect.isclass(getattr(builtins, reftarget, None)):
|
||||
# built-in class
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.domains.rst
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The reStructuredText domain.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""The reStructuredText domain."""
|
||||
|
||||
import re
|
||||
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)
|
||||
|
||||
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:
|
||||
del self.objects[typ, name]
|
||||
|
||||
|
@ -1,16 +1,6 @@
|
||||
"""
|
||||
sphinx.domains.std
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The standard domain.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""The standard domain."""
|
||||
|
||||
import re
|
||||
import unicodedata
|
||||
import warnings
|
||||
from copy import copy
|
||||
from typing import (TYPE_CHECKING, Any, Callable, Dict, Iterable, Iterator, List, Optional,
|
||||
Tuple, Type, Union, cast)
|
||||
@ -22,7 +12,6 @@ from docutils.statemachine import StringList
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.addnodes import desc_signature, pending_xref
|
||||
from sphinx.deprecation import RemovedInSphinx50Warning
|
||||
from sphinx.directives import ObjectDescription
|
||||
from sphinx.domains import Domain, ObjType
|
||||
from sphinx.locale import _, __
|
||||
@ -243,7 +232,7 @@ class Cmdoption(ObjectDescription[str]):
|
||||
descr = _('%s command line option') % currprogram
|
||||
else:
|
||||
descr = _('command line option')
|
||||
for option in sig.split(', '):
|
||||
for option in signode.get('allnames', []):
|
||||
entry = '; '.join([descr, option])
|
||||
self.indexnode['entries'].append(('pair', entry, signode['ids'][0], '', None))
|
||||
|
||||
@ -336,6 +325,7 @@ class Glossary(SphinxDirective):
|
||||
def run(self) -> List[Node]:
|
||||
node = addnodes.glossary()
|
||||
node.document = self.state.document
|
||||
node['sorted'] = ('sorted' in self.options)
|
||||
|
||||
# This directive implements a custom format of the reST definition list
|
||||
# that allows multiple lines of terms before the definition. This is
|
||||
@ -400,9 +390,8 @@ class Glossary(SphinxDirective):
|
||||
was_empty = False
|
||||
|
||||
# now, parse all the entries into a big definition list
|
||||
items = []
|
||||
items: List[nodes.definition_list_item] = []
|
||||
for terms, definition in entries:
|
||||
termtexts: List[str] = []
|
||||
termnodes: List[Node] = []
|
||||
system_messages: List[Node] = []
|
||||
for line, source, lineno in terms:
|
||||
@ -416,7 +405,6 @@ class Glossary(SphinxDirective):
|
||||
node_id=None, document=self.state.document)
|
||||
term.rawsource = line
|
||||
system_messages.extend(sysmsg)
|
||||
termtexts.append(term.astext())
|
||||
termnodes.append(term)
|
||||
|
||||
termnodes.extend(system_messages)
|
||||
@ -426,16 +414,10 @@ class Glossary(SphinxDirective):
|
||||
self.state.nested_parse(definition, definition.items[0][1],
|
||||
defnode)
|
||||
termnodes.append(defnode)
|
||||
items.append((termtexts,
|
||||
nodes.definition_list_item('', *termnodes)))
|
||||
items.append(nodes.definition_list_item('', *termnodes))
|
||||
|
||||
if 'sorted' in self.options:
|
||||
items.sort(key=lambda x:
|
||||
unicodedata.normalize('NFD', x[0][0].lower()))
|
||||
|
||||
dlist = nodes.definition_list()
|
||||
dlist = nodes.definition_list('', *items)
|
||||
dlist['classes'].append('glossary')
|
||||
dlist.extend(item[1] for item in items)
|
||||
node += dlist
|
||||
return messages + [node]
|
||||
|
||||
@ -675,11 +657,6 @@ class StandardDomain(Domain):
|
||||
objtype, name, docname, location=location)
|
||||
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
|
||||
def _terms(self) -> Dict[str, Tuple[str, str]]:
|
||||
""".. note:: Will be removed soon. internal use only."""
|
||||
@ -775,7 +752,7 @@ class StandardDomain(Domain):
|
||||
if not sectname:
|
||||
continue
|
||||
else:
|
||||
toctree = next(iter(node.traverse(addnodes.toctree)), None)
|
||||
toctree = next(node.findall(addnodes.toctree), None)
|
||||
if toctree and toctree.get('caption'):
|
||||
sectname = toctree.get('caption')
|
||||
else:
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
sphinx.environment
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Global creation environment.
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Global creation environment."""
|
||||
|
||||
import os
|
||||
import pickle
|
||||
@ -49,7 +41,7 @@ default_settings: Dict[str, Any] = {
|
||||
'embed_images': False,
|
||||
'embed_stylesheet': False,
|
||||
'cloak_email_addresses': True,
|
||||
'pep_base_url': 'https://www.python.org/dev/peps/',
|
||||
'pep_base_url': 'https://peps.python.org/',
|
||||
'pep_references': None,
|
||||
'rfc_base_url': 'https://datatracker.ietf.org/doc/html/',
|
||||
'rfc_references': None,
|
||||
@ -261,7 +253,7 @@ class BuildEnvironment:
|
||||
"""Update settings by new config."""
|
||||
self.settings['input_encoding'] = config.source_encoding
|
||||
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)
|
||||
self.settings.setdefault('smart_quotes', True)
|
||||
@ -535,7 +527,7 @@ class BuildEnvironment:
|
||||
self.apply_post_transforms(doctree, docname)
|
||||
|
||||
# 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,
|
||||
prune=prune_toctrees,
|
||||
includehidden=includehidden)
|
||||
@ -621,7 +613,7 @@ class BuildEnvironment:
|
||||
|
||||
def check_consistency(self) -> None:
|
||||
"""Do consistency checks."""
|
||||
included = set().union(*self.included.values()) # type: ignore
|
||||
included = set().union(*self.included.values())
|
||||
for docname in sorted(self.all_docs):
|
||||
if docname not in self.files_to_rebuild:
|
||||
if docname == self.config.root_doc:
|
||||
|
@ -1,9 +1 @@
|
||||
"""
|
||||
sphinx.environment.adapters
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sphinx environment adapters
|
||||
|
||||
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
"""Sphinx environment adapters"""
|
||||
|
@ -1,12 +1,4 @@
|
||||
"""
|
||||
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.
|
||||
"""
|
||||
"""Assets adapter for sphinx.environment."""
|
||||
|
||||
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