Merge branch '5.x' into patch-1

This commit is contained in:
Takeshi KOMIYA 2022-05-08 02:36:54 +09:00
commit a48e811781
556 changed files with 54696 additions and 54810 deletions

View File

@ -7,6 +7,7 @@ on:
jobs: jobs:
test: test:
if: github.repository_owner == 'sphinx-doc'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:

View File

@ -10,6 +10,7 @@ permissions:
jobs: jobs:
action: action:
if: github.repository_owner == 'sphinx-doc'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: dessant/lock-threads@v2 - uses: dessant/lock-threads@v2

View File

@ -5,43 +5,34 @@ on: [push, pull_request]
jobs: jobs:
ubuntu: ubuntu:
runs-on: ubuntu-18.04 runs-on: ubuntu-18.04
name: Python ${{ matrix.python }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
name: [py36, py37, py38, py39, py310]
include: include:
- name: py36 - python: "3.6"
python: 3.6
docutils: du14 docutils: du14
- name: py37 - python: "3.7"
python: 3.7
docutils: du15 docutils: du15
- name: py38 - python: "3.8"
python: 3.8
docutils: du16 docutils: du16
- name: py39 - python: "3.9"
python: 3.9
docutils: du17 docutils: du17
coverage: "--cov ./ --cov-append --cov-config setup.cfg" - python: "3.10"
- name: py310 docutils: du18
python: "3.10" - python: "3.11-dev"
docutils: du17
- name: py311-dev
python: 3.11-dev
docutils: py311 docutils: py311
env:
PYTEST_ADDOPTS: ${{ matrix.coverage }}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python }} - name: Set up Python ${{ matrix.python }}
uses: actions/setup-python@v2 uses: actions/setup-python@v3
if: "!endsWith(matrix.python, '-dev')" if: "!endsWith(matrix.python, '-dev')"
with: with:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
- name: Set up Python ${{ matrix.python }} (deadsnakes) - name: Set up Python ${{ matrix.python }} (deadsnakes)
uses: deadsnakes/action@v2.0.1 uses: deadsnakes/action@v2.0.1
if: endsWith(matrix.python, '-dev') if: "endsWith(matrix.python, '-dev')"
with: with:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
- name: Check Python version - name: Check Python version
@ -49,29 +40,48 @@ jobs:
- name: Install graphviz - name: Install graphviz
run: sudo apt-get install graphviz run: sudo apt-get install graphviz
- name: Install dependencies - name: Install dependencies
run: pip install -U tox codecov run: python -m pip install -U pip tox
- name: Install the latest py package (for py3.11-dev)
run: pip install -U git+https://github.com/pytest-dev/py
if: ${{ matrix.python == '3.11-dev' }}
- name: Run Tox - name: Run Tox
run: tox -e ${{ matrix.docutils }} -- -vv run: tox -e ${{ matrix.docutils }} -- -vv
- name: codecov
uses: codecov/codecov-action@v1
if: matrix.coverage
windows: windows:
runs-on: windows-2019 runs-on: windows-2019
strategy:
matrix:
architecture: [x86, x64]
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v1 uses: actions/setup-python@v3
with: with:
architecture: ${{ matrix.architecture }} python-version: 3
- name: Install dependencies - name: Install dependencies
run: pip install -U tox run: python -m pip install -U pip tox
- name: Run Tox - name: Run Tox
run: tox -e py -- -vv run: tox -e py -- -vv
coverage:
# only run on pushes to branches in the sphinx-doc/sphinx repo
if: github.repository_owner == 'sphinx-doc' && github.event_name == 'push'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python 3
uses: actions/setup-python@v3
with:
python-version: 3
- name: Check Python version
run: python --version
- name: Install graphviz
run: sudo apt-get install graphviz
- name: Install dependencies
run: python -m pip install -U pip tox pytest-cov
- name: Run Tox
run: tox --sitepackages -e py -- -vv
env:
PYTEST_ADDOPTS: "--cov ./ --cov-append --cov-config setup.cfg"
- name: codecov
uses: codecov/codecov-action@v3

View File

@ -6,14 +6,15 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
node-version: 10.7 node-version: 16
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Use Node.js ${{ env.node-version }} - name: Use Node.js ${{ env.node-version }}
uses: actions/setup-node@v1 uses: actions/setup-node@v2
with: with:
node-version: ${{ env.node-version }} node-version: ${{ env.node-version }}
cache: "npm"
- run: npm install - run: npm install
- name: Run headless test - name: Run headless test
uses: GabrielBB/xvfb-action@v1 uses: GabrielBB/xvfb-action@v1

View File

@ -7,46 +7,52 @@ on:
jobs: jobs:
push: push:
if: github.repository_owner == 'sphinx-doc'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
ref: 4.x ref: 5.x
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v2 uses: actions/setup-python@v2
with: with:
python-version: 3.9 # https://github.com/transifex/transifex-client/pull/330 python-version: 3.9 # https://github.com/transifex/transifex-client/pull/330
- name: Install dependencies - name: Install dependencies
run: pip install -U babel jinja2 transifex-client run: pip install -U babel jinja2 transifex-client
- name: Install Sphinx
run: pip install .
- name: Extract translations from source code - name: Extract translations from source code
run: python setup.py extract_messages run: python utils/babel_runner.py extract
- name: Push translations to transifex.com - name: Push translations to transifex.com
run: cd sphinx/locale && tx push -s --no-interactive --parallel run: cd sphinx/locale && tx push -s --no-interactive --parallel
env: env:
TX_TOKEN: ${{ secrets.TX_TOKEN }} TX_TOKEN: ${{ secrets.TX_TOKEN }}
pull: pull:
if: github.repository_owner == 'sphinx-doc'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
with: with:
ref: 4.x ref: 5.x
- name: Set up Python - name: Set up Python
uses: actions/setup-python@v2 uses: actions/setup-python@v2
with: with:
python-version: 3.9 # https://github.com/transifex/transifex-client/pull/330 python-version: 3.9 # https://github.com/transifex/transifex-client/pull/330
- name: Install dependencies - name: Install dependencies
run: pip install -U babel jinja2 transifex-client run: pip install -U babel jinja2 transifex-client
- name: Install Sphinx
run: pip install .
- name: Extract translations from source code - name: Extract translations from source code
run: python setup.py extract_messages run: python utils/babel_runner.py extract
- name: Pull translations to transifex.com - name: Pull translations to transifex.com
run: cd sphinx/locale && tx pull -a -f --no-interactive --parallel run: cd sphinx/locale && tx pull -a -f --no-interactive --parallel
env: env:
TX_TOKEN: ${{ secrets.TX_TOKEN }} TX_TOKEN: ${{ secrets.TX_TOKEN }}
- name: Compile message catalogs - name: Compile message catalogs
run: python setup.py compile_catalog run: python utils/babel_runner.py compile
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@v3 uses: peter-evans/create-pull-request@v3
with: with:

View File

@ -18,6 +18,7 @@ Other co-maintainers:
Other contributors, listed alphabetically, are: Other contributors, listed alphabetically, are:
* Adam Turner -- JavaScript improvements
* Alastair Houghton -- Apple Help builder * Alastair Houghton -- Apple Help builder
* Alexander Todorov -- inheritance_diagram tests and improvements * Alexander Todorov -- inheritance_diagram tests and improvements
* Andi Albrecht -- agogo theme * Andi Albrecht -- agogo theme
@ -73,6 +74,7 @@ Other contributors, listed alphabetically, are:
* Pauli Virtanen -- autodoc improvements, autosummary extension * Pauli Virtanen -- autodoc improvements, autosummary extension
* Eric N. Vander Weele -- autodoc improvements * Eric N. Vander Weele -- autodoc improvements
* Stefan van der Walt -- autosummary extension * Stefan van der Walt -- autosummary extension
* Hugo van Kemenade -- support FORCE_COLOR and NO_COLOR
* Thomas Waldmann -- apidoc module fixes * Thomas Waldmann -- apidoc module fixes
* John Waltman -- Texinfo builder * John Waltman -- Texinfo builder
* Barry Warsaw -- setup command improvements * Barry Warsaw -- setup command improvements

183
CHANGES
View File

@ -1,4 +1,119 @@
Release 4.5.0 (in development) Release 5.0.0 (in development)
==============================
Dependencies
------------
* #10164: Support `Docutils 0.18`_. Patch by Adam Turner.
.. _Docutils 0.18: https://docutils.sourceforge.io/RELEASE-NOTES.html#release-0-18-2021-10-26
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.builders.html.html5_ready``
* ``sphinx.io.read_doc()``
* ``sphinx.util.docutils.__version_info__``
* ``sphinx.util.docutils.is_html5_writer_available()``
* ``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``).
* #8417: autodoc: ``:inherited-members:`` option now takes multiple classes. It
allows to suppress inherited members of several classes on the module at once
by specifying the option to :rst:dir:`automodule` directive
* #9792: autodoc: Add new option for ``autodoc_typehints_description_target`` to
include undocumented return values but not undocumented parameters.
* #10285: autodoc: singledispatch functions having typehints are not documented
* autodoc: :confval:`autodoc_typehints_format` now also applies to attributes,
data, properties, and type variable bounds.
* #10258: autosummary: Recognize a documented attribute of a module as
non-imported
* #10028: Removed internal usages of JavaScript frameworks (jQuery and
underscore.js) and modernised ``doctools.js`` and ``searchtools.js`` to
EMCAScript 2018.
* #10302: C++, add support for conditional expressions (``?:``).
* #5157, #10251: Inline code is able to be highlighted via :rst:dir:`role`
directive
* #10337: Make sphinx-build faster by caching Publisher object during build
Bugs fixed
----------
* #10200: apidoc: Duplicated submodules are shown for modules having both .pyx
and .so files
* #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
* #10305: autodoc: Failed to extract optional forward-ref'ed typehints correctly
via :confval:`autodoc_type_aliases`
* #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
* #10188: LaTeX: alternating multiply referred footnotes produce a ``?`` in
pdf output
* #10318: ``:prepend:`` option of :rst:dir:`literalinclude` directive does not
work with ``:dedent:`` option
Testing
--------
Release 4.5.1 (in development)
============================== ==============================
Dependencies Dependencies
@ -10,26 +125,60 @@ Incompatible changes
Deprecated 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()`` * ``sphinx.ext.napoleon.docstring.GoogleDocstring._qualify_name()``
Features added 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 * #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 * #9494, #9456: html search: Add a config variable
:confval:`html_show_search_summary` to enable/disable the search summaries :confval:`html_show_search_summary` to enable/disable the search summaries
* #9337: HTML theme, add option ``enable_search_shortcuts`` that enables :kbd:'/' as * #9337: HTML theme, add option ``enable_search_shortcuts`` that enables :kbd:`/` as
a Quick search shortcut and :kbd:`Esc` shortcut that a Quick search shortcut and :kbd:`Esc` shortcut that
removes search highlighting. 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 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 * #10133: autodoc: Crashed when mocked module is used for type annotation
* #10146: autodoc: :confval:`autodoc_default_options` does not support * #10146: autodoc: :confval:`autodoc_default_options` does not support
``no-value`` option ``no-value`` option
* #9971: autodoc: TypeError is raised when the target object is annotated by * #9971: autodoc: TypeError is raised when the target object is annotated by
unhashable object 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 * #9529: LaTeX: named auto numbered footnote (ex. ``[#named]``) that is referred
multiple times was rendered to a question mark multiple times was rendered to a question mark
* #9924: LaTeX: multi-line :rst:dir:`cpp:function` directive has big vertical * #9924: LaTeX: multi-line :rst:dir:`cpp:function` directive has big vertical
@ -38,38 +187,14 @@ Bugs fixed
variables/structure members variables/structure members
* #10175: LaTeX: named footnote reference is linked to an incorrect footnote if * #10175: LaTeX: named footnote reference is linked to an incorrect footnote if
the name is also used in the different document 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 * #10181: napoleon: attributes are displayed like class attributes for google
style docstrings when :confval:`napoleon_use_ivar` is enabled style docstrings when :confval:`napoleon_use_ivar` is enabled
* #10122: sphinx-build: make.bat does not check the installation of sphinx-build * #10122: sphinx-build: make.bat does not check the installation of sphinx-build
command before showing help command before showing help
Testing
--------
Release 4.4.1 (in development)
==============================
Dependencies
------------
Incompatible changes
--------------------
Deprecated
----------
Features added
--------------
Bugs fixed
----------
* #9876: autodoc: Failed to document an imported class that is built from native
binary module
Testing
--------
Release 4.4.0 (released Jan 17, 2022) Release 4.4.0 (released Jan 17, 2022)
===================================== =====================================

View File

@ -15,9 +15,11 @@ Documentation using the alabaster theme
* `Alabaster <https://alabaster.readthedocs.io/>`__ * `Alabaster <https://alabaster.readthedocs.io/>`__
* `Blinker <https://pythonhosted.org/blinker/>`__ * `Blinker <https://pythonhosted.org/blinker/>`__
* `Calibre <https://manual.calibre-ebook.com/>`__ * `Calibre <https://manual.calibre-ebook.com/>`__
* `CherryPy <https://cherrypy.readthedocs.io/>`__
* `Click <https://click.palletsprojects.com/>`__ (customized) * `Click <https://click.palletsprojects.com/>`__ (customized)
* `coala <https://docs.coala.io/>`__ (customized) * `coala <https://docs.coala.io/>`__ (customized)
* `CodePy <https://documen.tician.de/codepy/>`__ * `CodePy <https://documen.tician.de/codepy/>`__
* `Django Q <https://django-q.readthedocs.io/>`__
* `Eve <https://docs.python-eve.org/>`__ (Python REST API framework) * `Eve <https://docs.python-eve.org/>`__ (Python REST API framework)
* `Fabric <https://docs.fabfile.org/>`__ * `Fabric <https://docs.fabfile.org/>`__
* `Fityk <https://fityk.nieto.pl/>`__ * `Fityk <https://fityk.nieto.pl/>`__
@ -30,19 +32,21 @@ Documentation using the alabaster theme
* `MDAnalysis <https://www.mdanalysis.org/docs/>`__ (customized) * `MDAnalysis <https://www.mdanalysis.org/docs/>`__ (customized)
* `MeshPy <https://documen.tician.de/meshpy/>`__ * `MeshPy <https://documen.tician.de/meshpy/>`__
* `Molecule <https://molecule.readthedocs.io/>`__ * `Molecule <https://molecule.readthedocs.io/>`__
* `Momotor LTI <https://momotor.org/doc/lti/canvas/>`__
* `Podman <https://docs.podman.io/>`__
* `PyCUDA <https://documen.tician.de/pycuda/>`__ * `PyCUDA <https://documen.tician.de/pycuda/>`__
* `PyOpenCL <https://documen.tician.de/pyopencl/>`__ * `PyOpenCL <https://documen.tician.de/pyopencl/>`__
* `PyLangAcq <https://pylangacq.org/>`__ * `PyLangAcq <https://pylangacq.org/>`__
* `pytest <https://docs.pytest.org/>`__ (customized) * `pytest <https://docs.pytest.org/>`__ (customized)
* `python-apt <https://apt.alioth.debian.org/python-apt-doc/>`__ * `python-apt <https://apt-team.pages.debian.net/python-apt/>`__
* `PyVisfile <https://documen.tician.de/pyvisfile/>`__ * `PyVisfile <https://documen.tician.de/pyvisfile/>`__
* `Requests <http://www.python-requests.org/>`__ * `Requests <https://docs.python-requests.org/>`__
* `searx <https://asciimoo.github.io/searx/>`__ * `searx <https://asciimoo.github.io/searx/>`__
* `Spyder <https://docs.spyder-ide.org/>`__ (customized) * `Spyder <https://docs.spyder-ide.org/>`__ (customized)
* `Tablib <http://docs.python-tablib.org/>`__ * `Tablib <http://docs.python-tablib.org/>`__
* `urllib3 <https://urllib3.readthedocs.io/>`__ (customized) * `urllib3 <https://urllib3.readthedocs.io/>`__ (customized)
* `Werkzeug <https://werkzeug.palletsprojects.com/>`__ * `Werkzeug <https://werkzeug.palletsprojects.com/>`__
* `Write the Docs <https://writethedocs-www.readthedocs.io/>`__ * `Write the Docs <https://www.writethedocs.org/>`__
Documentation using the classic theme Documentation using the classic theme
------------------------------------- -------------------------------------
@ -58,8 +62,6 @@ Documentation using the classic theme
* `Buildbot <https://docs.buildbot.net/latest/>`__ * `Buildbot <https://docs.buildbot.net/latest/>`__
* `CMake <https://cmake.org/documentation/>`__ (customized) * `CMake <https://cmake.org/documentation/>`__ (customized)
* `Chaco <https://docs.enthought.com/chaco/>`__ (customized) * `Chaco <https://docs.enthought.com/chaco/>`__ (customized)
* `CORE <https://downloads.pf.itd.nrl.navy.mil/docs/core/core-html/>`__
* `CORE Python modules <https://downloads.pf.itd.nrl.navy.mil/docs/core/core-python-html/>`__
* `Cormoran <http://cormoran.nhopkg.org/docs/>`__ * `Cormoran <http://cormoran.nhopkg.org/docs/>`__
* `DEAP <https://deap.readthedocs.io/>`__ (customized) * `DEAP <https://deap.readthedocs.io/>`__ (customized)
* `Director <https://pythonhosted.org/director/>`__ * `Director <https://pythonhosted.org/director/>`__
@ -67,27 +69,26 @@ Documentation using the classic theme
* `F2py <http://f2py.sourceforge.net/docs/>`__ * `F2py <http://f2py.sourceforge.net/docs/>`__
* `Generic Mapping Tools (GMT) <https://gmt.soest.hawaii.edu/doc/latest/>`__ (customized) * `Generic Mapping Tools (GMT) <https://gmt.soest.hawaii.edu/doc/latest/>`__ (customized)
* `Genomedata <https://noble.gs.washington.edu/proj/genomedata/doc/1.3.3/>`__ * `Genomedata <https://noble.gs.washington.edu/proj/genomedata/doc/1.3.3/>`__
* `GetFEM++ <http://getfem.org/>`__ (customized) * `GetFEM++ <https://getfem.org/>`__ (customized)
* `Glasgow Haskell Compiler <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/>`__ (customized) * `Glasgow Haskell Compiler <https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/>`__ (customized)
* `Grok <http://grok.zope.org/doc/current/>`__ (customized) * `Grok <http://grok.zope.org/doc/current/>`__ (customized)
* `GROMACS <https://manual.gromacs.org/documentation/>`__ * `GROMACS <https://manual.gromacs.org/documentation/>`__
* `GSL Shell <https://www.nongnu.org/gsl-shell/>`__ * `GSL Shell <https://www.nongnu.org/gsl-shell/>`__
* `Hands-on Python Tutorial <https://anh.cs.luc.edu/python/hands-on/3.1/handsonHtml/>`__ * `Hands-on Python Tutorial <http://anh.cs.luc.edu/python/hands-on/3.1/handsonHtml/>`__
* `Kaa <https://api.freevo.org/kaa-base/>`__ (customized) * `Kaa <https://freevo.github.io/kaa-base/>`__ (customized)
* `Leo <https://leoeditor.com/>`__ * `Leo <https://leoeditor.com/>`__ (customized)
* `LEPL <http://www.acooke.org/lepl/>`__ (customized)
* `Mayavi <https://docs.enthought.com/mayavi/mayavi/>`__ (customized) * `Mayavi <https://docs.enthought.com/mayavi/mayavi/>`__ (customized)
* `MediaGoblin <https://mediagoblin.readthedocs.io/>`__ (customized) * `MediaGoblin <https://mediagoblin.readthedocs.io/>`__ (customized)
* `mpmath <https://mpmath.org/doc/current/>`__ * `mpmath <https://mpmath.org/doc/current/>`__
* `OpenCV <https://docs.opencv.org/>`__ (customized) * `OpenCV <https://docs.opencv.org/>`__ (customized)
* `OpenEXR <https://excamera.com/articles/26/doc/index.html>`__ * `OpenEXR <https://excamera.com/articles/26/doc/index.html>`__
* `OpenGDA <http://www.opengda.org/gdadoc/html/>`__ * `OpenGDA <http://www.opengda.org/documentation/>`__
* `Peach^3 <https://peach3.nl/doc/latest/userdoc/>`__ (customized) * `phpDocumentor <https://docs.phpdoc.org/>`__ (customized)
* `Plone <https://docs.plone.org/>`__ (customized) * `Plone <https://docs.plone.org/>`__ (customized)
* `PyEMD <https://pyemd.readthedocs.io/>`__ * `PyEMD <https://pyemd.readthedocs.io/>`__
* `Pyevolve <http://pyevolve.sourceforge.net/>`__ * `Pyevolve <http://pyevolve.sourceforge.net/>`__
* `Pygame <https://www.pygame.org/docs/>`__ (customized) * `Pygame <https://www.pygame.org/docs/>`__ (customized)
* `PyMQI <https://pythonhosted.org/pymqi/>`__ * `PyMQI <https://dsuch.github.io/pymqi/>`__
* `PyQt4 <http://pyqt.sourceforge.net/Docs/PyQt4/>`__ (customized) * `PyQt4 <http://pyqt.sourceforge.net/Docs/PyQt4/>`__ (customized)
* `PyQt5 <http://pyqt.sourceforge.net/Docs/PyQt5/>`__ (customized) * `PyQt5 <http://pyqt.sourceforge.net/Docs/PyQt5/>`__ (customized)
* `Python 2 <https://docs.python.org/2/>`__ * `Python 2 <https://docs.python.org/2/>`__
@ -120,7 +121,8 @@ Documentation using the sphinxdoc theme
* `MDAnalysis Tutorial <https://www.mdanalysis.org/MDAnalysisTutorial/>`__ * `MDAnalysis Tutorial <https://www.mdanalysis.org/MDAnalysisTutorial/>`__
* `NetworkX <https://networkx.github.io/>`__ * `NetworkX <https://networkx.github.io/>`__
* `PyCantonese <https://pycantonese.org/>`__ * `PyCantonese <https://pycantonese.org/>`__
* `Pyre <https://docs.danse.us/pyre/sphinx/>`__ * `PyRe <https://hackl.science/pyre/>`__
* `Pyre <https://pyre.readthedocs.io/>`__
* `pySPACE <https://pyspace.github.io/pyspace/>`__ * `pySPACE <https://pyspace.github.io/pyspace/>`__
* `Pysparse <http://pysparse.sourceforge.net/>`__ * `Pysparse <http://pysparse.sourceforge.net/>`__
* `PyTango <https://www.esrf.eu/computing/cs/tango/tango_doc/kernel_doc/pytango/latest/>`__ * `PyTango <https://www.esrf.eu/computing/cs/tango/tango_doc/kernel_doc/pytango/latest/>`__
@ -136,8 +138,7 @@ Documentation using the nature theme
* `Alembic <https://alembic.sqlalchemy.org/>`__ * `Alembic <https://alembic.sqlalchemy.org/>`__
* `Cython <https://docs.cython.org/>`__ * `Cython <https://docs.cython.org/>`__
* `easybuild <https://easybuild.readthedocs.io/>`__ * `easybuild <https://easybuild.readthedocs.io/>`__
* `jsFiddle <http://doc.jsfiddle.net/>`__ * `libLAS <https://liblas.org/>`__ (customized)
* `libLAS <https://www.liblas.org/>`__ (customized)
* `Lmod <https://lmod.readthedocs.io/>`__ * `Lmod <https://lmod.readthedocs.io/>`__
* `MapServer <https://mapserver.org/>`__ (customized) * `MapServer <https://mapserver.org/>`__ (customized)
* `Pandas <https://pandas.pydata.org/pandas-docs/stable/>`__ * `Pandas <https://pandas.pydata.org/pandas-docs/stable/>`__
@ -154,11 +155,10 @@ Documentation using another builtin theme
* `Breathe <https://breathe.readthedocs.io/>`__ (haiku) * `Breathe <https://breathe.readthedocs.io/>`__ (haiku)
* `MPipe <https://vmlaker.github.io/mpipe/>`__ (sphinx13) * `MPipe <https://vmlaker.github.io/mpipe/>`__ (sphinx13)
* `NLTK <https://www.nltk.org/>`__ (agogo) * `NLTK <https://www.nltk.org/>`__ (agogo)
* `Programmieren mit PyGTK und Glade (German) <https://www.florian-diesch.de/doc/python-und-glade/online/>`__ (agogo, customized)
* `PyPubSub <https://pypubsub.readthedocs.io/>`__ (bizstyle) * `PyPubSub <https://pypubsub.readthedocs.io/>`__ (bizstyle)
* `Pylons <https://docs.pylonsproject.org/projects/pylons-webframework/>`__ (pyramid) * `Pylons <https://docs.pylonsproject.org/projects/pylons-webframework/>`__ (pyramid)
* `Pyramid web framework <https://docs.pylonsproject.org/projects/pyramid/>`__ (pyramid) * `Pyramid web framework <https://docs.pylonsproject.org/projects/pyramid/>`__ (pyramid)
* `RxDock <https://www.rxdock.org/documentation/html/devel/>`__ * `RxDock <https://www.rxdock.org/documentation/devel/html/>`__
* `Sphinx <https://www.sphinx-doc.org/>`__ (sphinx13) :-) * `Sphinx <https://www.sphinx-doc.org/>`__ (sphinx13) :-)
* `Valence <https://docs.valence.desire2learn.com/>`__ (haiku, customized) * `Valence <https://docs.valence.desire2learn.com/>`__ (haiku, customized)
@ -176,9 +176,12 @@ Documentation using sphinx_rtd_theme
* `Blender Reference Manual <https://docs.blender.org/manual/>`__ * `Blender Reference Manual <https://docs.blender.org/manual/>`__
* `Blocks <https://blocks.readthedocs.io/>`__ * `Blocks <https://blocks.readthedocs.io/>`__
* `bootstrap-datepicker <https://bootstrap-datepicker.readthedocs.io/>`__ * `bootstrap-datepicker <https://bootstrap-datepicker.readthedocs.io/>`__
* `Certbot <https://letsencrypt.readthedocs.io/>`__ * `Certbot <https://certbot.eff.org/docs/>`__
* `CKAN <https://docs.ckan.org/>`__
* `Copr Buildsystem <https://docs.pagure.org/copr.copr/>`__ (customized)
* `Coreboot <https://doc.coreboot.org/>`__
* `Chainer <https://docs.chainer.org/>`__ (customized) * `Chainer <https://docs.chainer.org/>`__ (customized)
* `CherryPy <https://docs.cherrypy.org/>`__ * `citeproc-js <https://citeproc-js.readthedocs.io/>`__
* `cloud-init <https://cloudinit.readthedocs.io/>`__ * `cloud-init <https://cloudinit.readthedocs.io/>`__
* `CodeIgniter <https://www.codeigniter.com/user_guide/>`__ * `CodeIgniter <https://www.codeigniter.com/user_guide/>`__
* `Conda <https://conda.io/docs/>`__ * `Conda <https://conda.io/docs/>`__
@ -187,7 +190,9 @@ Documentation using sphinx_rtd_theme
* `Databricks <https://docs.databricks.com/>`__ (customized) * `Databricks <https://docs.databricks.com/>`__ (customized)
* `Dataiku DSS <https://doc.dataiku.com/>`__ * `Dataiku DSS <https://doc.dataiku.com/>`__
* `DNF <https://dnf.readthedocs.io/>`__ * `DNF <https://dnf.readthedocs.io/>`__
* `Distro Tracker <https://qa.pages.debian.net/distro-tracker/>`__
* `Django-cas-ng <https://djangocas.dev/docs/>`__ * `Django-cas-ng <https://djangocas.dev/docs/>`__
* `dj-stripe <https://dj-stripe.readthedocs.io/>`__
* `edX <https://docs.edx.org/>`__ * `edX <https://docs.edx.org/>`__
* `Electrum <https://docs.electrum.org/>`__ * `Electrum <https://docs.electrum.org/>`__
* `Elemental <https://libelemental.org/documentation/dev/>`__ * `Elemental <https://libelemental.org/documentation/dev/>`__
@ -207,13 +212,15 @@ Documentation using sphinx_rtd_theme
* `Graylog <https://docs.graylog.org/>`__ * `Graylog <https://docs.graylog.org/>`__
* `GPAW <https://wiki.fysik.dtu.dk/gpaw/>`__ (customized) * `GPAW <https://wiki.fysik.dtu.dk/gpaw/>`__ (customized)
* `HDF5 for Python (h5py) <https://docs.h5py.org/>`__ * `HDF5 for Python (h5py) <https://docs.h5py.org/>`__
* `HyperKitty <https://hyperkitty.readthedocs.io/>`__
* `Hyperledger Fabric <https://hyperledger-fabric.readthedocs.io/>`__ * `Hyperledger Fabric <https://hyperledger-fabric.readthedocs.io/>`__
* `Hyperledger Sawtooth <https://intelledger.github.io/>`__ * `Hyperledger Sawtooth <https://sawtooth.hyperledger.org/docs/>`__
* `IdentityServer <https://docs.identityserver.io/>`__ * `IdentityServer <https://docs.identityserver.io/>`__
* `Idris <https://docs.idris-lang.org/>`__ * `Idris <https://docs.idris-lang.org/>`__
* `Inkscape <https://inkscape-manuals.readthedocs.io/>`__ (customized)
* `javasphinx <https://bronto-javasphinx.readthedocs.io/>`__ * `javasphinx <https://bronto-javasphinx.readthedocs.io/>`__
* `Julia <https://julia.readthedocs.io/>`__
* `Jupyter Notebook <https://jupyter-notebook.readthedocs.io/>`__ * `Jupyter Notebook <https://jupyter-notebook.readthedocs.io/>`__
* `Kanboard <https://docs.kanboard.org/>`__
* `Lasagne <https://lasagne.readthedocs.io/>`__ * `Lasagne <https://lasagne.readthedocs.io/>`__
* `latexindent.pl <https://latexindentpl.readthedocs.io/>`__ * `latexindent.pl <https://latexindentpl.readthedocs.io/>`__
* `Learning Apache Spark with Python <https://runawayhorse001.github.io/LearningApacheSpark>`__ * `Learning Apache Spark with Python <https://runawayhorse001.github.io/LearningApacheSpark>`__
@ -226,7 +233,6 @@ Documentation using sphinx_rtd_theme
* `Mesa 3D <https://docs.mesa3d.org/>`__ * `Mesa 3D <https://docs.mesa3d.org/>`__
* `micca - MICrobial Community Analysis <https://micca.readthedocs.io/>`__ * `micca - MICrobial Community Analysis <https://micca.readthedocs.io/>`__
* `MicroPython <https://docs.micropython.org/>`__ * `MicroPython <https://docs.micropython.org/>`__
* `Minds <https://www.minds.org/docs/>`__ (customized)
* `Mink <https://mink.behat.org/>`__ * `Mink <https://mink.behat.org/>`__
* `Mockery <https://docs.mockery.io/>`__ * `Mockery <https://docs.mockery.io/>`__
* `mod_wsgi <https://modwsgi.readthedocs.io/>`__ * `mod_wsgi <https://modwsgi.readthedocs.io/>`__
@ -234,9 +240,14 @@ Documentation using sphinx_rtd_theme
* `Mopidy <https://docs.mopidy.com/>`__ * `Mopidy <https://docs.mopidy.com/>`__
* `mpi4py <https://mpi4py.readthedocs.io/>`__ * `mpi4py <https://mpi4py.readthedocs.io/>`__
* `MyHDL <https://docs.myhdl.org/>`__ * `MyHDL <https://docs.myhdl.org/>`__
* `Mypy <https://mypy.readthedocs.io/>`__
* `Netgate Docs <https://docs.netgate.com/>`__
* `Nextcloud Server <https://docs.nextcloud.com/#server>`__
* `Nextflow <https://www.nextflow.io/docs/latest/index.html>`__ * `Nextflow <https://www.nextflow.io/docs/latest/index.html>`__
* `nghttp2 <https://nghttp2.org/documentation/>`__
* `NICOS <https://forge.frm2.tum.de/nicos/doc/nicos-master/>`__ (customized) * `NICOS <https://forge.frm2.tum.de/nicos/doc/nicos-master/>`__ (customized)
* `OpenFAST <https://openfast.readthedocs.io/>`__ * `OpenFAST <https://openfast.readthedocs.io/>`__
* `Panda3D <https://docs.panda3d.org/>`__ (customized)
* `Pelican <https://docs.getpelican.com/>`__ * `Pelican <https://docs.getpelican.com/>`__
* `picamera <https://picamera.readthedocs.io/>`__ * `picamera <https://picamera.readthedocs.io/>`__
* `Pillow <https://pillow.readthedocs.io/>`__ * `Pillow <https://pillow.readthedocs.io/>`__
@ -245,15 +256,21 @@ Documentation using sphinx_rtd_theme
* `peewee <https://docs.peewee-orm.com/>`__ * `peewee <https://docs.peewee-orm.com/>`__
* `Phinx <https://docs.phinx.org/>`__ * `Phinx <https://docs.phinx.org/>`__
* `phpMyAdmin <https://docs.phpmyadmin.net/>`__ * `phpMyAdmin <https://docs.phpmyadmin.net/>`__
* `PHPUnit <https://phpunit.readthedocs.io/>`__
* `PHPWord <https://phpword.readthedocs.io/>`__
* `PROS <https://pros.cs.purdue.edu/v5/>`__ (customized) * `PROS <https://pros.cs.purdue.edu/v5/>`__ (customized)
* `Pushkin <http://docs.pushkin.io/>`__ * `Pushkin <http://docs.pushkin.io/>`__
* `Pweave <https://mpastell.com/pweave/>`__ * `Pweave <https://mpastell.com/pweave/>`__
* `pyca/cryptograhpy <https://cryptography.io/>`__
* `PyNaCl <https://pynacl.readthedocs.io/>`__
* `pyOpenSSL <https://www.pyopenssl.org/>`__
* `PyPy <https://doc.pypy.org/>`__ * `PyPy <https://doc.pypy.org/>`__
* `python-sqlparse <https://sqlparse.readthedocs.io/>`__ * `python-sqlparse <https://sqlparse.readthedocs.io/>`__
* `PyVISA <https://pyvisa.readthedocs.io/>`__ * `PyVISA <https://pyvisa.readthedocs.io/>`__
* `pyvista <https://docs.pyvista.org/>`__ * `pyvista <https://docs.pyvista.org/>`__
* `Read The Docs <https://docs.readthedocs.io/>`__ * `Read The Docs <https://docs.readthedocs.io/>`__
* `ROCm Platform <https://rocm-documentation.readthedocs.io/>`__ * `RenderDoc <https://renderdoc.org/docs/>`__
* `ROCm Platform <https://rocmdocs.amd.com/>`__
* `Free your information from their silos (French) <https://redaction-technique.org/>`__ (customized) * `Free your information from their silos (French) <https://redaction-technique.org/>`__ (customized)
* `Releases Sphinx extension <https://releases.readthedocs.io/>`__ * `Releases Sphinx extension <https://releases.readthedocs.io/>`__
* `Qtile <https://docs.qtile.org/>`__ * `Qtile <https://docs.qtile.org/>`__
@ -269,6 +286,7 @@ Documentation using sphinx_rtd_theme
* `Sonos Controller (SoCo) <https://docs.python-soco.com/>`__ * `Sonos Controller (SoCo) <https://docs.python-soco.com/>`__
* `Sphinx AutoAPI <https://sphinx-autoapi.readthedocs.io/>`__ * `Sphinx AutoAPI <https://sphinx-autoapi.readthedocs.io/>`__
* `sphinx-argparse <https://sphinx-argparse.readthedocs.io/>`__ * `sphinx-argparse <https://sphinx-argparse.readthedocs.io/>`__
* `sphinx-tabs <https://sphinx-tabs.readthedocs.io/>`__
* `Sphinx-Gallery <https://sphinx-gallery.readthedocs.io/>`__ (customized) * `Sphinx-Gallery <https://sphinx-gallery.readthedocs.io/>`__ (customized)
* `Sphinx with Github Webpages <https://runawayhorse001.github.io/SphinxGithub>`__ * `Sphinx with Github Webpages <https://runawayhorse001.github.io/SphinxGithub>`__
* `SpotBugs <https://spotbugs.readthedocs.io/>`__ * `SpotBugs <https://spotbugs.readthedocs.io/>`__
@ -281,15 +299,18 @@ Documentation using sphinx_rtd_theme
* `Topshelf <https://docs.topshelf-project.com/>`__ * `Topshelf <https://docs.topshelf-project.com/>`__
* `Theano <http://www.deeplearning.net/software/theano/>`__ * `Theano <http://www.deeplearning.net/software/theano/>`__
* `ThreatConnect <https://docs.threatconnect.com/>`__ * `ThreatConnect <https://docs.threatconnect.com/>`__
* `TrueNAS <https://www.ixsystems.com/documentation/truenas/>`__ (customized)
* `Tuleap <https://tuleap.net/doc/en/>`__ * `Tuleap <https://tuleap.net/doc/en/>`__
* `TYPO3 <https://docs.typo3.org/>`__ (customized) * `TYPO3 <https://docs.typo3.org/>`__ (customized)
* `Veyon <https://docs.veyon.io/>`__ * `Veyon <https://docs.veyon.io/>`__
* `Ubiquity <https://micro-framework.readthedocs.io/>`__
* `uWSGI <https://uwsgi-docs.readthedocs.io/>`__ * `uWSGI <https://uwsgi-docs.readthedocs.io/>`__
* `virtualenv <https://virtualenv.readthedocs.io/>`__ * `virtualenv <https://virtualenv.readthedocs.io/>`__
* `Wagtail <https://docs.wagtail.io/>`__ * `Wagtail <https://docs.wagtail.io/>`__
* `Web Application Attack and Audit Framework (w3af) <https://docs.w3af.org/>`__ * `Web Application Attack and Audit Framework (w3af) <https://docs.w3af.org/>`__
* `Weblate <https://docs.weblate.org/>`__ * `Weblate <https://docs.weblate.org/>`__
* `x265 <https://x265.readthedocs.io/>`__ * `x265 <https://x265.readthedocs.io/>`__
* `Zeek <https://docs.zeek.org/>`__
* `Zulip <https://zulip.readthedocs.io/>`__ * `Zulip <https://zulip.readthedocs.io/>`__
Documentation using sphinx_bootstrap_theme Documentation using sphinx_bootstrap_theme
@ -317,12 +338,12 @@ Documentation using a custom theme or integrated in a website
* `Bokeh <https://bokeh.pydata.org/>`__ * `Bokeh <https://bokeh.pydata.org/>`__
* `Boto 3 <https://boto3.readthedocs.io/>`__ * `Boto 3 <https://boto3.readthedocs.io/>`__
* `CakePHP <https://book.cakephp.org/>`__ * `CakePHP <https://book.cakephp.org/>`__
* `CasperJS <http://docs.casperjs.org/>`__
* `Ceph <https://docs.ceph.com/docs/master/>`__ * `Ceph <https://docs.ceph.com/docs/master/>`__
* `Chef <https://docs.chef.io/>`__ * `Chef <https://docs.chef.io/>`__
* `CKAN <https://docs.ckan.org/>`__ * `CKAN <https://docs.ckan.org/>`__
* `Confluent Platform <https://docs.confluent.io/>`__ * `Confluent Platform <https://docs.confluent.io/>`__
* `Django <https://docs.djangoproject.com/>`__ * `Django <https://docs.djangoproject.com/>`__
* `django CMS <https://docs.django-cms.org/>`__
* `Doctrine <https://www.doctrine-project.org/>`__ * `Doctrine <https://www.doctrine-project.org/>`__
* `Enterprise Toolkit for Acrobat products <https://www.adobe.com/devnet-docs/acrobatetk/>`__ * `Enterprise Toolkit for Acrobat products <https://www.adobe.com/devnet-docs/acrobatetk/>`__
* `FreeFEM <https://doc.freefem.org/introduction/>`__ * `FreeFEM <https://doc.freefem.org/introduction/>`__
@ -335,7 +356,7 @@ Documentation using a custom theme or integrated in a website
* `Guzzle <https://docs.guzzlephp.org/>`__ * `Guzzle <https://docs.guzzlephp.org/>`__
* `H2O.ai <https://docs.h2o.ai/>`__ * `H2O.ai <https://docs.h2o.ai/>`__
* `Heka <https://hekad.readthedocs.io/>`__ * `Heka <https://hekad.readthedocs.io/>`__
* `Istihza (Turkish Python documentation project) <https://belgeler.yazbel.com/python-istihza/>`__ * `Istihza (Turkish Python documentation project) <https://python-istihza.yazbel.com/>`__
* `JupyterHub <https://jupyterhub.readthedocs.io/>`__ * `JupyterHub <https://jupyterhub.readthedocs.io/>`__
* `Kombu <http://docs.kombu.me/>`__ * `Kombu <http://docs.kombu.me/>`__
* `Lasso <https://lassoguide.com/>`__ * `Lasso <https://lassoguide.com/>`__
@ -356,6 +377,7 @@ Documentation using a custom theme or integrated in a website
* `OpenTURNS <https://openturns.github.io/openturns/master/>`__ * `OpenTURNS <https://openturns.github.io/openturns/master/>`__
* `Open vSwitch <https://docs.openvswitch.org/>`__ * `Open vSwitch <https://docs.openvswitch.org/>`__
* `PlatformIO <https://docs.platformio.org/>`__ * `PlatformIO <https://docs.platformio.org/>`__
* `Psycopg <https://www.psycopg.org/docs/>`__
* `PyEphem <https://rhodesmill.org/pyephem/>`__ * `PyEphem <https://rhodesmill.org/pyephem/>`__
* `Pygments <https://pygments.org/docs/>`__ * `Pygments <https://pygments.org/docs/>`__
* `Plone User Manual (German) <https://www.hasecke.com/plone-benutzerhandbuch/4.0/>`__ * `Plone User Manual (German) <https://www.hasecke.com/plone-benutzerhandbuch/4.0/>`__
@ -384,14 +406,16 @@ Documentation using a custom theme or integrated in a website
Homepages and other non-documentation sites Homepages and other non-documentation sites
------------------------------------------- -------------------------------------------
* `Alan Crosswell's Using the Django REST Framework and DRF-JSONAPI <http://www.columbia.edu/~alan/django-jsonapi-training/>`__
* `Arizona State University PHY494/PHY598/CHM598 Simulation approaches to Bio-and Nanophysics <https://becksteinlab.physics.asu.edu/pages/courses/2013/SimBioNano/>`__ (classic) * `Arizona State University PHY494/PHY598/CHM598 Simulation approaches to Bio-and Nanophysics <https://becksteinlab.physics.asu.edu/pages/courses/2013/SimBioNano/>`__ (classic)
* `Benoit Boissinot <https://bboissin.appspot.com/>`__ (classic, customized) * `Benoit Boissinot <https://bboissin.appspot.com/>`__ (classic, customized)
* `Computer Networks, Parallelization, and Simulation Laboratory (CNPSLab) <https://lab.miletic.net/>`__ (sphinx_rtd_theme) * `EBI Cloud Consultancy Team <https://tsi-ccdoc.readthedocs.io/>`__ (sphinx_rtd_theme)
* `Deep Learning Tutorials <http://www.deeplearning.net/tutorial/>`__ (sphinxdoc)
* `Eric Holscher <https://ericholscher.com/>`__ (alabaster) * `Eric Holscher <https://ericholscher.com/>`__ (alabaster)
* `Florian Diesch <https://www.florian-diesch.de/>`__
* `Institute for the Design of Advanced Energy Systems (IDAES) <https://idaes-pse.readthedocs.io/>`__ (sphinx_rtd_theme)
* `IDAES Examples <https://idaes.github.io/examples-pse/>`__ (sphinx_rtd_theme)
* `Lei Ma's Statistical Mechanics lecture notes <http://statisticalphysics.openmetric.org/>`__ (sphinx_bootstrap_theme) * `Lei Ma's Statistical Mechanics lecture notes <http://statisticalphysics.openmetric.org/>`__ (sphinx_bootstrap_theme)
* `Loyola University Chicago COMP 339-439 Distributed Systems course <https://books.cs.luc.edu/distributedsystems/>`__ (sphinx_bootstrap_theme) * `Loyola University Chicago CS Academic Programs <https://academics.cs.luc.edu/index.html>`__ (sphinx_rtd_theme, customized)
* `Pylearn2 <http://www.deeplearning.net/software/pylearn2/>`__ (sphinxdoc, customized)
* `PyXLL <https://www.pyxll.com/>`__ (sphinx_bootstrap_theme, customized) * `PyXLL <https://www.pyxll.com/>`__ (sphinx_bootstrap_theme, customized)
* `SciPy Cookbook <https://scipy-cookbook.readthedocs.io/>`__ (sphinx_rtd_theme) * `SciPy Cookbook <https://scipy-cookbook.readthedocs.io/>`__ (sphinx_rtd_theme)
* `Tech writer at work blog <https://blog.documatt.com/>`__ (custom theme) * `Tech writer at work blog <https://blog.documatt.com/>`__ (custom theme)
@ -444,6 +468,6 @@ Projects integrating Sphinx functionality
* `Read the Docs <https://readthedocs.org/>`__, a software-as-a-service documentation hosting platform, uses * `Read the Docs <https://readthedocs.org/>`__, a software-as-a-service documentation hosting platform, uses
Sphinx to automatically build documentation updates that are pushed to GitHub. Sphinx to automatically build documentation updates that are pushed to GitHub.
* `Spyder <https://docs.spyder-ide.org/help.html>`__, the Scientific Python Development Environment, uses Sphinx in its * `Spyder <https://docs.spyder-ide.org/current/panes/help.html>`__, the Scientific Python Development
help pane to render rich documentation for functions, classes and methods Environment, uses Sphinx in its help pane to render rich documentation for functions, classes and methods
automatically or on-demand. automatically or on-demand.

View File

@ -1,6 +1,9 @@
License for Sphinx License for Sphinx
================== ==================
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). Copyright (c) 2007-2022 by the Sphinx team (see AUTHORS file).
All rights reserved. All rights reserved.

View File

@ -66,11 +66,11 @@ doclinter:
.PHONY: test .PHONY: test
test: test:
@$(PYTHON) -X dev -m pytest -v $(TEST) @$(PYTHON) -X dev -X warn_default_encoding -m pytest -v $(TEST)
.PHONY: covertest .PHONY: covertest
covertest: covertest:
@$(PYTHON) -X dev -m pytest -v --cov=sphinx --junitxml=.junit.xml $(TEST) @$(PYTHON) -X dev -X warn_default_encoding -m pytest -v --cov=sphinx --junitxml=.junit.xml $(TEST)
.PHONY: build .PHONY: build
build: build:

View File

@ -14,7 +14,7 @@
<form action="https://groups.google.com/group/sphinx-users/boxsubscribe" <form action="https://groups.google.com/group/sphinx-users/boxsubscribe"
class="subscribeform"> class="subscribeform">
<input type="text" name="email" value="your@email" <input type="text" name="email" value="your@email"
onfocus="$(this).val('');" /> onfocus="this.value = ''" />
<input type="submit" name="sub" value="Subscribe" /> <input type="submit" name="sub" value="Subscribe" />
</form> </form>
</div> </div>

View File

@ -27,31 +27,28 @@
</style> </style>
<script> <script>
// intelligent scrolling of the sidebar content // intelligent scrolling of the sidebar content
$(window).scroll(function() { window.onscroll = () => {
var sb = $('.sphinxsidebarwrapper'); const sb = document.getElementsByClassName('sphinxsidebarwrapper')[0]
var win = $(window); const sbh = sb.offsetHeight
var sbh = sb.height(); const offset = document.getElementsByClassName('sphinxsidebar')[0].offsetTop;
var offset = $('.sphinxsidebar').position()['top']; const wintop = window.scrollTop;
var wintop = win.scrollTop(); const winbot = wintop + window.offsetHeight
var winbot = wintop + win.innerHeight(); const curtop = sb.offsetTop;
var curtop = sb.position()['top']; const curbot = curtop + sbh;
var curbot = curtop + sbh;
// does sidebar fit in window? // does sidebar fit in window?
if (sbh < win.innerHeight()) { if (sbh < window.offsetHeight) {
// yes: easy case -- always keep at the top // yes: easy case -- always keep at the top
sb.css('top', $u.min([$u.max([0, wintop - offset - 10]), sb.style.top = Math.min(Math.max(0, wintop - offset - 10), window.innerHeight - sbh - 200)
$(document).height() - sbh - 200]));
} else { } else {
// no: only scroll if top/bottom edge of sidebar is at // no: only scroll if top/bottom edge of sidebar is at
// top/bottom edge of window // top/bottom edge of window
if (curtop > wintop && curbot > winbot) { if (curtop > wintop && curbot > winbot) {
sb.css('top', $u.max([wintop - offset - 10, 0])); sb.style.top = Math.max(wintop - offset - 10, 0)
} else if (curtop < wintop && curbot < winbot) { } else if (curtop < wintop && curbot < winbot) {
sb.css('top', $u.min([winbot - sbh - offset - 20, sb.style.top = Math.min(winbot - sbh - offset - 20, window.innerHeight - sbh - 200)
$(document).height() - sbh - 200]));
} }
} }
}); }
</script> </script>
{%- endif %} {%- endif %}
{% endblock %} {% endblock %}

View File

@ -1,5 +1,6 @@
# Sphinx documentation build configuration file # Sphinx documentation build configuration file
import os
import re import re
import sphinx import sphinx
@ -81,11 +82,11 @@ autodoc_member_order = 'groupwise'
autosummary_generate = False autosummary_generate = False
todo_include_todos = True todo_include_todos = True
extlinks = {'duref': ('https://docutils.sourceforge.io/docs/ref/rst/' extlinks = {'duref': ('https://docutils.sourceforge.io/docs/ref/rst/'
'restructuredtext.html#%s', ''), 'restructuredtext.html#%s', '%s'),
'durole': ('https://docutils.sourceforge.io/docs/ref/rst/' 'durole': ('https://docutils.sourceforge.io/docs/ref/rst/'
'roles.html#%s', ''), 'roles.html#%s', '%s'),
'dudir': ('https://docutils.sourceforge.io/docs/ref/rst/' 'dudir': ('https://docutils.sourceforge.io/docs/ref/rst/'
'directives.html#%s', '')} 'directives.html#%s', '%s')}
man_pages = [ man_pages = [
('contents', 'sphinx-all', 'Sphinx documentation generator system manual', ('contents', 'sphinx-all', 'Sphinx documentation generator system manual',
@ -108,7 +109,7 @@ texinfo_documents = [
intersphinx_mapping = { intersphinx_mapping = {
'python': ('https://docs.python.org/3/', None), 'python': ('https://docs.python.org/3/', None),
'requests': ('https://requests.readthedocs.io/en/master', None), 'requests': ('https://docs.python-requests.org/en/latest/', None),
'readthedocs': ('https://docs.readthedocs.io/en/stable', None), 'readthedocs': ('https://docs.readthedocs.io/en/stable', None),
} }
@ -139,10 +140,33 @@ def parse_event(env, sig, signode):
return name return name
def linkify_issues_in_changelog(app, docname, source):
""" Linkify issue references like #123 in changelog to GitHub. """
if docname == 'changes':
changelog_path = os.path.join(os.path.dirname(__file__), "../CHANGES")
# this path trickery is needed because this script can
# be invoked with different working directories:
# * running make in docs/
# * running tox -e docs in the repo root dir
with open(changelog_path, encoding="utf-8") as f:
changelog = f.read()
def linkify(match):
url = 'https://github.com/sphinx-doc/sphinx/issues/' + match[1]
return '`{} <{}>`_'.format(match[0], url)
linkified_changelog = re.sub(r'(?:PR)?#([0-9]+)\b', linkify, changelog)
source[0] = source[0].replace('.. include:: ../CHANGES', linkified_changelog)
def setup(app): def setup(app):
from sphinx.ext.autodoc import cut_lines from sphinx.ext.autodoc import cut_lines
from sphinx.util.docfields import GroupedField from sphinx.util.docfields import GroupedField
app.connect('autodoc-process-docstring', cut_lines(4, what=['module'])) app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
app.connect('source-read', linkify_issues_in_changelog)
app.add_object_type('confval', 'confval', app.add_object_type('confval', 'confval',
objname='configuration value', objname='configuration value',
indextemplate='pair: %s; configuration value') indextemplate='pair: %s; configuration value')

View File

@ -265,7 +265,7 @@ Here is some sample code to accomplish this:
copy_asset_file('path/to/myextension/_static/myjsfile.js', staticdir) copy_asset_file('path/to/myextension/_static/myjsfile.js', staticdir)
def setup(app): def setup(app):
app.connect('builder-inited', copy_custom_files) app.connect('build-finished', copy_custom_files)
Inject JavaScript based on user configuration Inject JavaScript based on user configuration

View File

@ -70,7 +70,7 @@ def merge_todos(app, env, docnames, other):
def process_todo_nodes(app, doctree, fromdocname): def process_todo_nodes(app, doctree, fromdocname):
if not app.config.todo_include_todos: if not app.config.todo_include_todos:
for node in doctree.traverse(todo): for node in doctree.findall(todo):
node.parent.remove(node) node.parent.remove(node)
# Replace all todolist nodes with a list of the collected todos. # Replace all todolist nodes with a list of the collected todos.
@ -80,7 +80,7 @@ def process_todo_nodes(app, doctree, fromdocname):
if not hasattr(env, 'todo_all_todos'): if not hasattr(env, 'todo_all_todos'):
env.todo_all_todos = [] env.todo_all_todos = []
for node in doctree.traverse(todolist): for node in doctree.findall(todolist):
if not app.config.todo_include_todos: if not app.config.todo_include_todos:
node.replace_self([]) node.replace_self([])
continue continue
@ -93,7 +93,7 @@ def process_todo_nodes(app, doctree, fromdocname):
description = ( description = (
_('(The original entry is located in %s, line %d and can be found ') % _('(The original entry is located in %s, line %d and can be found ') %
(filename, todo_info['lineno'])) (filename, todo_info['lineno']))
para += nodes.Text(description, description) para += nodes.Text(description)
# Create a reference # Create a reference
newnode = nodes.reference('', '') newnode = nodes.reference('', '')
@ -104,7 +104,7 @@ def process_todo_nodes(app, doctree, fromdocname):
newnode['refuri'] += '#' + todo_info['target']['refid'] newnode['refuri'] += '#' + todo_info['target']['refid']
newnode.append(innernode) newnode.append(innernode)
para += newnode para += newnode
para += nodes.Text('.)', '.)') para += nodes.Text('.)')
# Insert into the todolist # Insert into the todolist
content.append(todo_info['todo']) content.append(todo_info['todo'])

View File

@ -22,6 +22,51 @@ The following is a list of deprecated interfaces.
- (will be) Removed - (will be) Removed
- Alternatives - Alternatives
* - ``sphinx.util.jsdump``
- 5.0
- 7.0
- The standard library ``json`` module.
* - :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.builders.html.html5_ready``
- 5.0
- 7.0
- N/A
* - ``sphinx.io.read_doc()``
- 5.0
- 7.0
- ``sphinx.builders.Builder.read_doc()``
* - ``sphinx.util.docutils.__version_info__``
- 5.0
- 7.0
- ``docutils.__version_info__``
* - ``sphinx.util.docutils.is_html5_writer_available()``
- 5.0
- 7.0
- N/A
* - ``sphinx.writers.latex.LaTeXWriter.docclasses``
- 5.0
- 7.0
- N/A
* - ``sphinx.ext.napoleon.docstring.GoogleDocstring._qualify_name()`` * - ``sphinx.ext.napoleon.docstring.GoogleDocstring._qualify_name()``
- 4.5 - 4.5
- 6.0 - 6.0

View File

@ -178,7 +178,7 @@ as metadata of the extension. Metadata keys currently recognized are:
* The core logic of the extension is parallelly executable during * The core logic of the extension is parallelly executable during
the reading phase. the reading phase.
* It has event handlers for :event:`env-merge-info` and * It has event handlers for :event:`env-merge-info` and
:event:`env-purge-doc` events if it stores dataa to the build :event:`env-purge-doc` events if it stores data to the build
environment object (env) during the reading phase. environment object (env) during the reading phase.
* ``'parallel_write_safe'``: a boolean that specifies if parallel writing of * ``'parallel_write_safe'``: a boolean that specifies if parallel writing of

View File

@ -35,3 +35,4 @@ to configure their settings appropriately.
.. module:: sphinx.parsers .. module:: sphinx.parsers
.. autoclass:: Parser .. autoclass:: Parser
:members:

View File

@ -350,19 +350,3 @@ The following notes may be helpful if you want to create Texinfo files:
scheme ``info``. For example:: scheme ``info``. For example::
info:Texinfo#makeinfo_options info:Texinfo#makeinfo_options
- Inline markup
The standard formatting for ``*strong*`` and ``_emphasis_`` can
result in ambiguous output when used to markup parameter names and
other values. Since this is a fairly common practice, the default
formatting has been changed so that ``emphasis`` and ``strong`` are
now displayed like ```literal'``\s.
The standard formatting can be re-enabled by adding the following to
your :file:`conf.py`::
texinfo_elements = {'preamble': """
@definfoenclose strong,*,*
@definfoenclose emph,_,_
"""}

View File

@ -252,17 +252,19 @@ locales. The translations are kept as gettext ``.po`` files translated from the
master template :file:`sphinx/locale/sphinx.pot`. master template :file:`sphinx/locale/sphinx.pot`.
Sphinx uses `Babel <https://babel.pocoo.org/en/latest/>`_ to extract messages Sphinx uses `Babel <https://babel.pocoo.org/en/latest/>`_ to extract messages
and maintain the catalog files. It is integrated in ``setup.py``: and maintain the catalog files. The ``utils`` directory contains a helper
script, ``babel_runner.py``.
* Use ``python setup.py extract_messages`` to update the ``.pot`` template. * Use ``python babel_runner.py extract`` to update the ``.pot`` template.
* Use ``python setup.py update_catalog`` to update all existing language * Use ``python babel_runner.py update`` to update all existing language
catalogs in ``sphinx/locale/*/LC_MESSAGES`` with the current messages in the catalogs in ``sphinx/locale/*/LC_MESSAGES`` with the current messages in the
template file. template file.
* Use ``python setup.py compile_catalog`` to compile the ``.po`` files to binary * Use ``python babel_runner.py compile`` to compile the ``.po`` files to binary
``.mo`` files and ``.js`` files. ``.mo`` files and ``.js`` files.
When an updated ``.po`` file is submitted, run compile_catalog to commit both When an updated ``.po`` file is submitted, run
the source and the compiled catalogs. ``python babel_runner.py compile`` to commit both the source and the compiled
catalogs.
When a new locale is submitted, add a new directory with the ISO 639-1 language When a new locale is submitted, add a new directory with the ISO 639-1 language
identifier and put ``sphinx.po`` in there. Don't forget to update the possible identifier and put ``sphinx.po`` in there. Don't forget to update the possible
@ -273,9 +275,9 @@ The Sphinx core messages can also be translated on `Transifex
which is provided by the ``transifex_client`` Python package, can be used to which is provided by the ``transifex_client`` Python package, can be used to
pull translations in ``.po`` format from Transifex. To do this, go to pull translations in ``.po`` format from Transifex. To do this, go to
``sphinx/locale`` and then run ``tx pull -f -l LANG`` where ``LANG`` is an ``sphinx/locale`` and then run ``tx pull -f -l LANG`` where ``LANG`` is an
existing language identifier. It is good practice to run ``python setup.py existing language identifier. It is good practice to run
update_catalog`` afterwards to make sure the ``.po`` file has the canonical ``python babel_runner.py update`` afterwards to make sure the ``.po`` file has the
Babel formatting. canonical Babel formatting.
Debugging tips Debugging tips

View File

@ -100,6 +100,27 @@ But you can also explicitly enable the pending ones using e.g.
``PYTHONWARNINGS=default`` (see the :ref:`Python docs on configuring warnings ``PYTHONWARNINGS=default`` (see the :ref:`Python docs on configuring warnings
<python:describing-warning-filters>`) for more details. <python:describing-warning-filters>`) for more details.
Python version support policy
-----------------------------
The minimum Python version Sphinx supports is the default Python version
installed in the oldest `Long Term Support version of
Ubuntu <https://ubuntu.com/about/release-cycle>`_ that has standard support.
For example, as of July 2021, Ubuntu 16.04 has just entered extended
security maintenance (therefore, it doesn't count as standard support) and
the oldest LTS release to consider is Ubuntu 18.04 LTS, supported until
April 2023 and shipping Python 3.6.
This is a summary table with the current policy:
========== ========= ======
Date Ubuntu Python
========== ========= ======
April 2021 18.04 LTS 3.6+
---------- --------- ------
April 2023 20.04 LTS 3.8+
========== ========= ======
Release procedures Release procedures
------------------ ------------------

View File

@ -304,6 +304,22 @@ variables to customize behavior:
Additional options for :program:`sphinx-build`. These options can Additional options for :program:`sphinx-build`. These options can
also be set via the shortcut variable **O** (capital 'o'). also be set via the shortcut variable **O** (capital 'o').
.. describe:: NO_COLOR
When set (regardless of value), :program:`sphinx-build` will not use color
in terminal output. ``NO_COLOR`` takes precedence over ``FORCE_COLOR``. See
`no-color.org <https://no-color.org/>`__ for other libraries supporting this
community standard.
.. versionadded:: 4.5.0
.. describe:: FORCE_COLOR
When set (regardless of value), :program:`sphinx-build` will use color in
terminal output. ``NO_COLOR`` takes precedence over ``FORCE_COLOR``.
.. versionadded:: 4.5.0
.. _when-deprecation-warnings-are-displayed: .. _when-deprecation-warnings-are-displayed:
Deprecation Warnings Deprecation Warnings

View File

@ -4,10 +4,9 @@ Automatic documentation generation from code
In the :ref:`previous section <tutorial-describing-objects>` of the tutorial In the :ref:`previous section <tutorial-describing-objects>` of the tutorial
you manually documented a Python function in Sphinx. However, the description you manually documented a Python function in Sphinx. However, the description
was out of sync with the code itself, since the function signature was not was out of sync with the code itself, since the function signature was not
the same. Besides, it would be nice to reuse `Python the same. Besides, it would be nice to reuse :pep:`Python docstrings
docstrings <https://www.python.org/dev/peps/pep-0257/#what-is-a-docstring>`_ <257#what-is-a-docstring>` in the documentation, rather than having to write
in the documentation, rather than having to write the information in two the information in two places.
places.
Fortunately, :doc:`the autodoc extension </usage/extensions/autodoc>` provides this Fortunately, :doc:`the autodoc extension </usage/extensions/autodoc>` provides this
functionality. functionality.

View File

@ -57,7 +57,7 @@ Notice several things:
- Sphinx parsed the argument of the ``.. py:function`` directive and - Sphinx parsed the argument of the ``.. py:function`` directive and
highlighted the module, the function name, and the parameters appropriately. highlighted the module, the function name, and the parameters appropriately.
- The directive content includes a one-line description of the function, - The directive content includes a one-line description of the function,
as well as a :ref:`info field list <info-field-lists>` containing the function as well as an :ref:`info field list <info-field-lists>` containing the function
parameter, its expected type, the return value, and the return type. parameter, its expected type, the return value, and the return type.
.. note:: .. note::

View File

@ -68,6 +68,24 @@ be translated you need to follow these instructions:
* Run your desired build. * Run your desired build.
In order to protect against mistakes, a warning is emitted if
cross-references in the translated paragraph do not match those from the
original. This can be turned off globally using the
:confval:`suppress_warnings` configuration variable. Alternatively, to
turn it off for one message only, end the message with ``#noqa`` like
this::
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
risus tortor, luctus id ultrices at. #noqa
(Write ``\#noqa`` in case you want to have "#noqa" literally in the
text. This does not apply to code blocks, where ``#noqa`` is ignored
because code blocks do not contain references anyway.)
.. versionadded:: 4.5
The ``#noqa`` mechanism.
Translating with sphinx-intl Translating with sphinx-intl
---------------------------- ----------------------------

View File

@ -6,6 +6,10 @@ Setuptools integration
Sphinx supports integration with setuptools and distutils through a custom Sphinx supports integration with setuptools and distutils through a custom
command - :class:`~sphinx.setup_command.BuildDoc`. command - :class:`~sphinx.setup_command.BuildDoc`.
.. deprecated:: 5.0
This feature will be removed in v7.0.
Using setuptools integration Using setuptools integration
---------------------------- ----------------------------

View File

@ -316,7 +316,11 @@ General configuration
* ``app.add_role`` * ``app.add_role``
* ``app.add_generic_role`` * ``app.add_generic_role``
* ``app.add_source_parser`` * ``app.add_source_parser``
* ``autosectionlabel.*``
* ``download.not_readable`` * ``download.not_readable``
* ``epub.unknown_project_files``
* ``epub.duplicated_toc_entry``
* ``i18n.inconsistent_references``
* ``image.not_readable`` * ``image.not_readable``
* ``ref.term`` * ``ref.term``
* ``ref.ref`` * ``ref.ref``
@ -332,11 +336,9 @@ General configuration
* ``toc.excluded`` * ``toc.excluded``
* ``toc.not_readable`` * ``toc.not_readable``
* ``toc.secnum`` * ``toc.secnum``
* ``epub.unknown_project_files``
* ``epub.duplicated_toc_entry``
* ``autosectionlabel.*``
You can choose from these types. You can choose from these types. You can also give only the first
component to exclude all warnings attached to it.
Now, this option should be considered *experimental*. Now, this option should be considered *experimental*.
@ -366,6 +368,10 @@ General configuration
Added ``toc.excluded`` and ``toc.not_readable`` Added ``toc.excluded`` and ``toc.not_readable``
.. versionadded:: 4.5
Added ``i18n.inconsistent_references``
.. confval:: needs_sphinx .. confval:: needs_sphinx
If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will
@ -392,7 +398,7 @@ General configuration
.. confval:: manpages_url .. confval:: manpages_url
A URL to cross-reference :rst:role:`manpage` directives. If this is A URL to cross-reference :rst:role:`manpage` roles. If this is
defined to ``https://manpages.debian.org/{path}``, the defined to ``https://manpages.debian.org/{path}``, the
:literal:`:manpage:`man(1)`` role will link to :literal:`:manpage:`man(1)`` role will link to
<https://manpages.debian.org/man(1)>. The patterns available are: <https://manpages.debian.org/man(1)>. The patterns available are:
@ -546,7 +552,7 @@ General configuration
make latex O="-D smartquotes_action=" make latex O="-D smartquotes_action="
This can follow some ``make html`` with no problem, in contrast to the This can follow some ``make html`` with no problem, in contrast to the
situation from the prior note. It requires Docutils 0.14 or later. situation from the prior note.
.. versionadded:: 1.6.6 .. versionadded:: 1.6.6

View File

@ -41,7 +41,7 @@ you can also enable the :mod:`napoleon <sphinx.ext.napoleon>` extension.
docstrings to correct reStructuredText before :mod:`autodoc` processes them. docstrings to correct reStructuredText before :mod:`autodoc` processes them.
.. _Google: https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings .. _Google: https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings
.. _NumPy: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt .. _NumPy: https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard
Directives Directives
@ -266,6 +266,10 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
``__str__`` will be documented as in the past, but other special method ``__str__`` will be documented as in the past, but other special method
that are not implemented in your class ``Foo``. that are not implemented in your class ``Foo``.
Since v5.0, it can take a comma separated list of ancestor classes. It
allows to suppress inherited members of several classes on the module at
once by specifying the option to :rst:dir:`automodule` directive.
Note: this will lead to markup errors if the inherited members come from a Note: this will lead to markup errors if the inherited members come from a
module whose docstrings are not reST formatted. module whose docstrings are not reST formatted.
@ -275,6 +279,10 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
It takes an ancestor class name as an argument. It takes an ancestor class name as an argument.
.. versionchanged:: 5.0
It takes a comma separated list of ancestor class names.
* It's possible to override the signature for explicitly documented callable * It's possible to override the signature for explicitly documented callable
objects (functions, methods, classes) with the regular syntax that will objects (functions, methods, classes) with the regular syntax that will
override the signature gained from introspection:: override the signature gained from introspection::
@ -468,7 +476,7 @@ There are also config values that you can set:
.. confval:: autodoc_class_signature .. confval:: autodoc_class_signature
This value selects how the signautre will be displayed for the class defined This value selects how the signature will be displayed for the class defined
by :rst:dir:`autoclass` directive. The possible values are: by :rst:dir:`autoclass` directive. The possible values are:
``"mixed"`` ``"mixed"``
@ -626,16 +634,24 @@ There are also config values that you can set:
When set to ``"documented"``, types will only be documented for a parameter When set to ``"documented"``, types will only be documented for a parameter
or a return value that is already documented by the docstring. or a return value that is already documented by the docstring.
With ``"documented_params"``, parameter types will only be annotated if the
parameter is documented in the docstring. The return type is always
annotated (except if it is ``None``).
.. versionadded:: 4.0 .. versionadded:: 4.0
.. versionadded:: 5.0
New option ``'documented_params'`` is added.
.. confval:: autodoc_type_aliases .. confval:: autodoc_type_aliases
A dictionary for users defined `type aliases`__ that maps a type name to the A dictionary for users defined `type aliases`__ that maps a type name to the
full-qualified object name. It is used to keep type aliases not evaluated in full-qualified object name. It is used to keep type aliases not evaluated in
the document. Defaults to empty (``{}``). the document. Defaults to empty (``{}``).
The type aliases are only available if your program enables `Postponed The type aliases are only available if your program enables :pep:`Postponed
Evaluation of Annotations (PEP 563)`__ feature via ``from __future__ import Evaluation of Annotations (PEP 563) <563>` feature via ``from __future__ import
annotations``. annotations``.
For example, there is code using a type alias:: For example, there is code using a type alias::
@ -662,7 +678,6 @@ There are also config values that you can set:
... ...
.. __: https://www.python.org/dev/peps/pep-0563/
.. __: https://mypy.readthedocs.io/en/latest/kinds_of_types.html#type-aliases .. __: https://mypy.readthedocs.io/en/latest/kinds_of_types.html#type-aliases
.. versionadded:: 3.3 .. versionadded:: 3.3
@ -672,12 +687,15 @@ There are also config values that you can set:
following values: following values:
* ``'fully-qualified'`` -- Show the module name and its name of typehints * ``'fully-qualified'`` -- Show the module name and its name of typehints
(default)
* ``'short'`` -- Suppress the leading module names of the typehints * ``'short'`` -- Suppress the leading module names of the typehints
(ex. ``io.StringIO`` -> ``StringIO``) (ex. ``io.StringIO`` -> ``StringIO``) (default)
.. versionadded:: 4.4 .. versionadded:: 4.4
.. versionchanged:: 5.0
The default setting was changed to ``'short'``
.. confval:: autodoc_preserve_defaults .. confval:: autodoc_preserve_defaults
If True, the default argument values of functions will be not evaluated on If True, the default argument values of functions will be not evaluated on

View File

@ -93,8 +93,8 @@ a comma-separated list of group names.
* ``<``, ``>``: Exclusive ordered comparison clause * ``<``, ``>``: Exclusive ordered comparison clause
* ``===``: Arbitrary equality clause. * ``===``: Arbitrary equality clause.
``pyversion`` option is followed `PEP-440: Version Specifiers ``pyversion`` option is followed :pep:`PEP-440: Version Specifiers
<https://www.python.org/dev/peps/pep-0440/#version-specifiers>`__. <440#version-specifiers>`.
.. versionadded:: 1.6 .. versionadded:: 1.6

View File

@ -45,7 +45,7 @@ on the first line, separated by a colon.
def function_with_types_in_docstring(param1, param2): def function_with_types_in_docstring(param1, param2):
"""Example function with types documented in the docstring. """Example function with types documented in the docstring.
`PEP 484`_ type annotations are supported. If attribute, parameter, and :pep:`484` type annotations are supported. If attribute, parameter, and
return types are annotated according to `PEP 484`_, they do not need to be return types are annotated according to `PEP 484`_, they do not need to be
included in the docstring: included in the docstring:
@ -55,10 +55,6 @@ def function_with_types_in_docstring(param1, param2):
Returns: Returns:
bool: The return value. True for success, False otherwise. bool: The return value. True for success, False otherwise.
.. _PEP 484:
https://www.python.org/dev/peps/pep-0484/
""" """
@ -311,4 +307,4 @@ class ExamplePEP526Class:
""" """
attr1: str attr1: str
attr2: int attr2: int

View File

@ -37,8 +37,8 @@ module_level_variable1 : int
with it. with it.
.. _NumPy Documentation HOWTO: .. _NumPy docstring standard:
https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard
""" """
@ -55,7 +55,7 @@ on the first line, separated by a colon.
def function_with_types_in_docstring(param1, param2): def function_with_types_in_docstring(param1, param2):
"""Example function with types documented in the docstring. """Example function with types documented in the docstring.
`PEP 484`_ type annotations are supported. If attribute, parameter, and :pep:`484` type annotations are supported. If attribute, parameter, and
return types are annotated according to `PEP 484`_, they do not need to be return types are annotated according to `PEP 484`_, they do not need to be
included in the docstring: included in the docstring:
@ -70,10 +70,6 @@ def function_with_types_in_docstring(param1, param2):
------- -------
bool bool
True if successful, False otherwise. True if successful, False otherwise.
.. _PEP 484:
https://www.python.org/dev/peps/pep-0484/
""" """

View File

@ -59,3 +59,11 @@ The extension adds a config value:
Since links are generated from the role in the reading stage, they appear as Since links are generated from the role in the reading stage, they appear as
ordinary links to e.g. the ``linkcheck`` builder. ordinary links to e.g. the ``linkcheck`` builder.
.. confval:: extlinks_detect_hardcoded_links
If enabled, extlinks emits a warning if a hardcoded link is replaceable
by an extlink, and suggests a replacement via warning. It defaults to
``False``.
.. versionadded:: 4.5

View File

@ -157,6 +157,10 @@ linking:
.. versionadded:: 4.3 .. versionadded:: 4.3
.. versionchanged:: 5.0
Changed default value from an empty list to ``['std:doc']``.
A list of strings being either: A list of strings being either:
- the name of a specific reference type in a domain, - the name of a specific reference type in a domain,
@ -165,7 +169,7 @@ linking:
``std:*``, ``py:*``, or ``cpp:*``, or ``std:*``, ``py:*``, or ``cpp:*``, or
- simply a wildcard ``*``. - simply a wildcard ``*``.
The default value is an empty list. The default value is ``['std:doc']``.
When a non-:rst:role:`external` cross-reference is being resolved by When a non-:rst:role:`external` cross-reference is being resolved by
intersphinx, skip resolution if it matches one of the specifications in this intersphinx, skip resolution if it matches one of the specifications in this

View File

@ -26,7 +26,7 @@ Are you tired of writing docstrings that look like this::
:rtype: BufferedFileStorage :rtype: BufferedFileStorage
`reStructuredText`_ is great, but it creates visually dense, hard to read `reStructuredText`_ is great, but it creates visually dense, hard to read
`docstrings`_. Compare the jumble above to the same thing rewritten :pep:`docstrings <287>`. Compare the jumble above to the same thing rewritten
according to the `Google Python Style Guide`_:: according to the `Google Python Style Guide`_::
Args: Args:
@ -50,11 +50,10 @@ the documentation, so it doesn't modify any of the docstrings in your actual
source code files. source code files.
.. _ReStructuredText: https://docutils.sourceforge.io/rst.html .. _ReStructuredText: https://docutils.sourceforge.io/rst.html
.. _docstrings: https://www.python.org/dev/peps/pep-0287/
.. _Google Python Style Guide: .. _Google Python Style Guide:
https://google.github.io/styleguide/pyguide.html https://google.github.io/styleguide/pyguide.html
.. _Google: .. _Google:
https://google.github.io/styleguide/pyguide.html#Comments https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings
.. _NumPy: .. _NumPy:
https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard
.. _Khan Academy: .. _Khan Academy:
@ -199,11 +198,11 @@ not be mixed. Choose one style for your project and be consistent with it.
Type Annotations Type Annotations
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
`PEP 484`_ introduced a standard way to express types in Python code. :pep:`484` introduced a standard way to express types in Python code.
This is an alternative to expressing types directly in docstrings. This is an alternative to expressing types directly in docstrings.
One benefit of expressing types according to `PEP 484`_ is that One benefit of expressing types according to :pep:`484` is that
type checkers and IDEs can take advantage of them for static code type checkers and IDEs can take advantage of them for static code
analysis. `PEP 484`_ was then extended by `PEP 526`_ which introduced analysis. :pep:`484` was then extended by :pep:`526` which introduced
a similar way to annotate variables (and attributes). a similar way to annotate variables (and attributes).
Google style with Python 3 type annotations:: Google style with Python 3 type annotations::
@ -267,9 +266,7 @@ Google style with types in docstrings::
`Python 2/3 compatible annotations`_ aren't currently `Python 2/3 compatible annotations`_ aren't currently
supported by Sphinx and won't show up in the docs. supported by Sphinx and won't show up in the docs.
.. _PEP 484: https://www.python.org/dev/peps/pep-0484/ .. _Python 2/3 compatible annotations: https://peps.python.org/pep-0484/#suggested-syntax-for-python-2-7-and-straddling-code
.. _PEP 526: https://www.python.org/dev/peps/pep-0526/
.. _Python 2/3 compatible annotations: https://www.python.org/dev/peps/pep-0484/#suggested-syntax-for-python-2-7-and-straddling-code
Configuration Configuration
@ -301,7 +298,7 @@ sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
napoleon_attr_annotations = True napoleon_attr_annotations = True
.. _Google style: .. _Google style:
https://google.github.io/styleguide/pyguide.html https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings
.. _NumPy style: .. _NumPy style:
https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard
@ -548,7 +545,7 @@ sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
.. confval:: napoleon_attr_annotations .. confval:: napoleon_attr_annotations
True to allow using `PEP 526`_ attributes annotations in classes. True to allow using :pep:`526` attributes annotations in classes.
If an attribute is documented in the docstring without a type and If an attribute is documented in the docstring without a type and
has an annotation in the class body, that type is used. has an annotation in the class body, that type is used.

View File

@ -222,8 +222,8 @@ of images:
- `sphinxdoc/sphinx-latexpdf`_ - `sphinxdoc/sphinx-latexpdf`_
.. _Docker Hub: https://hub.docker.com/ .. _Docker Hub: https://hub.docker.com/
.. _sphinxdoc/sphinx: https://hub.docker.com/repository/docker/sphinxdoc/sphinx .. _sphinxdoc/sphinx: https://hub.docker.com/r/sphinxdoc/sphinx
.. _sphinxdoc/sphinx-latexpdf: https://hub.docker.com/repository/docker/sphinxdoc/sphinx-latexpdf .. _sphinxdoc/sphinx-latexpdf: https://hub.docker.com/r/sphinxdoc/sphinx-latexpdf
Former one is used for standard usage of Sphinx, and latter one is mainly used for Former one is used for standard usage of Sphinx, and latter one is mainly used for
PDF builds using LaTeX. Please choose one for your purpose. PDF builds using LaTeX. Please choose one for your purpose.
@ -243,7 +243,7 @@ PDF builds using LaTeX. Please choose one for your purpose.
$ docker run -it --rm -v /path/to/document:/docs sphinxdoc/sphinx sphinx-quickstart $ docker run -it --rm -v /path/to/document:/docs sphinxdoc/sphinx sphinx-quickstart
And you can following command this to build HTML document: And you can use the following command to build HTML document:
.. code-block:: console .. code-block:: console
@ -251,7 +251,7 @@ PDF builds using LaTeX. Please choose one for your purpose.
For more details, please read `README file`__ of docker images. For more details, please read `README file`__ of docker images.
.. __: https://hub.docker.com/repository/docker/sphinxdoc/sphinx .. __: https://hub.docker.com/r/sphinxdoc/sphinx
Installation from source Installation from source

View File

@ -499,8 +499,10 @@ __ https://pygments.org/docs/lexers
The directive's alias name :rst:dir:`sourcecode` works as well. This The directive's alias name :rst:dir:`sourcecode` works as well. This
directive takes a language name as an argument. It can be `any lexer alias directive takes a language name as an argument. It can be `any lexer alias
supported by Pygments <https://pygments.org/docs/lexers/>`_. If it is not supported by Pygments <https://pygments.org/docs/lexers/>`_. If it is not
given, the setting of :rst:dir:`highlight` directive will be used. given, the setting of :rst:dir:`highlight` directive will be used. If not
If not set, :confval:`highlight_language` will be used. set, :confval:`highlight_language` will be used. To display a code example
*inline* within other text, rather than as a separate block, you can use the
:rst:role:`code` role instead.
.. versionchanged:: 2.0 .. versionchanged:: 2.0
The ``language`` argument becomes optional. The ``language`` argument becomes optional.

View File

@ -211,6 +211,12 @@ The following directives are provided for module and class contents:
.. versionadded:: 4.0 .. versionadded:: 4.0
.. rst::directive:option:: module
:type: text
Describe the location where the object is defined. The default value is
the module specified by :rst:dir:`py:currentmodule`.
.. rst:directive:: .. py:data:: name .. rst:directive:: .. py:data:: name
Describes global data in a module, including both variables and values used Describes global data in a module, including both variables and values used
@ -237,6 +243,12 @@ The following directives are provided for module and class contents:
.. versionadded:: 4.0 .. versionadded:: 4.0
.. rst::directive:option:: module
:type: text
Describe the location where the object is defined. The default value is
the module specified by :rst:dir:`py:currentmodule`.
.. rst:directive:: .. py:exception:: name .. rst:directive:: .. py:exception:: name
Describes an exception class. The signature can, but need not include Describes an exception class. The signature can, but need not include
@ -251,6 +263,12 @@ The following directives are provided for module and class contents:
.. versionadded:: 3.1 .. versionadded:: 3.1
.. rst::directive:option:: module
:type: text
Describe the location where the object is defined. The default value is
the module specified by :rst:dir:`py:currentmodule`.
.. rst:directive:: .. py:class:: name .. rst:directive:: .. py:class:: name
.. py:class:: name(parameters) .. py:class:: name(parameters)
@ -291,6 +309,12 @@ The following directives are provided for module and class contents:
.. versionadded:: 3.1 .. versionadded:: 3.1
.. rst::directive:option:: module
:type: text
Describe the location where the object is defined. The default value is
the module specified by :rst:dir:`py:currentmodule`.
.. rst:directive:: .. py:attribute:: name .. rst:directive:: .. py:attribute:: name
Describes an object data attribute. The description should include Describes an object data attribute. The description should include
@ -317,6 +341,12 @@ The following directives are provided for module and class contents:
.. versionadded:: 4.0 .. versionadded:: 4.0
.. rst::directive:option:: module
:type: text
Describe the location where the object is defined. The default value is
the module specified by :rst:dir:`py:currentmodule`.
.. rst:directive:: .. py:property:: name .. rst:directive:: .. py:property:: name
Describes an object property. Describes an object property.
@ -340,6 +370,12 @@ The following directives are provided for module and class contents:
.. rst:directive:option:: type: type of the property .. rst:directive:option:: type: type of the property
:type: text :type: text
.. rst::directive:option:: module
:type: text
Describe the location where the object is defined. The default value is
the module specified by :rst:dir:`py:currentmodule`.
.. rst:directive:: .. py:method:: name(parameters) .. rst:directive:: .. py:method:: name(parameters)
Describes an object method. The parameters should not include the ``self`` Describes an object method. The parameters should not include the ``self``
@ -385,6 +421,12 @@ The following directives are provided for module and class contents:
.. versionadded:: 3.1 .. versionadded:: 3.1
.. rst::directive:option:: module
:type: text
Describe the location where the object is defined. The default value is
the module specified by :rst:dir:`py:currentmodule`.
.. rst:directive:option:: property .. rst:directive:option:: property
:type: no value :type: no value

View File

@ -276,6 +276,34 @@ The following role creates a cross-reference to a term in a
If you use a term that's not explained in a glossary, you'll get a warning If you use a term that's not explained in a glossary, you'll get a warning
during build. during build.
Inline code highlighting
------------------------
.. rst:role:: code
An *inline* code example. When used directly, this role just displays the
text *without* syntax highlighting, as a literal.
.. code-block:: rst
By default, inline code such as :code:`1 + 2` just displays without
highlighting.
Unlike the :rst:dir:`code-block` directive, this role does not respect the
default language set by the :rst:dir:`highlight` directive.
To enable syntax highlighting, you must first use the ``role`` directive to
define a custom ``code`` role for a particular language:
.. code-block:: rst
.. role:: python(code)
:language: python
In Python, :python:`1 + 2` is equal to :python:`3`.
To display a multi-line code example, use the :rst:dir:`code-block` directive
instead.
Math Math
---- ----

View File

@ -15,8 +15,6 @@ module.exports = function(config) {
// list of files / patterns to load in the browser // list of files / patterns to load in the browser
files: [ files: [
'sphinx/themes/basic/static/underscore.js',
'sphinx/themes/basic/static/jquery.js',
'sphinx/themes/basic/static/doctools.js', 'sphinx/themes/basic/static/doctools.js',
'sphinx/themes/basic/static/searchtools.js', 'sphinx/themes/basic/static/searchtools.js',
'tests/js/*.js' 'tests/js/*.js'
@ -59,7 +57,7 @@ module.exports = function(config) {
// start these browsers // start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['Chrome', 'Firefox'], browsers: ["Firefox"],
// Continuous Integration mode // Continuous Integration mode

1637
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,9 +12,8 @@
}, },
"devDependencies": { "devDependencies": {
"jasmine-core": "^3.4.0", "jasmine-core": "^3.4.0",
"karma": "^6.3.14", "karma": "^6.3.16",
"karma-chrome-launcher": "^3.0.0", "karma-firefox-launcher": "^2.0.0",
"karma-firefox-launcher": "^1.1.0", "karma-jasmine": "^4.0.0"
"karma-jasmine": "^2.0.0"
} }
} }

View File

@ -1,5 +1,5 @@
[metadata] [metadata]
license_file = LICENSE license_files = LICENSE
[egg_info] [egg_info]
tag_build = .dev tag_build = .dev
@ -9,23 +9,6 @@ tag_date = true
release = egg_info -Db '' release = egg_info -Db ''
upload = upload --sign --identity=36580288 upload = upload --sign --identity=36580288
[build_sphinx]
warning-is-error = 1
[extract_messages]
mapping_file = babel.cfg
output_file = sphinx/locale/sphinx.pot
keywords = _ __ l_ lazy_gettext
[update_catalog]
input_file = sphinx/locale/sphinx.pot
domain = sphinx
output_dir = sphinx/locale/
[compile_catalog]
domain = sphinx
directory = sphinx/locale/
[flake8] [flake8]
max-line-length = 95 max-line-length = 95
ignore = E116,E241,E251,E741,W504,I101 ignore = E116,E241,E251,E741,W504,I101
@ -35,12 +18,6 @@ import-order-style = smarkets
per-file-ignores = per-file-ignores =
tests/*: E501 tests/*: E501
[flake8:local-plugins]
extension =
X101 = utils.checks:sphinx_has_header
paths =
.
[isort] [isort]
line_length = 95 line_length = 95

126
setup.py
View File

@ -1,12 +1,10 @@
import os
import sys import sys
from io import StringIO
from setuptools import find_packages, setup from setuptools import find_packages, setup
import sphinx import sphinx
with open('README.rst') as f: with open('README.rst', encoding='utf-8') as f:
long_desc = f.read() long_desc = f.read()
if sys.version_info < (3, 6): if sys.version_info < (3, 6):
@ -22,7 +20,7 @@ install_requires = [
'sphinxcontrib-qthelp', 'sphinxcontrib-qthelp',
'Jinja2>=2.3', 'Jinja2>=2.3',
'Pygments>=2.0', 'Pygments>=2.0',
'docutils>=0.14,<0.18', 'docutils>=0.14,<0.19',
'snowballstemmer>=1.1', 'snowballstemmer>=1.1',
'babel>=1.3', 'babel>=1.3',
'alabaster>=0.7,<0.8', 'alabaster>=0.7,<0.8',
@ -43,134 +41,19 @@ extras_require = {
'lint': [ 'lint': [
'flake8>=3.5.0', 'flake8>=3.5.0',
'isort', 'isort',
'mypy>=0.931', 'mypy>=0.950',
'docutils-stubs', 'docutils-stubs',
"types-typed-ast", "types-typed-ast",
"types-requests", "types-requests",
], ],
'test': [ 'test': [
'pytest', 'pytest>=4.6',
'pytest-cov',
'html5lib', 'html5lib',
"typed_ast; python_version < '3.8'", "typed_ast; python_version < '3.8'",
'cython', 'cython',
], ],
} }
# Provide a "compile_catalog" command that also creates the translated
# JavaScript files if Babel is available.
cmdclass = {}
class Tee:
def __init__(self, stream):
self.stream = stream
self.buffer = StringIO()
def write(self, s):
self.stream.write(s)
self.buffer.write(s)
def flush(self):
self.stream.flush()
try:
from json import dump
from babel.messages.frontend import compile_catalog
from babel.messages.pofile import read_po
except ImportError:
pass
else:
class compile_catalog_plusjs(compile_catalog):
"""
An extended command that writes all message strings that occur in
JavaScript files to a JavaScript file along with the .mo file.
Unfortunately, babel's setup command isn't built very extensible, so
most of the run() code is duplicated here.
"""
def run(self):
try:
sys.stderr = Tee(sys.stderr)
compile_catalog.run(self)
finally:
if sys.stderr.buffer.getvalue():
print("Compiling failed.")
sys.exit(1)
if isinstance(self.domain, list):
for domain in self.domain:
self._run_domain_js(domain)
else:
self._run_domain_js(self.domain)
def _run_domain_js(self, domain):
po_files = []
js_files = []
if not self.input_file:
if self.locale:
po_files.append((self.locale,
os.path.join(self.directory, self.locale,
'LC_MESSAGES',
domain + '.po')))
js_files.append(os.path.join(self.directory, self.locale,
'LC_MESSAGES',
domain + '.js'))
else:
for locale in os.listdir(self.directory):
po_file = os.path.join(self.directory, locale,
'LC_MESSAGES',
domain + '.po')
if os.path.exists(po_file):
po_files.append((locale, po_file))
js_files.append(os.path.join(self.directory, locale,
'LC_MESSAGES',
domain + '.js'))
else:
po_files.append((self.locale, self.input_file))
if self.output_file:
js_files.append(self.output_file)
else:
js_files.append(os.path.join(self.directory, self.locale,
'LC_MESSAGES',
domain + '.js'))
for js_file, (locale, po_file) in zip(js_files, po_files):
with open(po_file, encoding='utf8') as infile:
catalog = read_po(infile, locale)
if catalog.fuzzy and not self.use_fuzzy:
continue
self.log.info('writing JavaScript strings in catalog %r to %r',
po_file, js_file)
jscatalog = {}
for message in catalog:
if any(x[0].endswith(('.js', '.js_t', '.html'))
for x in message.locations):
msgid = message.id
if isinstance(msgid, (list, tuple)):
msgid = msgid[0]
jscatalog[msgid] = message.string
with open(js_file, 'wt', encoding='utf8') as outfile:
outfile.write('Documentation.addTranslations(')
dump({
'messages': jscatalog,
'plural_expr': catalog.plural_expr,
'locale': str(catalog.locale)
}, outfile, sort_keys=True, indent=4)
outfile.write(');')
cmdclass['compile_catalog'] = compile_catalog_plusjs
setup( setup(
name='Sphinx', name='Sphinx',
version=sphinx.__version__, version=sphinx.__version__,
@ -246,5 +129,4 @@ setup(
python_requires=">=3.6", python_requires=">=3.6",
install_requires=install_requires, install_requires=install_requires,
extras_require=extras_require, extras_require=extras_require,
cmdclass=cmdclass,
) )

View File

@ -1,12 +1,4 @@
""" """The Sphinx documentation toolchain."""
Sphinx
~~~~~~
The Sphinx documentation toolchain.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
# Keep this file executable as-is in Python 3! # Keep this file executable as-is in Python 3!
# (Otherwise getting the version out of it from setup.py is impossible.) # (Otherwise getting the version out of it from setup.py is impossible.)
@ -26,9 +18,11 @@ if 'PYTHONWARNINGS' not in os.environ:
# docutils.io using mode='rU' for open # docutils.io using mode='rU' for open
warnings.filterwarnings('ignore', "'U' mode is deprecated", warnings.filterwarnings('ignore', "'U' mode is deprecated",
DeprecationWarning, module='docutils.io') DeprecationWarning, module='docutils.io')
warnings.filterwarnings('ignore', 'The frontend.Option class .*',
DeprecationWarning, module='docutils.frontend')
__version__ = '4.5.0+' __version__ = '5.0.0+'
__released__ = '4.5.0' # used when Sphinx builds its own docs __released__ = '5.0.0' # used when Sphinx builds its own docs
#: Version info for better programmatic use. #: Version info for better programmatic use.
#: #:
@ -38,7 +32,7 @@ __released__ = '4.5.0' # used when Sphinx builds its own docs
#: #:
#: .. versionadded:: 1.2 #: .. versionadded:: 1.2
#: Before version 1.2, check the string ``sphinx.__version__``. #: Before version 1.2, check the string ``sphinx.__version__``.
version_info = (4, 5, 0, 'beta', 0) version_info = (5, 0, 0, 'final', 0)
package_dir = path.abspath(path.dirname(__file__)) package_dir = path.abspath(path.dirname(__file__))

View File

@ -1,12 +1,4 @@
""" """The Sphinx documentation toolchain."""
sphinx.__main__
~~~~~~~~~~~~~~~
The Sphinx documentation toolchain.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import sys import sys

View File

@ -1,15 +1,8 @@
""" """Additional docutils nodes."""
sphinx.addnodes
~~~~~~~~~~~~~~~
Additional docutils nodes.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import TYPE_CHECKING, Any, Dict, List, Sequence from typing import TYPE_CHECKING, Any, Dict, List, Sequence
import docutils
from docutils import nodes from docutils import nodes
from docutils.nodes import Element from docutils.nodes import Element
@ -36,7 +29,6 @@ class document(nodes.document):
def set_id(self, node: Element, msgnode: Element = None, def set_id(self, node: Element, msgnode: Element = None,
suggested_prefix: str = '') -> str: suggested_prefix: str = '') -> str:
from sphinx.util import docutils
if docutils.__version_info__ >= (0, 16): if docutils.__version_info__ >= (0, 16):
ret = super().set_id(node, msgnode, suggested_prefix) # type: ignore ret = super().set_id(node, msgnode, suggested_prefix) # type: ignore
else: else:
@ -535,8 +527,6 @@ class manpage(nodes.Inline, nodes.FixedTextElement):
def setup(app: "Sphinx") -> Dict[str, Any]: def setup(app: "Sphinx") -> Dict[str, Any]:
from sphinx.util import docutils # lazy import
app.add_node(toctree) app.add_node(toctree)
app.add_node(desc) app.add_node(desc)

View File

@ -1,13 +1,6 @@
""" """Sphinx application class and extensibility interface.
sphinx.application
~~~~~~~~~~~~~~~~~~
Sphinx application class and extensibility interface. Gracefully adapted from the TextPress system by Armin.
Gracefully adapted from the TextPress system by Armin.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
""" """
import os import os
@ -266,7 +259,7 @@ class Sphinx:
"""Load translated strings from the configured localedirs if enabled in """Load translated strings from the configured localedirs if enabled in
the configuration. the configuration.
""" """
if self.config.language is None: if self.config.language == 'en':
self.translator, has_translation = locale.init([], None) self.translator, has_translation = locale.init([], None)
else: else:
logger.info(bold(__('loading translations [%s]... ') % self.config.language), logger.info(bold(__('loading translations [%s]... ') % self.config.language),
@ -285,8 +278,7 @@ class Sphinx:
locale_dirs += [path.join(package_dir, 'locale')] locale_dirs += [path.join(package_dir, 'locale')]
self.translator, has_translation = locale.init(locale_dirs, self.config.language) self.translator, has_translation = locale.init(locale_dirs, self.config.language)
if has_translation or self.config.language == 'en': if has_translation:
# "en" never needs to be translated
logger.info(__('done')) logger.info(__('done'))
else: else:
logger.info(__('not available for built-in messages')) logger.info(__('not available for built-in messages'))

View File

@ -1,13 +1,6 @@
""" """Builder superclass for all builders."""
sphinx.builders
~~~~~~~~~~~~~~~
Builder superclass for all builders.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import codecs
import pickle import pickle
import time import time
from os import path from os import path
@ -22,9 +15,9 @@ from sphinx.environment import CONFIG_CHANGED_REASON, CONFIG_OK, BuildEnvironmen
from sphinx.environment.adapters.asset import ImageAdapter from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.errors import SphinxError from sphinx.errors import SphinxError
from sphinx.events import EventManager from sphinx.events import EventManager
from sphinx.io import read_doc
from sphinx.locale import __ from sphinx.locale import __
from sphinx.util import import_object, logging, progress_message, rst, status_iterator from sphinx.util import (UnicodeDecodeErrorHandler, get_filetype, import_object, logging,
progress_message, rst, status_iterator)
from sphinx.util.build_phase import BuildPhase from sphinx.util.build_phase import BuildPhase
from sphinx.util.console import bold # type: ignore from sphinx.util.console import bold # type: ignore
from sphinx.util.docutils import sphinx_domains from sphinx.util.docutils import sphinx_domains
@ -472,8 +465,21 @@ class Builder:
if path.isfile(docutilsconf): if path.isfile(docutilsconf):
self.env.note_dependency(docutilsconf) self.env.note_dependency(docutilsconf)
filename = self.env.doc2path(docname)
filetype = get_filetype(self.app.config.source_suffix, filename)
publisher = self.app.registry.get_publisher(self.app, filetype)
with sphinx_domains(self.env), rst.default_role(docname, self.config.default_role): with sphinx_domains(self.env), rst.default_role(docname, self.config.default_role):
doctree = read_doc(self.app, self.env, self.env.doc2path(docname)) # set up error_handler for the target document
codecs.register_error('sphinx', UnicodeDecodeErrorHandler(docname)) # type: ignore
publisher.set_source(source_path=filename)
publisher.publish()
doctree = publisher.document
# The settings object is reused by the Publisher for each document.
# Becuase we modify the settings object in ``write_doctree``, we
# need to ensure that each doctree has an independent copy.
doctree.settings = doctree.settings.copy()
# store time of reading, for outdated files detection # store time of reading, for outdated files detection
# (Some filesystems have coarse timestamp resolution; # (Some filesystems have coarse timestamp resolution;

View File

@ -1,12 +1,4 @@
""" """Base class of epub2/epub3 builders."""
sphinx.builders._epub_base
~~~~~~~~~~~~~~~~~~~~~~~~~~
Base class of epub2/epub3 builders.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import html import html
import os import os
@ -491,7 +483,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
metadata['copyright'] = html.escape(self.config.epub_copyright) metadata['copyright'] = html.escape(self.config.epub_copyright)
metadata['scheme'] = html.escape(self.config.epub_scheme) metadata['scheme'] = html.escape(self.config.epub_scheme)
metadata['id'] = html.escape(self.config.epub_identifier) metadata['id'] = html.escape(self.config.epub_identifier)
metadata['date'] = html.escape(format_date("%Y-%m-%d")) metadata['date'] = html.escape(format_date("%Y-%m-%d", language='en'))
metadata['manifest_items'] = [] metadata['manifest_items'] = []
metadata['spines'] = [] metadata['spines'] = []
metadata['guides'] = [] metadata['guides'] = []

View File

@ -1,12 +1,4 @@
""" """Changelog builder."""
sphinx.builders.changes
~~~~~~~~~~~~~~~~~~~~~~~
Changelog builder.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import html import html
from os import path from os import path

View File

@ -1,12 +1,4 @@
""" """Directory HTML builders."""
sphinx.builders.dirhtml
~~~~~~~~~~~~~~~~~~~~~~~
Directory HTML builders.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from os import path from os import path
from typing import Any, Dict from typing import Any, Dict

View File

@ -1,12 +1,4 @@
""" """Do syntax checks, but no writing."""
sphinx.builders.dummy
~~~~~~~~~~~~~~~~~~~~~
Do syntax checks, but no writing.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import Any, Dict, Set from typing import Any, Dict, Set

View File

@ -1,12 +1,6 @@
""" """Build epub3 files.
sphinx.builders.epub3
~~~~~~~~~~~~~~~~~~~~~
Build epub3 files. Originally derived from epub.py.
Originally derived from epub.py.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
""" """
import html import html
@ -94,7 +88,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
metadata['contributor'] = html.escape(self.config.epub_contributor) metadata['contributor'] = html.escape(self.config.epub_contributor)
metadata['page_progression_direction'] = PAGE_PROGRESSION_DIRECTIONS.get(writing_mode) metadata['page_progression_direction'] = PAGE_PROGRESSION_DIRECTIONS.get(writing_mode)
metadata['ibook_scroll_axis'] = IBOOK_SCROLL_AXIS.get(writing_mode) metadata['ibook_scroll_axis'] = IBOOK_SCROLL_AXIS.get(writing_mode)
metadata['date'] = html.escape(format_date("%Y-%m-%dT%H:%M:%SZ")) metadata['date'] = html.escape(format_date("%Y-%m-%dT%H:%M:%SZ", language='en'))
metadata['version'] = html.escape(self.config.version) metadata['version'] = html.escape(self.config.version)
metadata['epub_version'] = self.config.epub_version metadata['epub_version'] = self.config.epub_version
return metadata return metadata

View File

@ -1,12 +1,4 @@
""" """The MessageCatalogBuilder class."""
sphinx.builders.gettext
~~~~~~~~~~~~~~~~~~~~~~~
The MessageCatalogBuilder class.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from codecs import open from codecs import open
from collections import OrderedDict, defaultdict from collections import OrderedDict, defaultdict

View File

@ -1,25 +1,19 @@
""" """Several HTML builders."""
sphinx.builders.html
~~~~~~~~~~~~~~~~~~~~
Several HTML builders.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import html import html
import os import os
import posixpath import posixpath
import re import re
import sys import sys
import warnings
from datetime import datetime from datetime import datetime
from os import path from os import path
from typing import IO, Any, Dict, Iterable, Iterator, List, Set, Tuple, Type from typing import IO, Any, Dict, Iterable, Iterator, List, Optional, Set, Tuple, Type
from urllib.parse import quote from urllib.parse import quote
import docutils.readers.doctree
from docutils import nodes from docutils import nodes
from docutils.core import publish_parts from docutils.core import Publisher
from docutils.frontend import OptionParser from docutils.frontend import OptionParser
from docutils.io import DocTreeInput, StringOutput from docutils.io import DocTreeInput, StringOutput
from docutils.nodes import Node from docutils.nodes import Node
@ -30,6 +24,7 @@ from sphinx import version_info as sphinx_version
from sphinx.application import Sphinx from sphinx.application import Sphinx
from sphinx.builders import Builder from sphinx.builders import Builder
from sphinx.config import ENUM, Config from sphinx.config import ENUM, Config
from sphinx.deprecation import RemovedInSphinx70Warning, deprecated_alias
from sphinx.domains import Domain, Index, IndexEntry from sphinx.domains import Domain, Index, IndexEntry
from sphinx.environment.adapters.asset import ImageAdapter from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.environment.adapters.indexentries import IndexEntries from sphinx.environment.adapters.indexentries import IndexEntries
@ -40,7 +35,7 @@ from sphinx.locale import _, __
from sphinx.search import js_index from sphinx.search import js_index
from sphinx.theming import HTMLThemeFactory from sphinx.theming import HTMLThemeFactory
from sphinx.util import isurl, logging, md5, progress_message, status_iterator from sphinx.util import isurl, logging, md5, progress_message, status_iterator
from sphinx.util.docutils import is_html5_writer_available, new_document from sphinx.util.docutils import new_document
from sphinx.util.fileutil import copy_asset from sphinx.util.fileutil import copy_asset
from sphinx.util.i18n import format_date from sphinx.util.i18n import format_date
from sphinx.util.inventory import InventoryFile from sphinx.util.inventory import InventoryFile
@ -48,13 +43,7 @@ from sphinx.util.matching import DOTFILES, Matcher, patmatch
from sphinx.util.osutil import copyfile, ensuredir, os_path, relative_uri from sphinx.util.osutil import copyfile, ensuredir, os_path, relative_uri
from sphinx.util.tags import Tags from sphinx.util.tags import Tags
from sphinx.writers.html import HTMLTranslator, HTMLWriter from sphinx.writers.html import HTMLTranslator, HTMLWriter
from sphinx.writers.html5 import HTML5Translator
# HTML5 Writer is available or not
if is_html5_writer_available():
from sphinx.writers.html5 import HTML5Translator
html5_ready = True
else:
html5_ready = False
#: the filename for the inventory of objects #: the filename for the inventory of objects
INVENTORY_FILENAME = 'objects.inv' INVENTORY_FILENAME = 'objects.inv'
@ -76,6 +65,17 @@ def get_stable_hash(obj: Any) -> str:
return md5(str(obj).encode()).hexdigest() return md5(str(obj).encode()).hexdigest()
def convert_locale_to_language_tag(locale: Optional[str]) -> Optional[str]:
"""Convert a locale string to a language tag (ex. en_US -> en-US).
refs: BCP 47 (:rfc:`5646`)
"""
if locale:
return locale.replace('_', '-')
else:
return None
class Stylesheet(str): class Stylesheet(str):
"""A metadata of stylesheet. """A metadata of stylesheet.
@ -208,6 +208,19 @@ class StandaloneHTMLBuilder(Builder):
# JS files # JS files
self.script_files: List[JavaScript] = [] self.script_files: List[JavaScript] = []
# Cached Publisher for writing doctrees to HTML
reader = docutils.readers.doctree.Reader(parser_name='restructuredtext')
pub = Publisher(
reader=reader,
parser=reader.parser,
writer=HTMLWriter(self),
source_class=DocTreeInput,
destination=StringOutput(encoding='unicode'),
)
op = pub.setup_option_parser(output_encoding='unicode', traceback=True)
pub.settings = op.get_default_values()
self._publisher = pub
def init(self) -> None: def init(self) -> None:
self.build_info = self.create_build_info() self.build_info = self.create_build_info()
# basename of images directory # basename of images directory
@ -315,8 +328,11 @@ class StandaloneHTMLBuilder(Builder):
self.script_files = [] self.script_files = []
self.add_js_file('documentation_options.js', id="documentation_options", self.add_js_file('documentation_options.js', id="documentation_options",
data_url_root='', priority=200) data_url_root='', priority=200)
# Remove frameworks and compatability module below in Sphinx 6.0
# xref RemovedInSphinx60Warning
self.add_js_file('jquery.js', priority=200) self.add_js_file('jquery.js', priority=200)
self.add_js_file('underscore.js', priority=200) self.add_js_file('underscore.js', priority=200)
self.add_js_file('_sphinx_javascript_frameworks_compat.js', priority=200)
self.add_js_file('doctools.js', priority=200) self.add_js_file('doctools.js', priority=200)
for filename, attrs in self.app.registry.js_files: for filename, attrs in self.app.registry.js_files:
@ -326,7 +342,7 @@ class StandaloneHTMLBuilder(Builder):
attrs.setdefault('priority', 800) # User's JSs are loaded after extensions' attrs.setdefault('priority', 800) # User's JSs are loaded after extensions'
self.add_js_file(filename, **attrs) self.add_js_file(filename, **attrs)
if self.config.language and self._get_translations_js(): if self._get_translations_js():
self.add_js_file('translations.js') self.add_js_file('translations.js')
def add_js_file(self, filename: str, **kwargs: Any) -> None: def add_js_file(self, filename: str, **kwargs: Any) -> None:
@ -337,7 +353,7 @@ class StandaloneHTMLBuilder(Builder):
@property @property
def default_translator_class(self) -> Type[nodes.NodeVisitor]: # type: ignore def default_translator_class(self) -> Type[nodes.NodeVisitor]: # type: ignore
if not html5_ready or self.config.html4_writer: if self.config.html4_writer:
return HTMLTranslator return HTMLTranslator
else: else:
return HTML5Translator return HTML5Translator
@ -364,7 +380,7 @@ class StandaloneHTMLBuilder(Builder):
def get_outdated_docs(self) -> Iterator[str]: def get_outdated_docs(self) -> Iterator[str]:
try: try:
with open(path.join(self.outdir, '.buildinfo')) as fp: with open(path.join(self.outdir, '.buildinfo'), encoding="utf-8") as fp:
buildinfo = BuildInfo.load(fp) buildinfo = BuildInfo.load(fp)
if self.build_info != buildinfo: if self.build_info != buildinfo:
@ -415,15 +431,12 @@ class StandaloneHTMLBuilder(Builder):
"""Utility: Render a lone doctree node.""" """Utility: Render a lone doctree node."""
if node is None: if node is None:
return {'fragment': ''} return {'fragment': ''}
doc = new_document('<partial node>') doc = new_document('<partial node>')
doc.append(node) doc.append(node)
self._publisher.set_source(doc)
writer = HTMLWriter(self) self._publisher.publish()
return publish_parts(reader_name='doctree', return self._publisher.writer.parts
writer=writer,
source_class=DocTreeInput,
settings_overrides={'output_encoding': 'unicode'},
source=doc)
def prepare_writing(self, docnames: Set[str]) -> None: def prepare_writing(self, docnames: Set[str]) -> None:
# create the search indexer # create the search indexer
@ -431,18 +444,20 @@ class StandaloneHTMLBuilder(Builder):
if self.search: if self.search:
from sphinx.search import IndexBuilder from sphinx.search import IndexBuilder
lang = self.config.html_search_language or self.config.language lang = self.config.html_search_language or self.config.language
if not lang:
lang = 'en'
self.indexer = IndexBuilder(self.env, lang, self.indexer = IndexBuilder(self.env, lang,
self.config.html_search_options, self.config.html_search_options,
self.config.html_search_scorer) self.config.html_search_scorer)
self.load_indexer(docnames) self.load_indexer(docnames)
self.docwriter = HTMLWriter(self) self.docwriter = HTMLWriter(self)
self.docsettings: Any = OptionParser( with warnings.catch_warnings():
defaults=self.env.settings, warnings.filterwarnings('ignore', category=DeprecationWarning)
components=(self.docwriter,), # DeprecationWarning: The frontend.OptionParser class will be replaced
read_config_files=True).get_default_values() # by a subclass of argparse.ArgumentParser in Docutils 0.21 or later.
self.docsettings: Any = OptionParser(
defaults=self.env.settings,
components=(self.docwriter,),
read_config_files=True).get_default_values()
self.docsettings.compact_lists = bool(self.config.html_compact_lists) self.docsettings.compact_lists = bool(self.config.html_compact_lists)
# determine the additional indices to include # determine the additional indices to include
@ -517,7 +532,7 @@ class StandaloneHTMLBuilder(Builder):
'file_suffix': self.out_suffix, 'file_suffix': self.out_suffix,
'link_suffix': self.link_suffix, 'link_suffix': self.link_suffix,
'script_files': self.script_files, 'script_files': self.script_files,
'language': self.config.language, 'language': convert_locale_to_language_tag(self.config.language),
'css_files': self.css_files, 'css_files': self.css_files,
'sphinx_version': __display_version__, 'sphinx_version': __display_version__,
'sphinx_version_tuple': sphinx_version, 'sphinx_version_tuple': sphinx_version,
@ -527,7 +542,7 @@ class StandaloneHTMLBuilder(Builder):
'parents': [], 'parents': [],
'logo': logo, 'logo': logo,
'favicon': favicon, 'favicon': favicon,
'html5_doctype': html5_ready and not self.config.html4_writer, 'html5_doctype': not self.config.html4_writer,
} }
if self.theme: if self.theme:
self.globalcontext.update( self.globalcontext.update(
@ -759,19 +774,20 @@ class StandaloneHTMLBuilder(Builder):
def create_pygments_style_file(self) -> None: def create_pygments_style_file(self) -> None:
"""create a style file for pygments.""" """create a style file for pygments."""
with open(path.join(self.outdir, '_static', 'pygments.css'), 'w') as f: with open(path.join(self.outdir, '_static', 'pygments.css'), 'w',
encoding="utf-8") as f:
f.write(self.highlighter.get_stylesheet()) f.write(self.highlighter.get_stylesheet())
if self.dark_highlighter: if self.dark_highlighter:
with open(path.join(self.outdir, '_static', 'pygments_dark.css'), 'w') as f: with open(path.join(self.outdir, '_static', 'pygments_dark.css'), 'w',
encoding="utf-8") as f:
f.write(self.dark_highlighter.get_stylesheet()) f.write(self.dark_highlighter.get_stylesheet())
def copy_translation_js(self) -> None: def copy_translation_js(self) -> None:
"""Copy a JavaScript file for translations.""" """Copy a JavaScript file for translations."""
if self.config.language is not None: jsfile = self._get_translations_js()
jsfile = self._get_translations_js() if jsfile:
if jsfile: copyfile(jsfile, path.join(self.outdir, '_static', 'translations.js'))
copyfile(jsfile, path.join(self.outdir, '_static', 'translations.js'))
def copy_stemmer_js(self) -> None: def copy_stemmer_js(self) -> None:
"""Copy a JavaScript file for stemmer.""" """Copy a JavaScript file for stemmer."""
@ -850,7 +866,7 @@ class StandaloneHTMLBuilder(Builder):
def write_buildinfo(self) -> None: def write_buildinfo(self) -> None:
try: try:
with open(path.join(self.outdir, '.buildinfo'), 'w') as fp: with open(path.join(self.outdir, '.buildinfo'), 'w', encoding="utf-8") as fp:
self.build_info.dump(fp) self.build_info.dump(fp)
except OSError as exc: except OSError as exc:
logger.warning(__('Failed to write build info file: %r'), exc) logger.warning(__('Failed to write build info file: %r'), exc)
@ -1305,6 +1321,12 @@ import sphinxcontrib.serializinghtml # NOQA
import sphinx.builders.dirhtml # NOQA import sphinx.builders.dirhtml # NOQA
import sphinx.builders.singlehtml # NOQA import sphinx.builders.singlehtml # NOQA
deprecated_alias('sphinx.builders.html',
{
'html5_ready': True,
},
RemovedInSphinx70Warning)
def setup(app: Sphinx) -> Dict[str, Any]: def setup(app: Sphinx) -> Dict[str, Any]:
# builders # builders

View File

@ -1,12 +1,4 @@
""" """Transforms for HTML builder."""
sphinx.builders.html.transforms
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Transforms for HTML builder.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import re import re
from typing import Any, Dict, List from typing import Any, Dict, List

View File

@ -1,12 +1,4 @@
""" """LaTeX builder."""
sphinx.builders.latex
~~~~~~~~~~~~~~~~~~~~~
LaTeX builder.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import os import os
import warnings import warnings
@ -24,7 +16,6 @@ from sphinx.builders.latex.constants import ADDITIONAL_SETTINGS, DEFAULT_SETTING
from sphinx.builders.latex.theming import Theme, ThemeFactory from sphinx.builders.latex.theming import Theme, ThemeFactory
from sphinx.builders.latex.util import ExtBabel from sphinx.builders.latex.util import ExtBabel
from sphinx.config import ENUM, Config from sphinx.config import ENUM, Config
from sphinx.deprecation import RemovedInSphinx50Warning
from sphinx.environment.adapters.asset import ImageAdapter from sphinx.environment.adapters.asset import ImageAdapter
from sphinx.errors import NoUri, SphinxError from sphinx.errors import NoUri, SphinxError
from sphinx.locale import _, __ from sphinx.locale import _, __
@ -172,9 +163,8 @@ class LaTeXBuilder(Builder):
self.context.update(ADDITIONAL_SETTINGS.get(self.config.latex_engine, {})) self.context.update(ADDITIONAL_SETTINGS.get(self.config.latex_engine, {}))
# Add special settings for (latex_engine, language_code) # Add special settings for (latex_engine, language_code)
if self.config.language: key = (self.config.latex_engine, self.config.language[:2])
key = (self.config.latex_engine, self.config.language[:2]) self.context.update(ADDITIONAL_SETTINGS.get(key, {}))
self.context.update(ADDITIONAL_SETTINGS.get(key, {}))
# Apply user settings to context # Apply user settings to context
self.context.update(self.config.latex_elements) self.context.update(self.config.latex_elements)
@ -205,7 +195,7 @@ class LaTeXBuilder(Builder):
def init_babel(self) -> None: def init_babel(self) -> None:
self.babel = ExtBabel(self.config.language, not self.context['babel']) self.babel = ExtBabel(self.config.language, not self.context['babel'])
if self.config.language and not self.babel.is_supported_language(): if not self.babel.is_supported_language():
# emit warning if specified language is invalid # emit warning if specified language is invalid
# (only emitting, nothing changed to processing) # (only emitting, nothing changed to processing)
logger.warning(__('no Babel option known for language %r'), logger.warning(__('no Babel option known for language %r'),
@ -234,12 +224,11 @@ class LaTeXBuilder(Builder):
self.context['classoptions'] += ',' + self.babel.get_language() self.context['classoptions'] += ',' + self.babel.get_language()
# this branch is not taken for xelatex/lualatex if default settings # this branch is not taken for xelatex/lualatex if default settings
self.context['multilingual'] = self.context['babel'] self.context['multilingual'] = self.context['babel']
if self.config.language: self.context['shorthandoff'] = SHORTHANDOFF
self.context['shorthandoff'] = SHORTHANDOFF
# Times fonts don't work with Cyrillic languages # Times fonts don't work with Cyrillic languages
if self.babel.uses_cyrillic() and 'fontpkg' not in self.config.latex_elements: if self.babel.uses_cyrillic() and 'fontpkg' not in self.config.latex_elements:
self.context['fontpkg'] = '' self.context['fontpkg'] = ''
elif self.context['polyglossia']: elif self.context['polyglossia']:
self.context['classoptions'] += ',' + self.babel.get_language() self.context['classoptions'] += ',' + self.babel.get_language()
options = self.babel.get_mainlanguage_options() options = self.babel.get_mainlanguage_options()
@ -253,7 +242,7 @@ class LaTeXBuilder(Builder):
def write_stylesheet(self) -> None: def write_stylesheet(self) -> None:
highlighter = highlighting.PygmentsBridge('latex', self.config.pygments_style) highlighter = highlighting.PygmentsBridge('latex', self.config.pygments_style)
stylesheet = path.join(self.outdir, 'sphinxhighlight.sty') stylesheet = path.join(self.outdir, 'sphinxhighlight.sty')
with open(stylesheet, 'w') as f: with open(stylesheet, 'w', encoding="utf-8") as f:
f.write('\\NeedsTeXFormat{LaTeX2e}[1995/12/01]\n') f.write('\\NeedsTeXFormat{LaTeX2e}[1995/12/01]\n')
f.write('\\ProvidesPackage{sphinxhighlight}' f.write('\\ProvidesPackage{sphinxhighlight}'
'[2016/05/29 stylesheet for highlighting with pygments]\n') '[2016/05/29 stylesheet for highlighting with pygments]\n')
@ -262,10 +251,14 @@ class LaTeXBuilder(Builder):
def write(self, *ignored: Any) -> None: def write(self, *ignored: Any) -> None:
docwriter = LaTeXWriter(self) docwriter = LaTeXWriter(self)
docsettings: Any = OptionParser( with warnings.catch_warnings():
defaults=self.env.settings, warnings.filterwarnings('ignore', category=DeprecationWarning)
components=(docwriter,), # DeprecationWarning: The frontend.OptionParser class will be replaced
read_config_files=True).get_default_values() # by a subclass of argparse.ArgumentParser in Docutils 0.21 or later.
docsettings: Any = OptionParser(
defaults=self.env.settings,
components=(docwriter,),
read_config_files=True).get_default_values()
self.init_document_data() self.init_document_data()
self.write_stylesheet() self.write_stylesheet()
@ -359,9 +352,9 @@ class LaTeXBuilder(Builder):
newnodes: List[Node] = [nodes.emphasis(sectname, sectname)] newnodes: List[Node] = [nodes.emphasis(sectname, sectname)]
for subdir, title in self.titles: for subdir, title in self.titles:
if docname.startswith(subdir): if docname.startswith(subdir):
newnodes.append(nodes.Text(_(' (in '), _(' (in '))) newnodes.append(nodes.Text(_(' (in ')))
newnodes.append(nodes.emphasis(title, title)) newnodes.append(nodes.emphasis(title, title))
newnodes.append(nodes.Text(')', ')')) newnodes.append(nodes.Text(')'))
break break
else: else:
pass pass
@ -382,14 +375,10 @@ class LaTeXBuilder(Builder):
# configure usage of xindy (impacts Makefile and latexmkrc) # configure usage of xindy (impacts Makefile and latexmkrc)
# FIXME: convert this rather to a confval with suitable default # FIXME: convert this rather to a confval with suitable default
# according to language ? but would require extra documentation # according to language ? but would require extra documentation
if self.config.language: xindy_lang_option = XINDY_LANG_OPTIONS.get(self.config.language[:2],
xindy_lang_option = \ '-L general -C utf8 ')
XINDY_LANG_OPTIONS.get(self.config.language[:2], xindy_cyrillic = self.config.language[:2] in XINDY_CYRILLIC_SCRIPTS
'-L general -C utf8 ')
xindy_cyrillic = self.config.language[:2] in XINDY_CYRILLIC_SCRIPTS
else:
xindy_lang_option = '-L english -C utf8 '
xindy_cyrillic = False
context = { context = {
'latex_engine': self.config.latex_engine, 'latex_engine': self.config.latex_engine,
'xindy_use': self.config.latex_use_xindy, 'xindy_use': self.config.latex_use_xindy,
@ -449,18 +438,6 @@ class LaTeXBuilder(Builder):
filename = path.join(package_dir, 'templates', 'latex', 'sphinxmessages.sty_t') filename = path.join(package_dir, 'templates', 'latex', 'sphinxmessages.sty_t')
copy_asset_file(filename, self.outdir, context=context, renderer=LaTeXRenderer()) copy_asset_file(filename, self.outdir, context=context, renderer=LaTeXRenderer())
@property
def usepackages(self) -> List[Tuple[str, str]]:
warnings.warn('LaTeXBuilder.usepackages is deprecated.',
RemovedInSphinx50Warning, stacklevel=2)
return self.app.registry.latex_packages
@property
def usepackages_after_hyperref(self) -> List[Tuple[str, str]]:
warnings.warn('LaTeXBuilder.usepackages_after_hyperref is deprecated.',
RemovedInSphinx50Warning, stacklevel=2)
return self.app.registry.latex_packages_after_hyperref
def validate_config_values(app: Sphinx, config: Config) -> None: def validate_config_values(app: Sphinx, config: Config) -> None:
for key in list(config.latex_elements): for key in list(config.latex_elements):
@ -488,7 +465,7 @@ def default_latex_engine(config: Config) -> str:
""" Better default latex_engine settings for specific languages. """ """ Better default latex_engine settings for specific languages. """
if config.language == 'ja': if config.language == 'ja':
return 'uplatex' return 'uplatex'
elif (config.language or '').startswith('zh'): elif config.language.startswith('zh'):
return 'xelatex' return 'xelatex'
elif config.language == 'el': elif config.language == 'el':
return 'xelatex' return 'xelatex'

View File

@ -1,12 +1,4 @@
""" """consntants for LaTeX builder."""
sphinx.builders.latex.constants
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
consntants for LaTeX builder.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import Any, Dict from typing import Any, Dict

View File

@ -1,12 +1,4 @@
""" """Additional nodes for LaTeX writer."""
sphinx.builders.latex.nodes
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Additional nodes for LaTeX writer.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from docutils import nodes from docutils import nodes

View File

@ -1,12 +1,4 @@
""" """Theming support for LaTeX builder."""
sphinx.builders.latex.theming
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Theming support for LaTeX builder.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import configparser import configparser
from os import path from os import path
@ -81,7 +73,7 @@ class UserTheme(Theme):
def __init__(self, name: str, filename: str) -> None: def __init__(self, name: str, filename: str) -> None:
super().__init__(name) super().__init__(name)
self.config = configparser.RawConfigParser() self.config = configparser.RawConfigParser()
self.config.read(path.join(filename)) self.config.read(path.join(filename), encoding='utf-8')
for key in self.REQUIRED_CONFIG_KEYS: for key in self.REQUIRED_CONFIG_KEYS:
try: try:

View File

@ -1,12 +1,4 @@
""" """Transforms for LaTeX builder."""
sphinx.builders.latex.transforms
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Transforms for LaTeX builder.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import Any, Dict, List, Set, Tuple, cast from typing import Any, Dict, List, Set, Tuple, cast

View File

@ -1,12 +1,4 @@
""" """Utilities for LaTeX builder."""
sphinx.builders.latex.util
~~~~~~~~~~~~~~~~~~~~~~~~~~
Utilities for LaTeX builder.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import Optional from typing import Optional
@ -20,7 +12,7 @@ class ExtBabel(Babel):
self.language_code = language_code self.language_code = language_code
self.use_polyglossia = use_polyglossia self.use_polyglossia = use_polyglossia
self.supported = True self.supported = True
super().__init__(language_code or '') super().__init__(language_code)
def uses_cyrillic(self) -> bool: def uses_cyrillic(self) -> bool:
return self.language in self.cyrillic_languages return self.language in self.cyrillic_languages

View File

@ -1,37 +1,25 @@
""" """The CheckExternalLinksBuilder class."""
sphinx.builders.linkcheck
~~~~~~~~~~~~~~~~~~~~~~~~~
The CheckExternalLinksBuilder class.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import json import json
import re import re
import socket import socket
import time import time
import warnings
from datetime import datetime, timezone from datetime import datetime, timezone
from email.utils import parsedate_to_datetime from email.utils import parsedate_to_datetime
from html.parser import HTMLParser from html.parser import HTMLParser
from os import path from os import path
from queue import PriorityQueue, Queue from queue import PriorityQueue, Queue
from threading import Thread from threading import Thread
from typing import (Any, Dict, Generator, List, NamedTuple, Optional, Pattern, Set, Tuple, from typing import Any, Dict, Generator, List, NamedTuple, Optional, Tuple, Union, cast
Union, cast)
from urllib.parse import unquote, urlparse, urlunparse from urllib.parse import unquote, urlparse, urlunparse
from docutils import nodes from docutils import nodes
from docutils.nodes import Element
from requests import Response from requests import Response
from requests.exceptions import ConnectionError, HTTPError, TooManyRedirects from requests.exceptions import ConnectionError, HTTPError, TooManyRedirects
from sphinx.application import Sphinx from sphinx.application import Sphinx
from sphinx.builders.dummy import DummyBuilder from sphinx.builders.dummy import DummyBuilder
from sphinx.config import Config from sphinx.config import Config
from sphinx.deprecation import RemovedInSphinx50Warning
from sphinx.environment import BuildEnvironment from sphinx.environment import BuildEnvironment
from sphinx.locale import __ from sphinx.locale import __
from sphinx.transforms.post_transforms import SphinxPostTransform from sphinx.transforms.post_transforms import SphinxPostTransform
@ -80,16 +68,6 @@ QUEUE_POLL_SECS = 1
DEFAULT_DELAY = 60.0 DEFAULT_DELAY = 60.0
def node_line_or_0(node: Element) -> int:
"""
PriorityQueue items must be comparable. The line number is part of the
tuple used by the PriorityQueue, keep an homogeneous type for comparison.
"""
warnings.warn('node_line_or_0() is deprecated.',
RemovedInSphinx50Warning, stacklevel=2)
return get_node_line(node) or 0
class AnchorCheckParser(HTMLParser): class AnchorCheckParser(HTMLParser):
"""Specialized HTML parser that looks for a specific anchor.""" """Specialized HTML parser that looks for a specific anchor."""
@ -133,114 +111,11 @@ class CheckExternalLinksBuilder(DummyBuilder):
'%(outdir)s/output.txt') '%(outdir)s/output.txt')
def init(self) -> None: def init(self) -> None:
self.broken_hyperlinks = 0
self.hyperlinks: Dict[str, Hyperlink] = {} self.hyperlinks: Dict[str, Hyperlink] = {}
self._good: Set[str] = set()
self._broken: Dict[str, str] = {}
self._redirected: Dict[str, Tuple[str, int]] = {}
# set a timeout for non-responding servers # set a timeout for non-responding servers
socket.setdefaulttimeout(5.0) socket.setdefaulttimeout(5.0)
# create queues and worker threads
self._wqueue: PriorityQueue[CheckRequestType] = PriorityQueue()
self._rqueue: Queue[CheckResult] = Queue()
@property
def anchors_ignore(self) -> List[Pattern]:
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "anchors_ignore"),
RemovedInSphinx50Warning,
stacklevel=2,
)
return [re.compile(x) for x in self.config.linkcheck_anchors_ignore]
@property
def auth(self) -> List[Tuple[Pattern, Any]]:
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "auth"),
RemovedInSphinx50Warning,
stacklevel=2,
)
return [(re.compile(pattern), auth_info) for pattern, auth_info
in self.config.linkcheck_auth]
@property
def to_ignore(self) -> List[Pattern]:
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "to_ignore"),
RemovedInSphinx50Warning,
stacklevel=2,
)
return [re.compile(x) for x in self.config.linkcheck_ignore]
@property
def good(self) -> Set[str]:
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "good"),
RemovedInSphinx50Warning,
stacklevel=2,
)
return self._good
@property
def broken(self) -> Dict[str, str]:
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "broken"),
RemovedInSphinx50Warning,
stacklevel=2,
)
return self._broken
@property
def redirected(self) -> Dict[str, Tuple[str, int]]:
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "redirected"),
RemovedInSphinx50Warning,
stacklevel=2,
)
return self._redirected
def check_thread(self) -> None:
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "check_thread"),
RemovedInSphinx50Warning,
stacklevel=2,
)
# do nothing.
def limit_rate(self, response: Response) -> Optional[float]:
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "limit_rate"),
RemovedInSphinx50Warning,
stacklevel=2,
)
worker = HyperlinkAvailabilityCheckWorker(self.env, self.config,
None, None, {})
return worker.limit_rate(response)
def rqueue(self, response: Response) -> Queue:
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "rqueue"),
RemovedInSphinx50Warning,
stacklevel=2,
)
return self._rqueue
def workers(self, response: Response) -> List[Thread]:
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "workers"),
RemovedInSphinx50Warning,
stacklevel=2,
)
return []
def wqueue(self, response: Response) -> Queue:
warnings.warn(
"%s.%s is deprecated." % (self.__class__.__name__, "wqueue"),
RemovedInSphinx50Warning,
stacklevel=2,
)
return self._wqueue
def process_result(self, result: CheckResult) -> None: def process_result(self, result: CheckResult) -> None:
filename = self.env.doc2path(result.docname, None) filename = self.env.doc2path(result.docname, None)
@ -273,6 +148,7 @@ class CheckExternalLinksBuilder(DummyBuilder):
logger.info(red('broken ') + result.uri + red(' - ' + result.message)) logger.info(red('broken ') + result.uri + red(' - ' + result.message))
self.write_entry('broken', result.docname, filename, result.lineno, self.write_entry('broken', result.docname, filename, result.lineno,
result.uri + ': ' + result.message) result.uri + ': ' + result.message)
self.broken_hyperlinks += 1
elif result.status == 'redirected': elif result.status == 'redirected':
try: try:
text, color = { text, color = {
@ -305,44 +181,36 @@ class CheckExternalLinksBuilder(DummyBuilder):
self.json_outfile.write('\n') self.json_outfile.write('\n')
def finish(self) -> None: def finish(self) -> None:
checker = HyperlinkAvailabilityChecker(self.env, self.config, self) checker = HyperlinkAvailabilityChecker(self.env, self.config)
logger.info('') logger.info('')
with open(path.join(self.outdir, 'output.txt'), 'w') as self.txt_outfile,\ output_text = path.join(self.outdir, 'output.txt')
open(path.join(self.outdir, 'output.json'), 'w') as self.json_outfile: output_json = path.join(self.outdir, 'output.json')
with open(output_text, 'w', encoding="utf-8") as self.txt_outfile,\
open(output_json, 'w', encoding="utf-8") as self.json_outfile:
for result in checker.check(self.hyperlinks): for result in checker.check(self.hyperlinks):
self.process_result(result) self.process_result(result)
if self._broken: if self.broken_hyperlinks:
self.app.statuscode = 1 self.app.statuscode = 1
class HyperlinkAvailabilityChecker: class HyperlinkAvailabilityChecker:
def __init__(self, env: BuildEnvironment, config: Config, def __init__(self, env: BuildEnvironment, config: Config) -> None:
builder: CheckExternalLinksBuilder = None) -> None:
# Warning: builder argument will be removed in the sphinx-5.0.
# Don't use it from extensions.
# tag: RemovedInSphinx50Warning
self.builder = builder
self.config = config self.config = config
self.env = env self.env = env
self.rate_limits: Dict[str, RateLimit] = {} self.rate_limits: Dict[str, RateLimit] = {}
self.rqueue: Queue = Queue()
self.workers: List[Thread] = [] self.workers: List[Thread] = []
self.wqueue: PriorityQueue = PriorityQueue()
self.to_ignore = [re.compile(x) for x in self.config.linkcheck_ignore] self.to_ignore = [re.compile(x) for x in self.config.linkcheck_ignore]
if builder:
self.rqueue = builder._rqueue
self.wqueue = builder._wqueue
else:
self.rqueue = Queue()
self.wqueue = PriorityQueue()
def invoke_threads(self) -> None: def invoke_threads(self) -> None:
for _i in range(self.config.linkcheck_workers): for _i in range(self.config.linkcheck_workers):
thread = HyperlinkAvailabilityCheckWorker(self.env, self.config, thread = HyperlinkAvailabilityCheckWorker(self.env, self.config,
self.rqueue, self.wqueue, self.rqueue, self.wqueue,
self.rate_limits, self.builder) self.rate_limits)
thread.start() thread.start()
self.workers.append(thread) self.workers.append(thread)
@ -378,11 +246,7 @@ class HyperlinkAvailabilityCheckWorker(Thread):
"""A worker class for checking the availability of hyperlinks.""" """A worker class for checking the availability of hyperlinks."""
def __init__(self, env: BuildEnvironment, config: Config, rqueue: Queue, def __init__(self, env: BuildEnvironment, config: Config, rqueue: Queue,
wqueue: Queue, rate_limits: Dict[str, RateLimit], wqueue: Queue, rate_limits: Dict[str, RateLimit]) -> None:
builder: CheckExternalLinksBuilder = None) -> None:
# Warning: builder argument will be removed in the sphinx-5.0.
# Don't use it from extensions.
# tag: RemovedInSphinx50Warning
self.config = config self.config = config
self.env = env self.env = env
self.rate_limits = rate_limits self.rate_limits = rate_limits
@ -396,17 +260,6 @@ class HyperlinkAvailabilityCheckWorker(Thread):
self.auth = [(re.compile(pattern), auth_info) for pattern, auth_info self.auth = [(re.compile(pattern), auth_info) for pattern, auth_info
in self.config.linkcheck_auth] in self.config.linkcheck_auth]
if builder:
# if given, fill the result of checks as cache
self._good = builder._good
self._broken = builder._broken
self._redirected = builder._redirected
else:
# only for compatibility. Will be removed in Sphinx-5.0
self._good = set()
self._broken = {}
self._redirected = {}
super().__init__(daemon=True) super().__init__(daemon=True)
def run(self) -> None: def run(self) -> None:
@ -554,14 +407,7 @@ class HyperlinkAvailabilityCheckWorker(Thread):
if path.exists(path.join(srcdir, uri)): if path.exists(path.join(srcdir, uri)):
return 'working', '', 0 return 'working', '', 0
else: else:
self._broken[uri] = ''
return 'broken', '', 0 return 'broken', '', 0
elif uri in self._good:
return 'working', 'old', 0
elif uri in self._broken:
return 'broken', self._broken[uri], 0
elif uri in self._redirected:
return 'redirected', self._redirected[uri][0], self._redirected[uri][1]
# need to actually check the URI # need to actually check the URI
for _ in range(self.config.linkcheck_retries): for _ in range(self.config.linkcheck_retries):
@ -569,13 +415,6 @@ class HyperlinkAvailabilityCheckWorker(Thread):
if status != "broken": if status != "broken":
break break
if status == "working":
self._good.add(uri)
elif status == "broken":
self._broken[uri] = info
elif status == "redirected":
self._redirected[uri] = (info, code)
return (status, info, code) return (status, info, code)
while True: while True:

View File

@ -1,13 +1,6 @@
""" """Manual pages builder."""
sphinx.builders.manpage
~~~~~~~~~~~~~~~~~~~~~~~
Manual pages builder.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import warnings
from os import path from os import path
from typing import Any, Dict, List, Set, Tuple, Union from typing import Any, Dict, List, Set, Tuple, Union
@ -18,7 +11,6 @@ from sphinx import addnodes
from sphinx.application import Sphinx from sphinx.application import Sphinx
from sphinx.builders import Builder from sphinx.builders import Builder
from sphinx.config import Config from sphinx.config import Config
from sphinx.errors import NoUri
from sphinx.locale import __ from sphinx.locale import __
from sphinx.util import logging, progress_message from sphinx.util import logging, progress_message
from sphinx.util.console import darkgreen # type: ignore from sphinx.util.console import darkgreen # type: ignore
@ -49,17 +41,19 @@ class ManualPageBuilder(Builder):
return 'all manpages' # for now return 'all manpages' # for now
def get_target_uri(self, docname: str, typ: str = None) -> str: def get_target_uri(self, docname: str, typ: str = None) -> str:
if typ == 'token': return ''
return ''
raise NoUri(docname, typ)
@progress_message(__('writing')) @progress_message(__('writing'))
def write(self, *ignored: Any) -> None: def write(self, *ignored: Any) -> None:
docwriter = ManualPageWriter(self) docwriter = ManualPageWriter(self)
docsettings: Any = OptionParser( with warnings.catch_warnings():
defaults=self.env.settings, warnings.filterwarnings('ignore', category=DeprecationWarning)
components=(docwriter,), # DeprecationWarning: The frontend.OptionParser class will be replaced
read_config_files=True).get_default_values() # by a subclass of argparse.ArgumentParser in Docutils 0.21 or later.
docsettings: Any = OptionParser(
defaults=self.env.settings,
components=(docwriter,),
read_config_files=True).get_default_values()
for info in self.config.man_pages: for info in self.config.man_pages:
docname, name, description, authors, section = info docname, name, description, authors, section = info

View File

@ -1,12 +1,4 @@
""" """Single HTML builders."""
sphinx.builders.singlehtml
~~~~~~~~~~~~~~~~~~~~~~~~~~
Single HTML builders.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from os import path from os import path
from typing import Any, Dict, List, Tuple, Union from typing import Any, Dict, List, Tuple, Union

View File

@ -1,14 +1,7 @@
""" """Texinfo builder."""
sphinx.builders.texinfo
~~~~~~~~~~~~~~~~~~~~~~~
Texinfo builder.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import os import os
import warnings
from os import path from os import path
from typing import Any, Dict, Iterable, List, Tuple, Union from typing import Any, Dict, Iterable, List, Tuple, Union
@ -109,10 +102,14 @@ class TexinfoBuilder(Builder):
with progress_message(__("writing")): with progress_message(__("writing")):
self.post_process_images(doctree) self.post_process_images(doctree)
docwriter = TexinfoWriter(self) docwriter = TexinfoWriter(self)
settings: Any = OptionParser( with warnings.catch_warnings():
defaults=self.env.settings, warnings.filterwarnings('ignore', category=DeprecationWarning)
components=(docwriter,), # DeprecationWarning: The frontend.OptionParser class will be replaced
read_config_files=True).get_default_values() # by a subclass of argparse.ArgumentParser in Docutils 0.21 or later.
settings: Any = OptionParser(
defaults=self.env.settings,
components=(docwriter,),
read_config_files=True).get_default_values()
settings.author = author settings.author = author
settings.title = title settings.title = title
settings.texinfo_filename = targetname[:-5] + '.info' settings.texinfo_filename = targetname[:-5] + '.info'
@ -158,9 +155,9 @@ class TexinfoBuilder(Builder):
newnodes: List[Node] = [nodes.emphasis(sectname, sectname)] newnodes: List[Node] = [nodes.emphasis(sectname, sectname)]
for subdir, title in self.titles: for subdir, title in self.titles:
if docname.startswith(subdir): if docname.startswith(subdir):
newnodes.append(nodes.Text(_(' (in '), _(' (in '))) newnodes.append(nodes.Text(_(' (in ')))
newnodes.append(nodes.emphasis(title, title)) newnodes.append(nodes.emphasis(title, title))
newnodes.append(nodes.Text(')', ')')) newnodes.append(nodes.Text(')'))
break break
else: else:
pass pass

View File

@ -1,12 +1,4 @@
""" """Plain-text Sphinx builder."""
sphinx.builders.text
~~~~~~~~~~~~~~~~~~~~
Plain-text Sphinx builder.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from os import path from os import path
from typing import Any, Dict, Iterator, Set, Tuple from typing import Any, Dict, Iterator, Set, Tuple

View File

@ -1,12 +1,4 @@
""" """Docutils-native XML and pseudo-XML builders."""
sphinx.builders.xml
~~~~~~~~~~~~~~~~~~~
Docutils-native XML and pseudo-XML builders.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from os import path from os import path
from typing import Any, Dict, Iterator, Set, Type, Union from typing import Any, Dict, Iterator, Set, Type, Union

View File

@ -1,9 +1 @@
""" """Modules for command line executables."""
sphinx.cmd
~~~~~~~~~~
Modules for command line executables.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""

View File

@ -1,12 +1,4 @@
""" """Build documentation from a provided source."""
sphinx.cmd.build
~~~~~~~~~~~~~~~~
Build documentation from a provided source.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import argparse import argparse
import bdb import bdb
@ -244,7 +236,7 @@ def build_main(argv: List[str] = sys.argv[1:]) -> int:
try: try:
warnfile = abspath(args.warnfile) warnfile = abspath(args.warnfile)
ensuredir(path.dirname(warnfile)) ensuredir(path.dirname(warnfile))
warnfp = open(args.warnfile, 'w') warnfp = open(args.warnfile, 'w', encoding="utf-8")
except Exception as exc: except Exception as exc:
parser.error(__('cannot open warning file %r: %s') % ( parser.error(__('cannot open warning file %r: %s') % (
args.warnfile, exc)) args.warnfile, exc))

View File

@ -1,17 +1,10 @@
""" """sphinx-build -M command-line handling.
sphinx.cmd.make_mode
~~~~~~~~~~~~~~~~~~~~
sphinx-build -M command-line handling. This replaces the old, platform-dependent and once-generated content
of Makefile / make.bat.
This replaces the old, platform-dependent and once-generated content This is in its own module so that importing it is fast. It should not
of Makefile / make.bat. import the main Sphinx modules (like sphinx.applications, sphinx.builders).
This is in its own module so that importing it is fast. It should not
import the main Sphinx modules (like sphinx.applications, sphinx.builders).
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
""" """
import os import os

View File

@ -1,12 +1,4 @@
""" """Quickly setup documentation source to work with Sphinx."""
sphinx.cmd.quickstart
~~~~~~~~~~~~~~~~~~~~~
Quickly setup documentation source to work with Sphinx.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import argparse import argparse
import locale import locale
@ -375,7 +367,7 @@ def generate(d: Dict, overwrite: bool = True, silent: bool = False, templatedir:
conf_path = os.path.join(templatedir, 'conf.py_t') if templatedir else None conf_path = os.path.join(templatedir, 'conf.py_t') if templatedir else None
if not conf_path or not path.isfile(conf_path): if not conf_path or not path.isfile(conf_path):
conf_path = os.path.join(package_dir, 'templates', 'quickstart', 'conf.py_t') conf_path = os.path.join(package_dir, 'templates', 'quickstart', 'conf.py_t')
with open(conf_path) as f: with open(conf_path, encoding="utf-8") as f:
conf_text = f.read() conf_text = f.read()
write_file(path.join(srcdir, 'conf.py'), template.render_string(conf_text, d)) write_file(path.join(srcdir, 'conf.py'), template.render_string(conf_text, d))

View File

@ -1,12 +1,4 @@
""" """Build configuration file handling."""
sphinx.config
~~~~~~~~~~~~~
Build configuration file handling.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import re import re
import traceback import traceback
@ -100,7 +92,7 @@ class Config:
# the real default is locale-dependent # the real default is locale-dependent
'today_fmt': (None, 'env', [str]), 'today_fmt': (None, 'env', [str]),
'language': (None, 'env', [str]), 'language': ('en', 'env', [str]),
'locale_dirs': (['locales'], 'env', []), 'locale_dirs': (['locales'], 'env', []),
'figure_language_filename': ('{root}.{language}{ext}', 'env', [str]), 'figure_language_filename': ('{root}.{language}{ext}', 'env', [str]),
'gettext_allow_fuzzy_translations': (False, 'gettext', []), 'gettext_allow_fuzzy_translations': (False, 'gettext', []),
@ -413,7 +405,7 @@ def correct_copyright_year(app: "Sphinx", config: Config) -> None:
if getenv('SOURCE_DATE_EPOCH') is not None: if getenv('SOURCE_DATE_EPOCH') is not None:
for k in ('copyright', 'epub_copyright'): for k in ('copyright', 'epub_copyright'):
if k in config: if k in config:
replace = r'\g<1>%s' % format_date('%Y') replace = r'\g<1>%s' % format_date('%Y', language='en')
config[k] = copyright_year_re.sub(replace, config[k]) config[k] = copyright_year_re.sub(replace, config[k])

View File

@ -1,12 +1,4 @@
""" """Sphinx deprecation classes and utilities."""
sphinx.deprecation
~~~~~~~~~~~~~~~~~~
Sphinx deprecation classes and utilities.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import sys import sys
import warnings import warnings
@ -14,15 +6,15 @@ from importlib import import_module
from typing import Any, Dict, Type from typing import Any, Dict, Type
class RemovedInSphinx50Warning(DeprecationWarning): class RemovedInSphinx60Warning(DeprecationWarning):
pass pass
class RemovedInSphinx60Warning(PendingDeprecationWarning): class RemovedInSphinx70Warning(PendingDeprecationWarning):
pass pass
RemovedInNextVersionWarning = RemovedInSphinx50Warning RemovedInNextVersionWarning = RemovedInSphinx60Warning
def deprecated_alias(modname: str, objects: Dict[str, object], def deprecated_alias(modname: str, objects: Dict[str, object],

View File

@ -1,12 +1,4 @@
""" """Handlers for additional ReST directives."""
sphinx.directives
~~~~~~~~~~~~~~~~~
Handlers for additional ReST directives.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import re import re
from typing import TYPE_CHECKING, Any, Dict, Generic, List, Tuple, TypeVar, cast from typing import TYPE_CHECKING, Any, Dict, Generic, List, Tuple, TypeVar, cast
@ -17,7 +9,6 @@ from docutils.parsers.rst import directives, roles
from sphinx import addnodes from sphinx import addnodes
from sphinx.addnodes import desc_signature from sphinx.addnodes import desc_signature
from sphinx.deprecation import RemovedInSphinx50Warning, deprecated_alias
from sphinx.util import docutils from sphinx.util import docutils
from sphinx.util.docfields import DocFieldTransformer, Field, TypedField from sphinx.util.docfields import DocFieldTransformer, Field, TypedField
from sphinx.util.docutils import SphinxDirective from sphinx.util.docutils import SphinxDirective
@ -266,16 +257,6 @@ class DefaultDomain(SphinxDirective):
return [] return []
deprecated_alias('sphinx.directives',
{
'DescDirective': ObjectDescription,
},
RemovedInSphinx50Warning,
{
'DescDirective': 'sphinx.directives.ObjectDescription',
})
def setup(app: "Sphinx") -> Dict[str, Any]: def setup(app: "Sphinx") -> Dict[str, Any]:
app.add_config_value("strip_signature_backslash", False, 'env') app.add_config_value("strip_signature_backslash", False, 'env')
directives.register_directive('default-role', DefaultRole) directives.register_directive('default-role', DefaultRole)

View File

@ -1,11 +1,3 @@
"""
sphinx.directives.code
~~~~~~~~~~~~~~~~~~~~~~
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import sys import sys
import textwrap import textwrap
from difflib import unified_diff from difflib import unified_diff
@ -232,9 +224,9 @@ class LiteralIncludeReader:
self.start_filter, self.start_filter,
self.end_filter, self.end_filter,
self.lines_filter, self.lines_filter,
self.dedent_filter,
self.prepend_filter, self.prepend_filter,
self.append_filter, self.append_filter]
self.dedent_filter]
lines = self.read_file(self.filename, location=location) lines = self.read_file(self.filename, location=location)
for func in filters: for func in filters:
lines = func(lines, location=location) lines = func(lines, location=location)

View File

@ -1,11 +1,3 @@
"""
sphinx.directives.other
~~~~~~~~~~~~~~~~~~~~~~~
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import re import re
from typing import TYPE_CHECKING, Any, Dict, List, cast from typing import TYPE_CHECKING, Any, Dict, List, cast
@ -180,7 +172,7 @@ class Author(SphinxDirective):
text = _('Code author: ') text = _('Code author: ')
else: else:
text = _('Author: ') text = _('Author: ')
emph += nodes.Text(text, text) emph += nodes.Text(text)
inodes, messages = self.state.inline_text(self.arguments[0], self.lineno) inodes, messages = self.state.inline_text(self.arguments[0], self.lineno)
emph.extend(inodes) emph.extend(inodes)

View File

@ -1,11 +1,3 @@
"""
sphinx.directives.patches
~~~~~~~~~~~~~~~~~~~~~~~~~
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import os import os
import warnings import warnings
from os import path from os import path

View File

@ -1,12 +1,7 @@
""" """Support for domains.
sphinx.domains
~~~~~~~~~~~~~~
Support for domains, which are groupings of description directives Domains are groupings of description directives
and roles describing e.g. constructs of one programming language. and roles describing e.g. constructs of one programming language.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
""" """
import copy import copy

View File

@ -1,12 +1,4 @@
""" """The C language domain."""
sphinx.domains.c
~~~~~~~~~~~~~~~~
The C language domain.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import re import re
from typing import (Any, Callable, Dict, Generator, Iterator, List, Optional, Tuple, TypeVar, from typing import (Any, Callable, Dict, Generator, Iterator, List, Optional, Tuple, TypeVar,
@ -20,7 +12,7 @@ from sphinx import addnodes
from sphinx.addnodes import pending_xref from sphinx.addnodes import pending_xref
from sphinx.application import Sphinx from sphinx.application import Sphinx
from sphinx.builders import Builder from sphinx.builders import Builder
from sphinx.deprecation import RemovedInSphinx50Warning from sphinx.deprecation import RemovedInSphinx60Warning
from sphinx.directives import ObjectDescription from sphinx.directives import ObjectDescription
from sphinx.domains import Domain, ObjType from sphinx.domains import Domain, ObjType
from sphinx.environment import BuildEnvironment from sphinx.environment import BuildEnvironment
@ -29,8 +21,8 @@ from sphinx.roles import SphinxRole, XRefRole
from sphinx.transforms import SphinxTransform from sphinx.transforms import SphinxTransform
from sphinx.transforms.post_transforms import ReferencesResolver from sphinx.transforms.post_transforms import ReferencesResolver
from sphinx.util import logging from sphinx.util import logging
from sphinx.util.cfamily import (ASTAttribute, ASTBaseBase, ASTBaseParenExprList, BaseParser, from sphinx.util.cfamily import (ASTAttributeList, ASTBaseBase, ASTBaseParenExprList,
DefinitionError, NoOldIdError, StringifyTransform, BaseParser, DefinitionError, NoOldIdError, StringifyTransform,
UnsupportedMultiCharacterCharLiteral, anon_identifier_re, UnsupportedMultiCharacterCharLiteral, anon_identifier_re,
binary_literal_re, char_literal_re, float_literal_re, binary_literal_re, char_literal_re, float_literal_re,
float_literal_suffix_re, hex_literal_re, identifier_re, float_literal_suffix_re, hex_literal_re, identifier_re,
@ -695,7 +687,7 @@ class ASTFunctionParameter(ASTBase):
class ASTParameters(ASTBase): class ASTParameters(ASTBase):
def __init__(self, args: List[ASTFunctionParameter], attrs: List[ASTAttribute]) -> None: def __init__(self, args: List[ASTFunctionParameter], attrs: ASTAttributeList) -> None:
self.args = args self.args = args
self.attrs = attrs self.attrs = attrs
@ -713,9 +705,9 @@ class ASTParameters(ASTBase):
first = False first = False
res.append(str(a)) res.append(str(a))
res.append(')') res.append(')')
for attr in self.attrs: if len(self.attrs) != 0:
res.append(' ') res.append(' ')
res.append(transform(attr)) res.append(transform(self.attrs))
return ''.join(res) return ''.join(res)
def describe_signature(self, signode: TextElement, mode: str, def describe_signature(self, signode: TextElement, mode: str,
@ -740,14 +732,14 @@ class ASTParameters(ASTBase):
arg.describe_signature(signode, 'markType', env, symbol=symbol) arg.describe_signature(signode, 'markType', env, symbol=symbol)
signode += addnodes.desc_sig_punctuation(')', ')') signode += addnodes.desc_sig_punctuation(')', ')')
for attr in self.attrs: if len(self.attrs) != 0:
signode += addnodes.desc_sig_space() signode += addnodes.desc_sig_space()
attr.describe_signature(signode) self.attrs.describe_signature(signode)
class ASTDeclSpecsSimple(ASTBaseBase): class ASTDeclSpecsSimple(ASTBaseBase):
def __init__(self, storage: str, threadLocal: str, inline: bool, def __init__(self, storage: str, threadLocal: str, inline: bool,
restrict: bool, volatile: bool, const: bool, attrs: List[Any]) -> None: restrict: bool, volatile: bool, const: bool, attrs: ASTAttributeList) -> None:
self.storage = storage self.storage = storage
self.threadLocal = threadLocal self.threadLocal = threadLocal
self.inline = inline self.inline = inline
@ -769,7 +761,8 @@ class ASTDeclSpecsSimple(ASTBaseBase):
def _stringify(self, transform: StringifyTransform) -> str: def _stringify(self, transform: StringifyTransform) -> str:
res: List[str] = [] res: List[str] = []
res.extend(transform(attr) for attr in self.attrs) if len(self.attrs) != 0:
res.append(transform(self.attrs))
if self.storage: if self.storage:
res.append(self.storage) res.append(self.storage)
if self.threadLocal: if self.threadLocal:
@ -786,14 +779,15 @@ class ASTDeclSpecsSimple(ASTBaseBase):
def describe_signature(self, modifiers: List[Node]) -> None: def describe_signature(self, modifiers: List[Node]) -> None:
def _add(modifiers: List[Node], text: str) -> None: def _add(modifiers: List[Node], text: str) -> None:
if len(modifiers) > 0: if len(modifiers) != 0:
modifiers.append(addnodes.desc_sig_space()) modifiers.append(addnodes.desc_sig_space())
modifiers.append(addnodes.desc_sig_keyword(text, text)) modifiers.append(addnodes.desc_sig_keyword(text, text))
for attr in self.attrs: if len(modifiers) != 0 and len(self.attrs) != 0:
if len(modifiers) > 0: modifiers.append(addnodes.desc_sig_space())
modifiers.append(addnodes.desc_sig_space()) tempNode = nodes.TextElement()
modifiers.append(attr.describe_signature(modifiers)) self.attrs.describe_signature(tempNode)
modifiers.extend(tempNode.children)
if self.storage: if self.storage:
_add(modifiers, self.storage) _add(modifiers, self.storage)
if self.threadLocal: if self.threadLocal:
@ -1010,7 +1004,7 @@ class ASTDeclaratorNameBitField(ASTDeclarator):
class ASTDeclaratorPtr(ASTDeclarator): class ASTDeclaratorPtr(ASTDeclarator):
def __init__(self, next: ASTDeclarator, restrict: bool, volatile: bool, const: bool, def __init__(self, next: ASTDeclarator, restrict: bool, volatile: bool, const: bool,
attrs: Any) -> None: attrs: ASTAttributeList) -> None:
assert next assert next
self.next = next self.next = next
self.restrict = restrict self.restrict = restrict
@ -1033,9 +1027,8 @@ class ASTDeclaratorPtr(ASTDeclarator):
def _stringify(self, transform: StringifyTransform) -> str: def _stringify(self, transform: StringifyTransform) -> str:
res = ['*'] res = ['*']
for a in self.attrs: res.append(transform(self.attrs))
res.append(transform(a)) if len(self.attrs) != 0 and (self.restrict or self.volatile or self.const):
if len(self.attrs) > 0 and (self.restrict or self.volatile or self.const):
res.append(' ') res.append(' ')
if self.restrict: if self.restrict:
res.append('restrict') res.append('restrict')
@ -1057,9 +1050,8 @@ class ASTDeclaratorPtr(ASTDeclarator):
env: "BuildEnvironment", symbol: "Symbol") -> None: env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode) verify_description_mode(mode)
signode += addnodes.desc_sig_punctuation('*', '*') signode += addnodes.desc_sig_punctuation('*', '*')
for a in self.attrs: self.attrs.describe_signature(signode)
a.describe_signature(signode) if len(self.attrs) != 0 and (self.restrict or self.volatile or self.const):
if len(self.attrs) > 0 and (self.restrict or self.volatile or self.const):
signode += addnodes.desc_sig_space() signode += addnodes.desc_sig_space()
def _add_anno(signode: TextElement, text: str) -> None: def _add_anno(signode: TextElement, text: str) -> None:
@ -1382,9 +1374,11 @@ class ASTEnum(ASTBase):
class ASTEnumerator(ASTBase): class ASTEnumerator(ASTBase):
def __init__(self, name: ASTNestedName, init: ASTInitializer) -> None: def __init__(self, name: ASTNestedName, init: Optional[ASTInitializer],
attrs: ASTAttributeList) -> None:
self.name = name self.name = name
self.init = init self.init = init
self.attrs = attrs
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str: def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
return symbol.get_full_nested_name().get_id(version) return symbol.get_full_nested_name().get_id(version)
@ -1392,6 +1386,9 @@ class ASTEnumerator(ASTBase):
def _stringify(self, transform: StringifyTransform) -> str: def _stringify(self, transform: StringifyTransform) -> str:
res = [] res = []
res.append(transform(self.name)) res.append(transform(self.name))
if len(self.attrs) != 0:
res.append(' ')
res.append(transform(self.attrs))
if self.init: if self.init:
res.append(transform(self.init)) res.append(transform(self.init))
return ''.join(res) return ''.join(res)
@ -1400,6 +1397,9 @@ class ASTEnumerator(ASTBase):
env: "BuildEnvironment", symbol: "Symbol") -> None: env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode) verify_description_mode(mode)
self.name.describe_signature(signode, mode, env, symbol) self.name.describe_signature(signode, mode, env, symbol)
if len(self.attrs) != 0:
signode += addnodes.desc_sig_space()
self.attrs.describe_signature(signode)
if self.init: if self.init:
self.init.describe_signature(signode, 'markType', env, symbol) self.init.describe_signature(signode, 'markType', env, symbol)
@ -2649,13 +2649,7 @@ class DefinitionParser(BaseParser):
'Expecting "," or ")" in parameters, ' 'Expecting "," or ")" in parameters, '
'got "%s".' % self.current_char) 'got "%s".' % self.current_char)
attrs = [] attrs = self._parse_attribute_list()
while True:
attr = self._parse_attribute()
if attr is None:
break
attrs.append(attr)
return ASTParameters(args, attrs) return ASTParameters(args, attrs)
def _parse_decl_specs_simple(self, outer: str, typed: bool) -> ASTDeclSpecsSimple: def _parse_decl_specs_simple(self, outer: str, typed: bool) -> ASTDeclSpecsSimple:
@ -2714,7 +2708,7 @@ class DefinitionParser(BaseParser):
continue continue
break break
return ASTDeclSpecsSimple(storage, threadLocal, inline, return ASTDeclSpecsSimple(storage, threadLocal, inline,
restrict, volatile, const, attrs) restrict, volatile, const, ASTAttributeList(attrs))
def _parse_decl_specs(self, outer: str, typed: bool = True) -> ASTDeclSpecs: def _parse_decl_specs(self, outer: str, typed: bool = True) -> ASTDeclSpecs:
if outer: if outer:
@ -2846,7 +2840,7 @@ class DefinitionParser(BaseParser):
next = self._parse_declarator(named, paramMode, typed) next = self._parse_declarator(named, paramMode, typed)
return ASTDeclaratorPtr(next=next, return ASTDeclaratorPtr(next=next,
restrict=restrict, volatile=volatile, const=const, restrict=restrict, volatile=volatile, const=const,
attrs=attrs) attrs=ASTAttributeList(attrs))
if typed and self.current_char == '(': # note: peeking, not skipping if typed and self.current_char == '(': # note: peeking, not skipping
# maybe this is the beginning of params, try that first, # maybe this is the beginning of params, try that first,
# otherwise assume it's noptr->declarator > ( ptr-declarator ) # otherwise assume it's noptr->declarator > ( ptr-declarator )
@ -3041,6 +3035,7 @@ class DefinitionParser(BaseParser):
def _parse_enumerator(self) -> ASTEnumerator: def _parse_enumerator(self) -> ASTEnumerator:
name = self._parse_nested_name() name = self._parse_nested_name()
attrs = self._parse_attribute_list()
self.skip_ws() self.skip_ws()
init = None init = None
if self.skip_string('='): if self.skip_string('='):
@ -3051,7 +3046,7 @@ class DefinitionParser(BaseParser):
initVal = self._parse_expression_fallback([], parser) initVal = self._parse_expression_fallback([], parser)
init = ASTInitializer(initVal) init = ASTInitializer(initVal)
return ASTEnumerator(name, init) return ASTEnumerator(name, init, attrs)
def parse_pre_v3_type_definition(self) -> ASTDeclaration: def parse_pre_v3_type_definition(self) -> ASTDeclaration:
self.skip_ws() self.skip_ws()
@ -3276,7 +3271,7 @@ class CObject(ObjectDescription[ASTDeclaration]):
msg = "{}: Pre-v3 C type directive '.. c:type:: {}' converted to " \ msg = "{}: Pre-v3 C type directive '.. c:type:: {}' converted to " \
"'.. c:{}:: {}'." \ "'.. c:{}:: {}'." \
"\nThe original parsing error was:\n{}" "\nThe original parsing error was:\n{}"
msg = msg.format(RemovedInSphinx50Warning.__name__, msg = msg.format(RemovedInSphinx60Warning.__name__,
sig, ast.objectType, ast, eOrig) sig, ast.objectType, ast, eOrig)
logger.warning(msg, location=signode) logger.warning(msg, location=signode)
except DefinitionError as e: except DefinitionError as e:
@ -3709,7 +3704,7 @@ class CXRefRole(XRefRole):
if self.env.config['c_warn_on_allowed_pre_v3']: if self.env.config['c_warn_on_allowed_pre_v3']:
msg = "{}: Pre-v3 C type role ':c:type:`{}`' converted to ':c:expr:`{}`'." msg = "{}: Pre-v3 C type role ':c:type:`{}`' converted to ':c:expr:`{}`'."
msg += "\nThe original parsing error was:\n{}" msg += "\nThe original parsing error was:\n{}"
msg = msg.format(RemovedInSphinx50Warning.__name__, text, text, eOrig) msg = msg.format(RemovedInSphinx60Warning.__name__, text, text, eOrig)
logger.warning(msg, location=self.get_location()) logger.warning(msg, location=self.get_location())
return [signode], [] return [signode], []

View File

@ -1,12 +1,4 @@
""" """The changeset domain."""
sphinx.domains.changeset
~~~~~~~~~~~~~~~~~~~~~~~~
The changeset domain.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import TYPE_CHECKING, Any, Dict, List, NamedTuple, cast from typing import TYPE_CHECKING, Any, Dict, List, NamedTuple, cast

View File

@ -1,12 +1,4 @@
""" """The citation domain."""
sphinx.domains.citation
~~~~~~~~~~~~~~~~~~~~~~~
The citation domain.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple, cast from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Tuple, cast

View File

@ -1,12 +1,4 @@
""" """The C++ language domain."""
sphinx.domains.cpp
~~~~~~~~~~~~~~~~~~
The C++ language domain.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import re import re
from typing import (Any, Callable, Dict, Generator, Iterator, List, Optional, Tuple, TypeVar, from typing import (Any, Callable, Dict, Generator, Iterator, List, Optional, Tuple, TypeVar,
@ -29,8 +21,8 @@ from sphinx.roles import SphinxRole, XRefRole
from sphinx.transforms import SphinxTransform from sphinx.transforms import SphinxTransform
from sphinx.transforms.post_transforms import ReferencesResolver from sphinx.transforms.post_transforms import ReferencesResolver
from sphinx.util import logging from sphinx.util import logging
from sphinx.util.cfamily import (ASTAttribute, ASTBaseBase, ASTBaseParenExprList, BaseParser, from sphinx.util.cfamily import (ASTAttributeList, ASTBaseBase, ASTBaseParenExprList,
DefinitionError, NoOldIdError, StringifyTransform, BaseParser, DefinitionError, NoOldIdError, StringifyTransform,
UnsupportedMultiCharacterCharLiteral, anon_identifier_re, UnsupportedMultiCharacterCharLiteral, anon_identifier_re,
binary_literal_re, char_literal_re, float_literal_re, binary_literal_re, char_literal_re, float_literal_re,
float_literal_suffix_re, hex_literal_re, identifier_re, float_literal_suffix_re, hex_literal_re, identifier_re,
@ -267,7 +259,8 @@ T = TypeVar('T')
class_object: class_object:
goal: a class declaration, but with specification of a base class goal: a class declaration, but with specification of a base class
grammar: grammar:
nested-name "final"[opt] (":" base-specifier-list)[opt] attribute-specifier-seq[opt]
nested-name "final"[opt] (":" base-specifier-list)[opt]
base-specifier-list -> base-specifier-list ->
base-specifier "..."[opt] base-specifier "..."[opt]
| base-specifier-list, base-specifier "..."[opt] | base-specifier-list, base-specifier "..."[opt]
@ -281,7 +274,8 @@ T = TypeVar('T')
goal: an unscoped enum or a scoped enum, optionally with the underlying goal: an unscoped enum or a scoped enum, optionally with the underlying
type specified type specified
grammar: grammar:
("class" | "struct")[opt] visibility[opt] nested-name (":" type)[opt] ("class" | "struct")[opt] visibility[opt]
attribute-specifier-seq[opt] nested-name (":" type)[opt]
enumerator_object: enumerator_object:
goal: an element in a scoped or unscoped enum. The name should be goal: an element in a scoped or unscoped enum. The name should be
injected according to the scopedness. injected according to the scopedness.
@ -535,7 +529,8 @@ _id_operator_v2 = {
'->': 'pt', '->': 'pt',
'()': 'cl', '()': 'cl',
'[]': 'ix', '[]': 'ix',
'.*': 'ds' # this one is not overloadable, but we need it for expressions '.*': 'ds', # this one is not overloadable, but we need it for expressions
'?': 'qu',
} }
_id_operator_unary_v2 = { _id_operator_unary_v2 = {
'++': 'pp_', '++': 'pp_',
@ -1524,6 +1519,44 @@ class ASTBinOpExpr(ASTExpression):
self.exprs[i].describe_signature(signode, mode, env, symbol) self.exprs[i].describe_signature(signode, mode, env, symbol)
class ASTConditionalExpr(ASTExpression):
def __init__(self, ifExpr: ASTExpression, thenExpr: ASTExpression,
elseExpr: ASTExpression):
self.ifExpr = ifExpr
self.thenExpr = thenExpr
self.elseExpr = elseExpr
def _stringify(self, transform: StringifyTransform) -> str:
res = []
res.append(transform(self.ifExpr))
res.append(' ? ')
res.append(transform(self.thenExpr))
res.append(' : ')
res.append(transform(self.elseExpr))
return ''.join(res)
def get_id(self, version: int) -> str:
assert version >= 2
res = []
res.append(_id_operator_v2['?'])
res.append(self.ifExpr.get_id(version))
res.append(self.thenExpr.get_id(version))
res.append(self.elseExpr.get_id(version))
return ''.join(res)
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
self.ifExpr.describe_signature(signode, mode, env, symbol)
signode += addnodes.desc_sig_space()
signode += addnodes.desc_sig_operator('?', '?')
signode += addnodes.desc_sig_space()
self.thenExpr.describe_signature(signode, mode, env, symbol)
signode += addnodes.desc_sig_space()
signode += addnodes.desc_sig_operator(':', ':')
signode += addnodes.desc_sig_space()
self.elseExpr.describe_signature(signode, mode, env, symbol)
class ASTBracedInitList(ASTBase): class ASTBracedInitList(ASTBase):
def __init__(self, exprs: List[Union[ASTExpression, "ASTBracedInitList"]], def __init__(self, exprs: List[Union[ASTExpression, "ASTBracedInitList"]],
trailingComma: bool) -> None: trailingComma: bool) -> None:
@ -1556,42 +1589,39 @@ class ASTBracedInitList(ASTBase):
class ASTAssignmentExpr(ASTExpression): class ASTAssignmentExpr(ASTExpression):
def __init__(self, exprs: List[Union[ASTExpression, ASTBracedInitList]], ops: List[str]): def __init__(self, leftExpr: ASTExpression, op: str,
assert len(exprs) > 0 rightExpr: Union[ASTExpression, ASTBracedInitList]):
assert len(exprs) == len(ops) + 1 self.leftExpr = leftExpr
self.exprs = exprs self.op = op
self.ops = ops self.rightExpr = rightExpr
def _stringify(self, transform: StringifyTransform) -> str: def _stringify(self, transform: StringifyTransform) -> str:
res = [] res = []
res.append(transform(self.exprs[0])) res.append(transform(self.leftExpr))
for i in range(1, len(self.exprs)): res.append(' ')
res.append(' ') res.append(self.op)
res.append(self.ops[i - 1]) res.append(' ')
res.append(' ') res.append(transform(self.rightExpr))
res.append(transform(self.exprs[i]))
return ''.join(res) return ''.join(res)
def get_id(self, version: int) -> str: def get_id(self, version: int) -> str:
# we end up generating the ID from left to right, instead of right to left
res = [] res = []
for i in range(len(self.ops)): res.append(_id_operator_v2[self.op])
res.append(_id_operator_v2[self.ops[i]]) res.append(self.leftExpr.get_id(version))
res.append(self.exprs[i].get_id(version)) res.append(self.rightExpr.get_id(version))
res.append(self.exprs[-1].get_id(version))
return ''.join(res) return ''.join(res)
def describe_signature(self, signode: TextElement, mode: str, def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None: env: "BuildEnvironment", symbol: "Symbol") -> None:
self.exprs[0].describe_signature(signode, mode, env, symbol) self.leftExpr.describe_signature(signode, mode, env, symbol)
for i in range(1, len(self.exprs)): signode += addnodes.desc_sig_space()
signode += addnodes.desc_sig_space() if ord(self.op[0]) >= ord('a') and ord(self.op[0]) <= ord('z'):
op = self.ops[i - 1] signode += addnodes.desc_sig_keyword(self.op, self.op)
if ord(op[0]) >= ord('a') and ord(op[0]) <= ord('z'): else:
signode += addnodes.desc_sig_keyword(op, op) signode += addnodes.desc_sig_operator(self.op, self.op)
else: signode += addnodes.desc_sig_space()
signode += addnodes.desc_sig_operator(op, op) self.rightExpr.describe_signature(signode, mode, env, symbol)
signode += addnodes.desc_sig_space()
self.exprs[i].describe_signature(signode, mode, env, symbol)
class ASTCommaExpr(ASTExpression): class ASTCommaExpr(ASTExpression):
@ -2018,7 +2048,7 @@ class ASTParametersQualifiers(ASTBase):
def __init__(self, args: List[ASTFunctionParameter], volatile: bool, const: bool, def __init__(self, args: List[ASTFunctionParameter], volatile: bool, const: bool,
refQual: Optional[str], exceptionSpec: ASTNoexceptSpec, refQual: Optional[str], exceptionSpec: ASTNoexceptSpec,
trailingReturn: "ASTType", trailingReturn: "ASTType",
override: bool, final: bool, attrs: List[ASTAttribute], override: bool, final: bool, attrs: ASTAttributeList,
initializer: Optional[str]) -> None: initializer: Optional[str]) -> None:
self.args = args self.args = args
self.volatile = volatile self.volatile = volatile
@ -2088,9 +2118,9 @@ class ASTParametersQualifiers(ASTBase):
res.append(' final') res.append(' final')
if self.override: if self.override:
res.append(' override') res.append(' override')
for attr in self.attrs: if len(self.attrs) != 0:
res.append(' ') res.append(' ')
res.append(transform(attr)) res.append(transform(self.attrs))
if self.initializer: if self.initializer:
res.append(' = ') res.append(' = ')
res.append(self.initializer) res.append(self.initializer)
@ -2141,9 +2171,9 @@ class ASTParametersQualifiers(ASTBase):
_add_anno(signode, 'final') _add_anno(signode, 'final')
if self.override: if self.override:
_add_anno(signode, 'override') _add_anno(signode, 'override')
for attr in self.attrs: if len(self.attrs) != 0:
signode += addnodes.desc_sig_space() signode += addnodes.desc_sig_space()
attr.describe_signature(signode) self.attrs.describe_signature(signode)
if self.initializer: if self.initializer:
signode += addnodes.desc_sig_space() signode += addnodes.desc_sig_space()
signode += addnodes.desc_sig_punctuation('=', '=') signode += addnodes.desc_sig_punctuation('=', '=')
@ -2181,7 +2211,7 @@ class ASTDeclSpecsSimple(ASTBase):
explicitSpec: Optional[ASTExplicitSpec], explicitSpec: Optional[ASTExplicitSpec],
consteval: bool, constexpr: bool, constinit: bool, consteval: bool, constexpr: bool, constinit: bool,
volatile: bool, const: bool, friend: bool, volatile: bool, const: bool, friend: bool,
attrs: List[ASTAttribute]) -> None: attrs: ASTAttributeList) -> None:
self.storage = storage self.storage = storage
self.threadLocal = threadLocal self.threadLocal = threadLocal
self.inline = inline self.inline = inline
@ -2213,7 +2243,8 @@ class ASTDeclSpecsSimple(ASTBase):
def _stringify(self, transform: StringifyTransform) -> str: def _stringify(self, transform: StringifyTransform) -> str:
res: List[str] = [] res: List[str] = []
res.extend(transform(attr) for attr in self.attrs) if len(self.attrs) != 0:
res.append(transform(self.attrs))
if self.storage: if self.storage:
res.append(self.storage) res.append(self.storage)
if self.threadLocal: if self.threadLocal:
@ -2240,12 +2271,8 @@ class ASTDeclSpecsSimple(ASTBase):
def describe_signature(self, signode: TextElement, def describe_signature(self, signode: TextElement,
env: "BuildEnvironment", symbol: "Symbol") -> None: env: "BuildEnvironment", symbol: "Symbol") -> None:
addSpace = False self.attrs.describe_signature(signode)
for attr in self.attrs: addSpace = len(self.attrs) != 0
if addSpace:
signode += addnodes.desc_sig_space()
addSpace = True
attr.describe_signature(signode)
def _add(signode: TextElement, text: str) -> bool: def _add(signode: TextElement, text: str) -> bool:
if addSpace: if addSpace:
@ -2562,7 +2589,7 @@ class ASTDeclaratorNameBitField(ASTDeclarator):
class ASTDeclaratorPtr(ASTDeclarator): class ASTDeclaratorPtr(ASTDeclarator):
def __init__(self, next: ASTDeclarator, volatile: bool, const: bool, def __init__(self, next: ASTDeclarator, volatile: bool, const: bool,
attrs: List[ASTAttribute]) -> None: attrs: ASTAttributeList) -> None:
assert next assert next
self.next = next self.next = next
self.volatile = volatile self.volatile = volatile
@ -2590,9 +2617,8 @@ class ASTDeclaratorPtr(ASTDeclarator):
def _stringify(self, transform: StringifyTransform) -> str: def _stringify(self, transform: StringifyTransform) -> str:
res = ['*'] res = ['*']
for a in self.attrs: res.append(transform(self.attrs))
res.append(transform(a)) if len(self.attrs) != 0 and (self.volatile or self.const):
if len(self.attrs) > 0 and (self.volatile or self.const):
res.append(' ') res.append(' ')
if self.volatile: if self.volatile:
res.append('volatile') res.append('volatile')
@ -2647,9 +2673,8 @@ class ASTDeclaratorPtr(ASTDeclarator):
env: "BuildEnvironment", symbol: "Symbol") -> None: env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode) verify_description_mode(mode)
signode += addnodes.desc_sig_punctuation('*', '*') signode += addnodes.desc_sig_punctuation('*', '*')
for a in self.attrs: self.attrs.describe_signature(signode)
a.describe_signature(signode) if len(self.attrs) != 0 and (self.volatile or self.const):
if len(self.attrs) > 0 and (self.volatile or self.const):
signode += addnodes.desc_sig_space() signode += addnodes.desc_sig_space()
def _add_anno(signode: TextElement, text: str) -> None: def _add_anno(signode: TextElement, text: str) -> None:
@ -2667,7 +2692,7 @@ class ASTDeclaratorPtr(ASTDeclarator):
class ASTDeclaratorRef(ASTDeclarator): class ASTDeclaratorRef(ASTDeclarator):
def __init__(self, next: ASTDeclarator, attrs: List[ASTAttribute]) -> None: def __init__(self, next: ASTDeclarator, attrs: ASTAttributeList) -> None:
assert next assert next
self.next = next self.next = next
self.attrs = attrs self.attrs = attrs
@ -2697,9 +2722,8 @@ class ASTDeclaratorRef(ASTDeclarator):
def _stringify(self, transform: StringifyTransform) -> str: def _stringify(self, transform: StringifyTransform) -> str:
res = ['&'] res = ['&']
for a in self.attrs: res.append(transform(self.attrs))
res.append(transform(a)) if len(self.attrs) != 0 and self.next.require_space_after_declSpecs():
if len(self.attrs) > 0 and self.next.require_space_after_declSpecs():
res.append(' ') res.append(' ')
res.append(transform(self.next)) res.append(transform(self.next))
return ''.join(res) return ''.join(res)
@ -2728,8 +2752,7 @@ class ASTDeclaratorRef(ASTDeclarator):
env: "BuildEnvironment", symbol: "Symbol") -> None: env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode) verify_description_mode(mode)
signode += addnodes.desc_sig_punctuation('&', '&') signode += addnodes.desc_sig_punctuation('&', '&')
for a in self.attrs: self.attrs.describe_signature(signode)
a.describe_signature(signode)
if len(self.attrs) > 0 and self.next.require_space_after_declSpecs(): if len(self.attrs) > 0 and self.next.require_space_after_declSpecs():
signode += addnodes.desc_sig_space() signode += addnodes.desc_sig_space()
self.next.describe_signature(signode, mode, env, symbol) self.next.describe_signature(signode, mode, env, symbol)
@ -3318,16 +3341,21 @@ class ASTBaseClass(ASTBase):
class ASTClass(ASTBase): class ASTClass(ASTBase):
def __init__(self, name: ASTNestedName, final: bool, bases: List[ASTBaseClass]) -> None: def __init__(self, name: ASTNestedName, final: bool, bases: List[ASTBaseClass],
attrs: ASTAttributeList) -> None:
self.name = name self.name = name
self.final = final self.final = final
self.bases = bases self.bases = bases
self.attrs = attrs
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str: def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
return symbol.get_full_nested_name().get_id(version) return symbol.get_full_nested_name().get_id(version)
def _stringify(self, transform: StringifyTransform) -> str: def _stringify(self, transform: StringifyTransform) -> str:
res = [] res = []
res.append(transform(self.attrs))
if len(self.attrs) != 0:
res.append(' ')
res.append(transform(self.name)) res.append(transform(self.name))
if self.final: if self.final:
res.append(' final') res.append(' final')
@ -3344,6 +3372,9 @@ class ASTClass(ASTBase):
def describe_signature(self, signode: TextElement, mode: str, def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None: env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode) verify_description_mode(mode)
self.attrs.describe_signature(signode)
if len(self.attrs) != 0:
signode += addnodes.desc_sig_space()
self.name.describe_signature(signode, mode, env, symbol=symbol) self.name.describe_signature(signode, mode, env, symbol=symbol)
if self.final: if self.final:
signode += addnodes.desc_sig_space() signode += addnodes.desc_sig_space()
@ -3361,8 +3392,9 @@ class ASTClass(ASTBase):
class ASTUnion(ASTBase): class ASTUnion(ASTBase):
def __init__(self, name: ASTNestedName) -> None: def __init__(self, name: ASTNestedName, attrs: ASTAttributeList) -> None:
self.name = name self.name = name
self.attrs = attrs
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str: def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
if version == 1: if version == 1:
@ -3370,20 +3402,29 @@ class ASTUnion(ASTBase):
return symbol.get_full_nested_name().get_id(version) return symbol.get_full_nested_name().get_id(version)
def _stringify(self, transform: StringifyTransform) -> str: def _stringify(self, transform: StringifyTransform) -> str:
return transform(self.name) res = []
res.append(transform(self.attrs))
if len(self.attrs) != 0:
res.append(' ')
res.append(transform(self.name))
return ''.join(res)
def describe_signature(self, signode: TextElement, mode: str, def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None: env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode) verify_description_mode(mode)
self.attrs.describe_signature(signode)
if len(self.attrs) != 0:
signode += addnodes.desc_sig_space()
self.name.describe_signature(signode, mode, env, symbol=symbol) self.name.describe_signature(signode, mode, env, symbol=symbol)
class ASTEnum(ASTBase): class ASTEnum(ASTBase):
def __init__(self, name: ASTNestedName, scoped: str, def __init__(self, name: ASTNestedName, scoped: str, underlyingType: ASTType,
underlyingType: ASTType) -> None: attrs: ASTAttributeList) -> None:
self.name = name self.name = name
self.scoped = scoped self.scoped = scoped
self.underlyingType = underlyingType self.underlyingType = underlyingType
self.attrs = attrs
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str: def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
if version == 1: if version == 1:
@ -3395,6 +3436,9 @@ class ASTEnum(ASTBase):
if self.scoped: if self.scoped:
res.append(self.scoped) res.append(self.scoped)
res.append(' ') res.append(' ')
res.append(transform(self.attrs))
if len(self.attrs) != 0:
res.append(' ')
res.append(transform(self.name)) res.append(transform(self.name))
if self.underlyingType: if self.underlyingType:
res.append(' : ') res.append(' : ')
@ -3405,6 +3449,9 @@ class ASTEnum(ASTBase):
env: "BuildEnvironment", symbol: "Symbol") -> None: env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode) verify_description_mode(mode)
# self.scoped has been done by the CPPEnumObject # self.scoped has been done by the CPPEnumObject
self.attrs.describe_signature(signode)
if len(self.attrs) != 0:
signode += addnodes.desc_sig_space()
self.name.describe_signature(signode, mode, env, symbol=symbol) self.name.describe_signature(signode, mode, env, symbol=symbol)
if self.underlyingType: if self.underlyingType:
signode += addnodes.desc_sig_space() signode += addnodes.desc_sig_space()
@ -3415,9 +3462,11 @@ class ASTEnum(ASTBase):
class ASTEnumerator(ASTBase): class ASTEnumerator(ASTBase):
def __init__(self, name: ASTNestedName, init: ASTInitializer) -> None: def __init__(self, name: ASTNestedName, init: Optional[ASTInitializer],
attrs: ASTAttributeList) -> None:
self.name = name self.name = name
self.init = init self.init = init
self.attrs = attrs
def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str: def get_id(self, version: int, objectType: str, symbol: "Symbol") -> str:
if version == 1: if version == 1:
@ -3427,6 +3476,9 @@ class ASTEnumerator(ASTBase):
def _stringify(self, transform: StringifyTransform) -> str: def _stringify(self, transform: StringifyTransform) -> str:
res = [] res = []
res.append(transform(self.name)) res.append(transform(self.name))
if len(self.attrs) != 0:
res.append(' ')
res.append(transform(self.attrs))
if self.init: if self.init:
res.append(transform(self.init)) res.append(transform(self.init))
return ''.join(res) return ''.join(res)
@ -3435,6 +3487,9 @@ class ASTEnumerator(ASTBase):
env: "BuildEnvironment", symbol: "Symbol") -> None: env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode) verify_description_mode(mode)
self.name.describe_signature(signode, mode, env, symbol) self.name.describe_signature(signode, mode, env, symbol)
if len(self.attrs) != 0:
signode += addnodes.desc_sig_space()
self.attrs.describe_signature(signode)
if self.init: if self.init:
self.init.describe_signature(signode, 'markType', env, symbol) self.init.describe_signature(signode, 'markType', env, symbol)
@ -5598,50 +5653,60 @@ class DefinitionParser(BaseParser):
return ASTBinOpExpr(exprs, ops) return ASTBinOpExpr(exprs, ops)
return _parse_bin_op_expr(self, 0, inTemplate=inTemplate) return _parse_bin_op_expr(self, 0, inTemplate=inTemplate)
def _parse_conditional_expression_tail(self, orExprHead: Any) -> None: def _parse_conditional_expression_tail(self, orExprHead: ASTExpression,
inTemplate: bool) -> Optional[ASTConditionalExpr]:
# Consumes the orExprHead on success.
# -> "?" expression ":" assignment-expression # -> "?" expression ":" assignment-expression
return None self.skip_ws()
if not self.skip_string("?"):
return None
thenExpr = self._parse_expression()
self.skip_ws()
if not self.skip_string(":"):
self.fail('Expected ":" after then-expression in conditional expression.')
elseExpr = self._parse_assignment_expression(inTemplate)
return ASTConditionalExpr(orExprHead, thenExpr, elseExpr)
def _parse_assignment_expression(self, inTemplate: bool) -> ASTExpression: def _parse_assignment_expression(self, inTemplate: bool) -> ASTExpression:
# -> conditional-expression # -> conditional-expression
# | logical-or-expression assignment-operator initializer-clause # | logical-or-expression assignment-operator initializer-clause
# | throw-expression # | yield-expression -> "co_yield" assignment-expression
# TODO: parse throw-expression: "throw" assignment-expression [opt] # | "co_yield" braced-init-list
# if not a throw expression, then: # | throw-expression -> "throw" assignment-expression[opt]
# -> conditional-expression -> # TODO: yield-expression
# TODO: throw-expression
# Now we have (after expanding conditional-expression:
# logical-or-expression # logical-or-expression
# | logical-or-expression "?" expression ":" assignment-expression # | logical-or-expression "?" expression ":" assignment-expression
# | logical-or-expression assignment-operator initializer-clause # | logical-or-expression assignment-operator initializer-clause
exprs: List[Union[ASTExpression, ASTBracedInitList]] = [] leftExpr = self._parse_logical_or_expression(inTemplate=inTemplate)
ops = [] # the ternary operator
orExpr = self._parse_logical_or_expression(inTemplate=inTemplate) condExpr = self._parse_conditional_expression_tail(leftExpr, inTemplate)
exprs.append(orExpr) if condExpr is not None:
# TODO: handle ternary with _parse_conditional_expression_tail return condExpr
while True: # and actual assignment
oneMore = False for op in _expression_assignment_ops:
self.skip_ws() if op[0] in 'anox':
for op in _expression_assignment_ops: if not self.skip_word(op):
if op[0] in 'anox': continue
if not self.skip_word(op): else:
continue if not self.skip_string(op):
else: continue
if not self.skip_string(op): rightExpr = self._parse_initializer_clause()
continue return ASTAssignmentExpr(leftExpr, op, rightExpr)
expr = self._parse_initializer_clause() # just a logical-or-expression
exprs.append(expr) return leftExpr
ops.append(op)
oneMore = True
if not oneMore:
break
if len(ops) == 0:
return orExpr
else:
return ASTAssignmentExpr(exprs, ops)
def _parse_constant_expression(self, inTemplate: bool) -> ASTExpression: def _parse_constant_expression(self, inTemplate: bool) -> ASTExpression:
# -> conditional-expression # -> conditional-expression ->
# logical-or-expression
# | logical-or-expression "?" expression ":" assignment-expression
orExpr = self._parse_logical_or_expression(inTemplate=inTemplate) orExpr = self._parse_logical_or_expression(inTemplate=inTemplate)
# TODO: use _parse_conditional_expression_tail condExpr = self._parse_conditional_expression_tail(orExpr, inTemplate)
if condExpr is not None:
return condExpr
return orExpr return orExpr
def _parse_expression(self) -> ASTExpression: def _parse_expression(self) -> ASTExpression:
@ -6057,12 +6122,7 @@ class DefinitionParser(BaseParser):
override = self.skip_word_and_ws( override = self.skip_word_and_ws(
'override') # they can be permuted 'override') # they can be permuted
attrs = [] attrs = self._parse_attribute_list()
while True:
attr = self._parse_attribute()
if attr is None:
break
attrs.append(attr)
self.skip_ws() self.skip_ws()
initializer = None initializer = None
@ -6174,7 +6234,7 @@ class DefinitionParser(BaseParser):
break break
return ASTDeclSpecsSimple(storage, threadLocal, inline, virtual, return ASTDeclSpecsSimple(storage, threadLocal, inline, virtual,
explicitSpec, consteval, constexpr, constinit, explicitSpec, consteval, constexpr, constinit,
volatile, const, friend, attrs) volatile, const, friend, ASTAttributeList(attrs))
def _parse_decl_specs(self, outer: str, typed: bool = True) -> ASTDeclSpecs: def _parse_decl_specs(self, outer: str, typed: bool = True) -> ASTDeclSpecs:
if outer: if outer:
@ -6271,7 +6331,7 @@ class DefinitionParser(BaseParser):
self.skip_ws() self.skip_ws()
volatile = False volatile = False
const = False const = False
attrs = [] attrList = []
while 1: while 1:
if not volatile: if not volatile:
volatile = self.skip_word_and_ws('volatile') volatile = self.skip_word_and_ws('volatile')
@ -6283,19 +6343,15 @@ class DefinitionParser(BaseParser):
continue continue
attr = self._parse_attribute() attr = self._parse_attribute()
if attr is not None: if attr is not None:
attrs.append(attr) attrList.append(attr)
continue continue
break break
next = self._parse_declarator(named, paramMode, typed) next = self._parse_declarator(named, paramMode, typed)
return ASTDeclaratorPtr(next=next, volatile=volatile, const=const, attrs=attrs) return ASTDeclaratorPtr(next=next, volatile=volatile, const=const,
attrs=ASTAttributeList(attrList))
# TODO: shouldn't we parse an R-value ref here first? # TODO: shouldn't we parse an R-value ref here first?
if typed and self.skip_string("&"): if typed and self.skip_string("&"):
attrs = [] attrs = self._parse_attribute_list()
while 1:
attr = self._parse_attribute()
if attr is None:
break
attrs.append(attr)
next = self._parse_declarator(named, paramMode, typed) next = self._parse_declarator(named, paramMode, typed)
return ASTDeclaratorRef(next=next, attrs=attrs) return ASTDeclaratorRef(next=next, attrs=attrs)
if typed and self.skip_string("..."): if typed and self.skip_string("..."):
@ -6567,6 +6623,7 @@ class DefinitionParser(BaseParser):
return ASTConcept(nestedName, initializer) return ASTConcept(nestedName, initializer)
def _parse_class(self) -> ASTClass: def _parse_class(self) -> ASTClass:
attrs = self._parse_attribute_list()
name = self._parse_nested_name() name = self._parse_nested_name()
self.skip_ws() self.skip_ws()
final = self.skip_word_and_ws('final') final = self.skip_word_and_ws('final')
@ -6594,24 +6651,26 @@ class DefinitionParser(BaseParser):
continue continue
else: else:
break break
return ASTClass(name, final, bases) return ASTClass(name, final, bases, attrs)
def _parse_union(self) -> ASTUnion: def _parse_union(self) -> ASTUnion:
attrs = self._parse_attribute_list()
name = self._parse_nested_name() name = self._parse_nested_name()
return ASTUnion(name) return ASTUnion(name, attrs)
def _parse_enum(self) -> ASTEnum: def _parse_enum(self) -> ASTEnum:
scoped = None # is set by CPPEnumObject scoped = None # is set by CPPEnumObject
self.skip_ws() attrs = self._parse_attribute_list()
name = self._parse_nested_name() name = self._parse_nested_name()
self.skip_ws() self.skip_ws()
underlyingType = None underlyingType = None
if self.skip_string(':'): if self.skip_string(':'):
underlyingType = self._parse_type(named=False) underlyingType = self._parse_type(named=False)
return ASTEnum(name, scoped, underlyingType) return ASTEnum(name, scoped, underlyingType, attrs)
def _parse_enumerator(self) -> ASTEnumerator: def _parse_enumerator(self) -> ASTEnumerator:
name = self._parse_nested_name() name = self._parse_nested_name()
attrs = self._parse_attribute_list()
self.skip_ws() self.skip_ws()
init = None init = None
if self.skip_string('='): if self.skip_string('='):
@ -6621,7 +6680,7 @@ class DefinitionParser(BaseParser):
return self._parse_constant_expression(inTemplate=False) return self._parse_constant_expression(inTemplate=False)
initVal = self._parse_expression_fallback([], parser) initVal = self._parse_expression_fallback([], parser)
init = ASTInitializer(initVal) init = ASTInitializer(initVal)
return ASTEnumerator(name, init) return ASTEnumerator(name, init, attrs)
# ========================================================================== # ==========================================================================
@ -7992,7 +8051,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
return { return {
'version': 'builtin', 'version': 'builtin',
'env_version': 4, 'env_version': 6,
'parallel_read_safe': True, 'parallel_read_safe': True,
'parallel_write_safe': True, 'parallel_write_safe': True,
} }

View File

@ -1,12 +1,4 @@
""" """The index domain."""
sphinx.domains.index
~~~~~~~~~~~~~~~~~~~~
The index domain.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Tuple from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Tuple
@ -110,7 +102,7 @@ class IndexRole(ReferenceRole):
index = addnodes.index(entries=entries) index = addnodes.index(entries=entries)
target = nodes.target('', '', ids=[target_id]) target = nodes.target('', '', ids=[target_id])
text = nodes.Text(title, title) text = nodes.Text(title)
self.set_source_info(index) self.set_source_info(index)
return [index, target, text], [] return [index, target, text], []

View File

@ -1,12 +1,4 @@
""" """The JavaScript domain."""
sphinx.domains.javascript
~~~~~~~~~~~~~~~~~~~~~~~~~
The JavaScript domain.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import Any, Dict, Iterator, List, Optional, Tuple, cast from typing import Any, Dict, Iterator, List, Optional, Tuple, cast
@ -122,13 +114,6 @@ class JSObject(ObjectDescription[Tuple[str, str]]):
fullname = (mod_name + '.' if mod_name else '') + name_obj[0] fullname = (mod_name + '.' if mod_name else '') + name_obj[0]
node_id = make_id(self.env, self.state.document, '', fullname) node_id = make_id(self.env, self.state.document, '', fullname)
signode['ids'].append(node_id) signode['ids'].append(node_id)
# Assign old styled node_id not to break old hyperlinks (if possible)
# Note: Will be removed in Sphinx-5.0 (RemovedInSphinx50Warning)
old_node_id = self.make_old_id(fullname)
if old_node_id not in self.state.document.ids and old_node_id not in signode['ids']:
signode['ids'].append(old_node_id)
self.state.document.note_explicit_target(signode) self.state.document.note_explicit_target(signode)
domain = cast(JavaScriptDomain, self.env.get_domain('js')) domain = cast(JavaScriptDomain, self.env.get_domain('js'))
@ -288,13 +273,6 @@ class JSModule(SphinxDirective):
location=(self.env.docname, self.lineno)) location=(self.env.docname, self.lineno))
target = nodes.target('', '', ids=[node_id], ismod=True) target = nodes.target('', '', ids=[node_id], ismod=True)
# Assign old styled node_id not to break old hyperlinks (if possible)
# Note: Will be removed in Sphinx-5.0 (RemovedInSphinx50Warning)
old_node_id = self.make_old_id(mod_name)
if old_node_id not in self.state.document.ids and old_node_id not in target['ids']:
target['ids'].append(old_node_id)
self.state.document.note_explicit_target(target) self.state.document.note_explicit_target(target)
ret.append(target) ret.append(target)
indextext = _('%s (module)') % mod_name indextext = _('%s (module)') % mod_name

View File

@ -1,12 +1,4 @@
""" """The math domain."""
sphinx.domains.math
~~~~~~~~~~~~~~~~~~~
The math domain.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple from typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple

View File

@ -1,12 +1,4 @@
""" """The Python domain."""
sphinx.domains.python
~~~~~~~~~~~~~~~~~~~~~
The Python domain.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import builtins import builtins
import inspect import inspect
@ -26,7 +18,7 @@ from sphinx import addnodes
from sphinx.addnodes import desc_signature, pending_xref, pending_xref_condition from sphinx.addnodes import desc_signature, pending_xref, pending_xref_condition
from sphinx.application import Sphinx from sphinx.application import Sphinx
from sphinx.builders import Builder from sphinx.builders import Builder
from sphinx.deprecation import RemovedInSphinx50Warning, RemovedInSphinx60Warning from sphinx.deprecation import RemovedInSphinx60Warning
from sphinx.directives import ObjectDescription from sphinx.directives import ObjectDescription
from sphinx.domains import Domain, Index, IndexEntry, ObjType from sphinx.domains import Domain, Index, IndexEntry, ObjType
from sphinx.environment import BuildEnvironment from sphinx.environment import BuildEnvironment
@ -133,7 +125,7 @@ def type_to_xref(target: str, env: BuildEnvironment = None, suppress_prefix: boo
refspecific=refspecific, **kwargs) refspecific=refspecific, **kwargs)
def _parse_annotation(annotation: str, env: BuildEnvironment = None) -> List[Node]: def _parse_annotation(annotation: str, env: BuildEnvironment) -> List[Node]:
"""Parse type annotation.""" """Parse type annotation."""
def unparse(node: ast.AST) -> List[Node]: def unparse(node: ast.AST) -> List[Node]:
if isinstance(node, ast.Attribute): if isinstance(node, ast.Attribute):
@ -227,10 +219,6 @@ def _parse_annotation(annotation: str, env: BuildEnvironment = None) -> List[Nod
raise SyntaxError # unsupported syntax raise SyntaxError # unsupported syntax
if env is None:
warnings.warn("The env parameter for _parse_annotation becomes required now.",
RemovedInSphinx50Warning, stacklevel=2)
try: try:
tree = ast_parse(annotation) tree = ast_parse(annotation)
result: List[Node] = [] result: List[Node] = []
@ -577,12 +565,6 @@ class PyObject(ObjectDescription[Tuple[str, str]]):
fullname = (modname + '.' if modname else '') + name_cls[0] fullname = (modname + '.' if modname else '') + name_cls[0]
node_id = make_id(self.env, self.state.document, '', fullname) node_id = make_id(self.env, self.state.document, '', fullname)
signode['ids'].append(node_id) signode['ids'].append(node_id)
# Assign old styled node_id(fullname) not to break old hyperlinks (if possible)
# Note: Will removed in Sphinx-5.0 (RemovedInSphinx50Warning)
if node_id != fullname and fullname not in self.state.document.ids:
signode['ids'].append(fullname)
self.state.document.note_explicit_target(signode) self.state.document.note_explicit_target(signode)
domain = cast(PythonDomain, self.env.get_domain('py')) domain = cast(PythonDomain, self.env.get_domain('py'))
@ -978,29 +960,6 @@ class PyProperty(PyObject):
return _('%s (%s property)') % (attrname, clsname) return _('%s (%s property)') % (attrname, clsname)
class PyDecoratorMixin:
"""
Mixin for decorator directives.
"""
def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]:
for cls in self.__class__.__mro__:
if cls.__name__ != 'DirectiveAdapter':
warnings.warn('PyDecoratorMixin is deprecated. '
'Please check the implementation of %s' % cls,
RemovedInSphinx50Warning, stacklevel=2)
break
else:
warnings.warn('PyDecoratorMixin is deprecated',
RemovedInSphinx50Warning, stacklevel=2)
ret = super().handle_signature(sig, signode) # type: ignore
signode.insert(0, addnodes.desc_addname('@', '@'))
return ret
def needs_arglist(self) -> bool:
return False
class PyModule(SphinxDirective): class PyModule(SphinxDirective):
""" """
Directive to mark description of a new module. Directive to mark description of a new module.
@ -1029,13 +988,6 @@ class PyModule(SphinxDirective):
node_id = make_id(self.env, self.state.document, 'module', modname) node_id = make_id(self.env, self.state.document, 'module', modname)
target = nodes.target('', '', ids=[node_id], ismod=True) target = nodes.target('', '', ids=[node_id], ismod=True)
self.set_source_info(target) self.set_source_info(target)
# Assign old styled node_id not to break old hyperlinks (if possible)
# Note: Will removed in Sphinx-5.0 (RemovedInSphinx50Warning)
old_node_id = self.make_old_id(modname)
if node_id != old_node_id and old_node_id not in self.state.document.ids:
target['ids'].append(old_node_id)
self.state.document.note_explicit_target(target) self.state.document.note_explicit_target(target)
domain.note_module(modname, domain.note_module(modname,
@ -1474,7 +1426,7 @@ def builtin_resolver(app: Sphinx, env: BuildEnvironment,
if s.startswith('typing.'): if s.startswith('typing.'):
s = s.split('.', 1)[1] s = s.split('.', 1)[1]
return s in typing.__all__ # type: ignore return s in typing.__all__
if node.get('refdomain') != 'py': if node.get('refdomain') != 'py':
return None return None

View File

@ -1,12 +1,4 @@
""" """The reStructuredText domain."""
sphinx.domains.rst
~~~~~~~~~~~~~~~~~~
The reStructuredText domain.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import re import re
from typing import Any, Dict, Iterator, List, Optional, Tuple, cast from typing import Any, Dict, Iterator, List, Optional, Tuple, cast
@ -40,13 +32,6 @@ class ReSTMarkup(ObjectDescription[str]):
def add_target_and_index(self, name: str, sig: str, signode: desc_signature) -> None: def add_target_and_index(self, name: str, sig: str, signode: desc_signature) -> None:
node_id = make_id(self.env, self.state.document, self.objtype, name) node_id = make_id(self.env, self.state.document, self.objtype, name)
signode['ids'].append(node_id) signode['ids'].append(node_id)
# Assign old styled node_id not to break old hyperlinks (if possible)
# Note: Will be removed in Sphinx-5.0 (RemovedInSphinx50Warning)
old_node_id = self.make_old_id(name)
if old_node_id not in self.state.document.ids and old_node_id not in signode['ids']:
signode['ids'].append(old_node_id)
self.state.document.note_explicit_target(signode) self.state.document.note_explicit_target(signode)
domain = cast(ReSTDomain, self.env.get_domain('rst')) domain = cast(ReSTDomain, self.env.get_domain('rst'))
@ -150,13 +135,6 @@ class ReSTDirectiveOption(ReSTMarkup):
node_id = make_id(self.env, self.state.document, prefix, name) node_id = make_id(self.env, self.state.document, prefix, name)
signode['ids'].append(node_id) signode['ids'].append(node_id)
# Assign old styled node_id not to break old hyperlinks (if possible)
# Note: Will be removed in Sphinx-5.0 (RemovedInSphinx50Warning)
old_node_id = self.make_old_id(name)
if old_node_id not in self.state.document.ids and old_node_id not in signode['ids']:
signode['ids'].append(old_node_id)
self.state.document.note_explicit_target(signode) self.state.document.note_explicit_target(signode)
domain.note_object(self.objtype, objname, node_id, location=signode) domain.note_object(self.objtype, objname, node_id, location=signode)

View File

@ -1,15 +1,6 @@
""" """The standard domain."""
sphinx.domains.std
~~~~~~~~~~~~~~~~~~
The standard domain.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import re import re
import warnings
from copy import copy from copy import copy
from typing import (TYPE_CHECKING, Any, Callable, Dict, Iterable, Iterator, List, Optional, from typing import (TYPE_CHECKING, Any, Callable, Dict, Iterable, Iterator, List, Optional,
Tuple, Type, Union, cast) Tuple, Type, Union, cast)
@ -21,7 +12,6 @@ from docutils.statemachine import StringList
from sphinx import addnodes from sphinx import addnodes
from sphinx.addnodes import desc_signature, pending_xref from sphinx.addnodes import desc_signature, pending_xref
from sphinx.deprecation import RemovedInSphinx50Warning
from sphinx.directives import ObjectDescription from sphinx.directives import ObjectDescription
from sphinx.domains import Domain, ObjType from sphinx.domains import Domain, ObjType
from sphinx.locale import _, __ from sphinx.locale import _, __
@ -65,13 +55,6 @@ class GenericObject(ObjectDescription[str]):
def add_target_and_index(self, name: str, sig: str, signode: desc_signature) -> None: def add_target_and_index(self, name: str, sig: str, signode: desc_signature) -> None:
node_id = make_id(self.env, self.state.document, self.objtype, name) node_id = make_id(self.env, self.state.document, self.objtype, name)
signode['ids'].append(node_id) signode['ids'].append(node_id)
# Assign old styled node_id not to break old hyperlinks (if possible)
# Note: Will be removed in Sphinx-5.0 (RemovedInSphinx50Warning)
old_node_id = self.make_old_id(name)
if old_node_id not in self.state.document.ids and old_node_id not in signode['ids']:
signode['ids'].append(old_node_id)
self.state.document.note_explicit_target(signode) self.state.document.note_explicit_target(signode)
if self.indextemplate: if self.indextemplate:
@ -139,13 +122,6 @@ class Target(SphinxDirective):
node_id = make_id(self.env, self.state.document, self.name, fullname) node_id = make_id(self.env, self.state.document, self.name, fullname)
node = nodes.target('', '', ids=[node_id]) node = nodes.target('', '', ids=[node_id])
self.set_source_info(node) self.set_source_info(node)
# Assign old styled node_id not to break old hyperlinks (if possible)
# Note: Will be removed in Sphinx-5.0 (RemovedInSphinx50Warning)
old_node_id = self.make_old_id(fullname)
if old_node_id not in self.state.document.ids and old_node_id not in node['ids']:
node['ids'].append(old_node_id)
self.state.document.note_explicit_target(node) self.state.document.note_explicit_target(node)
ret: List[Node] = [node] ret: List[Node] = [node]
if self.indextemplate: if self.indextemplate:
@ -440,7 +416,7 @@ def token_xrefs(text: str, productionGroup: str = '') -> List[Node]:
for m in token_re.finditer(text): for m in token_re.finditer(text):
if m.start() > pos: if m.start() > pos:
txt = text[pos:m.start()] txt = text[pos:m.start()]
retnodes.append(nodes.Text(txt, txt)) retnodes.append(nodes.Text(txt))
token = m.group(1) token = m.group(1)
if ':' in token: if ':' in token:
if token[0] == '~': if token[0] == '~':
@ -461,7 +437,7 @@ def token_xrefs(text: str, productionGroup: str = '') -> List[Node]:
retnodes.append(refnode) retnodes.append(refnode)
pos = m.end() pos = m.end()
if pos < len(text): if pos < len(text):
retnodes.append(nodes.Text(text[pos:], text[pos:])) retnodes.append(nodes.Text(text[pos:]))
return retnodes return retnodes
@ -502,14 +478,6 @@ class ProductionList(SphinxDirective):
prefix = 'grammar-token-%s' % productionGroup prefix = 'grammar-token-%s' % productionGroup
node_id = make_id(self.env, self.state.document, prefix, name) node_id = make_id(self.env, self.state.document, prefix, name)
subnode['ids'].append(node_id) subnode['ids'].append(node_id)
# Assign old styled node_id not to break old hyperlinks (if possible)
# Note: Will be removed in Sphinx-5.0 (RemovedInSphinx50Warning)
old_node_id = self.make_old_id(name)
if (old_node_id not in self.state.document.ids and
old_node_id not in subnode['ids']):
subnode['ids'].append(old_node_id)
self.state.document.note_implicit_target(subnode, subnode) self.state.document.note_implicit_target(subnode, subnode)
if len(productionGroup) != 0: if len(productionGroup) != 0:
@ -667,11 +635,6 @@ class StandardDomain(Domain):
objtype, name, docname, location=location) objtype, name, docname, location=location)
self.objects[objtype, name] = (self.env.docname, labelid) self.objects[objtype, name] = (self.env.docname, labelid)
def add_object(self, objtype: str, name: str, docname: str, labelid: str) -> None:
warnings.warn('StandardDomain.add_object() is deprecated.',
RemovedInSphinx50Warning, stacklevel=2)
self.objects[objtype, name] = (docname, labelid)
@property @property
def _terms(self) -> Dict[str, Tuple[str, str]]: def _terms(self) -> Dict[str, Tuple[str, str]]:
""".. note:: Will be removed soon. internal use only.""" """.. note:: Will be removed soon. internal use only."""
@ -762,11 +725,10 @@ class StandardDomain(Domain):
sectname = clean_astext(title) sectname = clean_astext(title)
elif node.tagname == 'rubric': elif node.tagname == 'rubric':
sectname = clean_astext(node) sectname = clean_astext(node)
elif node.tagname == 'target' and len(node) > 0:
# inline target (ex: blah _`blah` blah)
sectname = clean_astext(node)
elif self.is_enumerable_node(node): elif self.is_enumerable_node(node):
sectname = self.get_numfig_title(node) sectname = self.get_numfig_title(node)
if not sectname:
continue
else: else:
toctree = next(node.findall(addnodes.toctree), None) toctree = next(node.findall(addnodes.toctree), None)
if toctree and toctree.get('caption'): if toctree and toctree.get('caption'):
@ -774,8 +736,7 @@ class StandardDomain(Domain):
else: else:
# anonymous-only labels # anonymous-only labels
continue continue
if sectname: self.labels[name] = docname, labelid, sectname
self.labels[name] = docname, labelid, sectname
def add_program_option(self, program: str, name: str, docname: str, labelid: str) -> None: def add_program_option(self, program: str, name: str, docname: str, labelid: str) -> None:
self.progoptions[program, name] = (docname, labelid) self.progoptions[program, name] = (docname, labelid)

View File

@ -1,12 +1,4 @@
""" """Global creation environment."""
sphinx.environment
~~~~~~~~~~~~~~~~~~
Global creation environment.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import os import os
import pickle import pickle
@ -18,6 +10,7 @@ from os import path
from typing import (TYPE_CHECKING, Any, Callable, Dict, Generator, Iterator, List, Optional, from typing import (TYPE_CHECKING, Any, Callable, Dict, Generator, Iterator, List, Optional,
Set, Tuple, Union) Set, Tuple, Union)
import docutils
from docutils import nodes from docutils import nodes
from docutils.nodes import Node from docutils.nodes import Node
@ -46,10 +39,10 @@ logger = logging.getLogger(__name__)
default_settings: Dict[str, Any] = { default_settings: Dict[str, Any] = {
'auto_id_prefix': 'id', 'auto_id_prefix': 'id',
'embed_images': False, 'image_loading': 'link',
'embed_stylesheet': False, 'embed_stylesheet': False,
'cloak_email_addresses': True, 'cloak_email_addresses': True,
'pep_base_url': 'https://www.python.org/dev/peps/', 'pep_base_url': 'https://peps.python.org/',
'pep_references': None, 'pep_references': None,
'rfc_base_url': 'https://datatracker.ietf.org/doc/html/', 'rfc_base_url': 'https://datatracker.ietf.org/doc/html/',
'rfc_references': None, 'rfc_references': None,
@ -61,6 +54,8 @@ default_settings: Dict[str, Any] = {
'file_insertion_enabled': True, 'file_insertion_enabled': True,
'smartquotes_locales': [], 'smartquotes_locales': [],
} }
if docutils.__version_info__[:2] <= (0, 17):
default_settings['embed_images'] = False
# This is increased every time an environment attribute is added # This is increased every time an environment attribute is added
# or changed to properly invalidate pickle files. # or changed to properly invalidate pickle files.
@ -261,7 +256,7 @@ class BuildEnvironment:
"""Update settings by new config.""" """Update settings by new config."""
self.settings['input_encoding'] = config.source_encoding self.settings['input_encoding'] = config.source_encoding
self.settings['trim_footnote_reference_space'] = config.trim_footnote_reference_space self.settings['trim_footnote_reference_space'] = config.trim_footnote_reference_space
self.settings['language_code'] = config.language or 'en' self.settings['language_code'] = config.language
# Allow to disable by 3rd party extension (workaround) # Allow to disable by 3rd party extension (workaround)
self.settings.setdefault('smart_quotes', True) self.settings.setdefault('smart_quotes', True)

View File

@ -1,9 +1 @@
""" """Sphinx environment adapters"""
sphinx.environment.adapters
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sphinx environment adapters
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""

View File

@ -1,12 +1,4 @@
""" """Assets adapter for sphinx.environment."""
sphinx.environment.adapters.asset
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Assets adapter for sphinx.environment.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from sphinx.environment import BuildEnvironment from sphinx.environment import BuildEnvironment

View File

@ -1,12 +1,4 @@
""" """Index entries adapters for sphinx.environment."""
sphinx.environment.adapters.indexentries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Index entries adapters for sphinx.environment.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import re import re
import unicodedata import unicodedata

View File

@ -1,12 +1,4 @@
""" """Toctree adapter for sphinx.environment."""
sphinx.environment.adapters.toctree
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Toctree adapter for sphinx.environment.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import TYPE_CHECKING, Any, Iterable, List, Optional, cast from typing import TYPE_CHECKING, Any, Iterable, List, Optional, cast

View File

@ -1,12 +1,4 @@
""" """The data collector components for sphinx.environment."""
sphinx.environment.collectors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The data collector components for sphinx.environment.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import TYPE_CHECKING, Dict, List, Optional, Set from typing import TYPE_CHECKING, Dict, List, Optional, Set

View File

@ -1,12 +1,4 @@
""" """The image collector for sphinx.environment."""
sphinx.environment.collectors.asset
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The image collector for sphinx.environment.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import os import os
from glob import glob from glob import glob
@ -64,18 +56,16 @@ class ImageCollector(EnvironmentCollector):
rel_imgpath, full_imgpath = app.env.relfn2path(imguri, docname) rel_imgpath, full_imgpath = app.env.relfn2path(imguri, docname)
node['uri'] = rel_imgpath node['uri'] = rel_imgpath
if app.config.language: # Search language-specific figures at first
# Search language-specific figures at first i18n_imguri = get_image_filename_for_language(imguri, app.env)
i18n_imguri = get_image_filename_for_language(imguri, app.env) _, full_i18n_imgpath = app.env.relfn2path(i18n_imguri, docname)
_, full_i18n_imgpath = app.env.relfn2path(i18n_imguri, docname) self.collect_candidates(app.env, full_i18n_imgpath, candidates, node)
self.collect_candidates(app.env, full_i18n_imgpath, candidates, node)
self.collect_candidates(app.env, full_imgpath, candidates, node) self.collect_candidates(app.env, full_imgpath, candidates, node)
else: else:
if app.config.language: # substitute imguri by figure_language_filename
# substitute imguri by figure_language_filename # (ex. foo.png -> foo.en.png)
# (ex. foo.png -> foo.en.png) imguri = search_image_for_language(imguri, app.env)
imguri = search_image_for_language(imguri, app.env)
# Update `node['uri']` to a relative path from srcdir # Update `node['uri']` to a relative path from srcdir
# from a relative path from current document. # from a relative path from current document.

View File

@ -1,12 +1,4 @@
""" """The dependencies collector components for sphinx.environment."""
sphinx.environment.collectors.dependencies
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The dependencies collector components for sphinx.environment.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import os import os
from os import path from os import path

View File

@ -1,12 +1,4 @@
""" """The metadata collector components for sphinx.environment."""
sphinx.environment.collectors.metadata
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The metadata collector components for sphinx.environment.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import Any, Dict, List, Set, cast from typing import Any, Dict, List, Set, cast

View File

@ -1,12 +1,4 @@
""" """The title collector components for sphinx.environment."""
sphinx.environment.collectors.title
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The title collector components for sphinx.environment.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import Any, Dict, Set from typing import Any, Dict, Set

View File

@ -1,12 +1,4 @@
""" """Toctree collector for sphinx.environment."""
sphinx.environment.collectors.toctree
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Toctree collector for sphinx.environment.
:copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from typing import Any, Dict, List, Set, Tuple, Type, TypeVar, cast from typing import Any, Dict, List, Set, Tuple, Type, TypeVar, cast

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