mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch 'master' into 5637
This commit is contained in:
commit
c5f0025ed9
@ -6,6 +6,6 @@ jobs:
|
||||
working_directory: /sphinx
|
||||
steps:
|
||||
- checkout
|
||||
- run: /python3.5/bin/pip install -U pip setuptools
|
||||
- run: /python3.5/bin/pip install -U .[test,websupport]
|
||||
- run: make test PYTHON=/python3.5/bin/python
|
||||
- run: /python3.6/bin/pip install -U pip setuptools
|
||||
- run: /python3.6/bin/pip install -U .[test,websupport]
|
||||
- run: make test PYTHON=/python3.6/bin/python
|
||||
|
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -15,7 +15,7 @@ Steps to reproduce the behavior:
|
||||
```
|
||||
<Paste your command-line here which cause the problem>
|
||||
|
||||
$ git clone htps://github.com/.../some_project
|
||||
$ git clone https://github.com/.../some_project
|
||||
$ cd some_project
|
||||
$ pip install -r requirements.txt
|
||||
$ cd docs
|
||||
|
6
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
6
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
# Ref: https://help.github.com/en/github/building-a-strong-community/configuring-issue-templates-for-your-repository#configuring-the-template-chooser
|
||||
blank_issues_enabled: false # default: true
|
||||
contact_links:
|
||||
- name: Question
|
||||
url: https://groups.google.com/forum/#!forum/sphinx-users
|
||||
about: For Q&A purpose, please use sphinx-users mailing list.
|
17
.github/ISSUE_TEMPLATE/question.md
vendored
17
.github/ISSUE_TEMPLATE/question.md
vendored
@ -1,17 +0,0 @@
|
||||
---
|
||||
name: Question
|
||||
about: For Q&A purpose, please use https://groups.google.com/forum/#!forum/sphinx-users
|
||||
title: For Q&A purpose, please use sphinx-users group
|
||||
labels: 'question'
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
# Important
|
||||
|
||||
This is a list of issues for Sphinx, **not a forum**.
|
||||
If you'd like to post a question, please move to sphinx-users group.
|
||||
https://groups.google.com/forum/#!forum/sphinx-users
|
||||
|
||||
Thanks,
|
||||
|
11
.github/PULL_REQUEST_TEMPLATE.md
vendored
11
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -1,9 +1,20 @@
|
||||
Subject: <short purpose of this pull request>
|
||||
|
||||
<!--
|
||||
Before posting a pull request, please choose a appropriate branch:
|
||||
|
||||
- Breaking changes: master
|
||||
- Critical or severe bugs: X.Y.Z
|
||||
- Others: X.Y
|
||||
|
||||
For more details, see https://www.sphinx-doc.org/en/master/devguide.html#branch-model
|
||||
-->
|
||||
|
||||
### Feature or Bugfix
|
||||
<!-- please choose -->
|
||||
- Feature
|
||||
- Bugfix
|
||||
- Refactoring
|
||||
|
||||
### Purpose
|
||||
- <long purpose of this pull request>
|
||||
|
11
.travis.yml
11
.travis.yml
@ -19,12 +19,18 @@ matrix:
|
||||
- TOXENV=du13
|
||||
- python: '3.7'
|
||||
env:
|
||||
- TOXENV=py37
|
||||
- TOXENV=du14
|
||||
- python: '3.8'
|
||||
env:
|
||||
- TOXENV=du15
|
||||
- PYTEST_ADDOPTS="--cov ./ --cov-append --cov-config setup.cfg"
|
||||
- python: 'nightly'
|
||||
env: TOXENV=py38
|
||||
env:
|
||||
- TOXENV=du16
|
||||
- python: '3.6'
|
||||
env: TOXENV=docs
|
||||
- python: '3.6'
|
||||
env: TOXENV=docslint
|
||||
- python: '3.6'
|
||||
env: TOXENV=mypy
|
||||
- python: '3.6'
|
||||
@ -37,6 +43,7 @@ matrix:
|
||||
services: xvfb
|
||||
|
||||
install:
|
||||
- "sudo apt-get install graphviz"
|
||||
- if [ $IS_PYTHON = true ]; then pip install -U tox codecov; fi
|
||||
- if [ $IS_PYTHON = false ]; then npm install; fi
|
||||
|
||||
|
4
AUTHORS
4
AUTHORS
@ -25,6 +25,7 @@ Other contributors, listed alphabetically, are:
|
||||
* Henrique Bastos -- SVG support for graphviz extension
|
||||
* Daniel Bültmann -- todo extension
|
||||
* Marco Buttu -- doctest extension (pyversion option)
|
||||
* Nathan Damon -- bugfix in validation of static paths in html builders
|
||||
* Etienne Desautels -- apidoc module
|
||||
* Michael Droettboom -- inheritance_diagram extension
|
||||
* Charles Duffy -- original graphviz extension
|
||||
@ -35,7 +36,7 @@ Other contributors, listed alphabetically, are:
|
||||
* Hernan Grecco -- search improvements
|
||||
* Horst Gutmann -- internationalization support
|
||||
* Martin Hans -- autodoc improvements
|
||||
* Zac Hatfield-Dodds -- doctest reporting improvements
|
||||
* Zac Hatfield-Dodds -- doctest reporting improvements, intersphinx performance
|
||||
* Doug Hellmann -- graphviz improvements
|
||||
* Tim Hoffmann -- theme improvements
|
||||
* Antti Kaihola -- doctest extension (skipif option)
|
||||
@ -82,6 +83,7 @@ Other contributors, listed alphabetically, are:
|
||||
* Stephen Finucane -- setup command improvements and documentation
|
||||
* Daniel Pizetta -- inheritance diagram improvements
|
||||
* KINEBUCHI Tomohiko -- typing Sphinx as well as docutils
|
||||
* Adrián Chaves (Gallaecio) -- coverage builder improvements
|
||||
|
||||
Many thanks for all contributions!
|
||||
|
||||
|
76
CODE_OF_CONDUCT
Normal file
76
CODE_OF_CONDUCT
Normal file
@ -0,0 +1,76 @@
|
||||
Like the technical community as a whole, the Sphinx team and community is made
|
||||
up of volunteers from all over the world.
|
||||
Diversity is a strength, but it can also lead to communication issues and
|
||||
unhappiness. To that end, we have a few ground rules that we ask people to
|
||||
adhere to.
|
||||
|
||||
* **Be friendly and patient.**
|
||||
|
||||
* **Be welcoming.**
|
||||
We strive to be a community that welcomes and supports people of all
|
||||
backgrounds and identities. This includes, but is not limited to members of
|
||||
any race, ethnicity, culture, national origin, colour, immigration status,
|
||||
social and economic class, educational level, sex, sexual orientation, gender
|
||||
identity and expression, age, size, family status, political belief, religion,
|
||||
and mental and physical ability.
|
||||
|
||||
* **Be considerate.**
|
||||
Your work will be used by other people, and you in turn will depend on the
|
||||
work of others. Any decision you take will affect users and colleagues, and
|
||||
you should take those consequences into account when making decisions.
|
||||
Remember that we're a world-wide community, so you might not be communicating
|
||||
in someone else's primary language.
|
||||
|
||||
* **Be respectful.**
|
||||
Not all of us will agree all the time, but disagreement is no excuse for poor
|
||||
behavior and poor manners. We might all experience some frustration now and
|
||||
then, but we cannot allow that frustration to turn into a personal attack.
|
||||
It’s important to remember that a community where people feel uncomfortable or
|
||||
threatened is not a productive one. Members of the Sphinx community should be
|
||||
respectful when dealing with other members as well as with people outside the
|
||||
Sphinx community.
|
||||
|
||||
* **Be careful in the words that you choose.**
|
||||
We are a community of professionals, and we conduct ourselves professionally.
|
||||
Be kind to others. Do not insult or put down other participants. Harassment
|
||||
and other exclusionary behavior aren't acceptable. This includes, but is not
|
||||
limited to:
|
||||
|
||||
* Violent threats or language directed against another person.
|
||||
|
||||
* Discriminatory jokes and language.
|
||||
|
||||
* Posting sexually explicit or violent material.
|
||||
|
||||
* Posting (or threatening to post) other people's personally identifying
|
||||
information ("doxing").
|
||||
|
||||
* Personal insults, especially those using racist or sexist terms.
|
||||
|
||||
* Unwelcome sexual attention.
|
||||
|
||||
* Advocating for, or encouraging, any of the above behavior.
|
||||
|
||||
* Repeated harassment of others. In general, if someone asks you to stop, then
|
||||
stop.
|
||||
|
||||
* **When we disagree, try to understand why.**
|
||||
Disagreements, both social and technical, happen all the time and Sphinx is no
|
||||
exception. It is important that we resolve disagreements and differing views
|
||||
constructively. Remember that we’re different. Different people have different
|
||||
perspectives on issues. Being unable to understand why someone holds a
|
||||
viewpoint doesn’t mean that they’re wrong. Don’t forget that it is human to
|
||||
err and blaming each other doesn’t get us anywhere. Instead, focus on helping
|
||||
to resolve issues and learning from mistakes.
|
||||
|
||||
This isn’t an exhaustive list of things that you can’t do.
|
||||
Rather, take it in the spirit in which it’s intended - a guide to make it easier
|
||||
to enrich all of us and the technical communities in which we participate.
|
||||
This code of conduct applies to all spaces of the Sphinx community.
|
||||
|
||||
Attribution
|
||||
-----------
|
||||
|
||||
Original text courtesy of the Speak Up! project:
|
||||
http://web.archive.org/web/20141109123859/http://speakup.io/coc.html.
|
||||
|
@ -250,7 +250,7 @@ the source and the compiled catalogs.
|
||||
|
||||
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
|
||||
values for :confval:`language` in ``doc/config.rst``.
|
||||
values for :confval:`language` in ``doc/usage/configuration.rst``.
|
||||
|
||||
The Sphinx core messages can also be translated on `Transifex
|
||||
<https://www.transifex.com/>`_. There exists a client tool named ``tx`` in the
|
||||
@ -303,8 +303,8 @@ Debugging Tips
|
||||
* Set the debugging options in the `Docutils configuration file
|
||||
<http://docutils.sourceforge.net/docs/user/config.html>`_.
|
||||
|
||||
* JavaScript stemming algorithms in ``sphinx/search/*.py`` (except ``en.py``) are
|
||||
generated by this
|
||||
* JavaScript stemming algorithms in ``sphinx/search/*.py`` (except ``en.py``)
|
||||
are generated by this
|
||||
`modified snowballcode generator <https://github.com/shibukawa/snowball>`_.
|
||||
Generated `JSX <https://jsx.github.io/>`_ files are
|
||||
in `this repository <https://github.com/shibukawa/snowball-stemmer.jsx>`_.
|
||||
|
16
EXAMPLES
16
EXAMPLES
@ -52,7 +52,7 @@ Documentation using the classic theme
|
||||
* `Arb <http://arblib.org/>`__
|
||||
* `Bazaar <http://doc.bazaar.canonical.com/>`__ (customized)
|
||||
* `Beautiful Soup <https://www.crummy.com/software/BeautifulSoup/bs4/doc/>`__
|
||||
* `Blender <https://docs.blender.org/api/current/>`__
|
||||
* `Blender API <https://docs.blender.org/api/current/>`__
|
||||
* `Bugzilla <https://bugzilla.readthedocs.io/>`__
|
||||
* `Buildbot <https://docs.buildbot.net/latest/>`__
|
||||
* `CMake <https://cmake.org/documentation/>`__ (customized)
|
||||
@ -114,6 +114,7 @@ Documentation using the sphinxdoc theme
|
||||
* `ABRT <https://abrt.readthedocs.io/>`__
|
||||
* `cartopy <https://scitools.org.uk/cartopy/docs/latest/>`__
|
||||
* `Jython <http://www.jython.org/docs/>`__
|
||||
* `LLVM <https://llvm.org/docs/>`__
|
||||
* `Matplotlib <https://matplotlib.org/>`__
|
||||
* `MDAnalysis Tutorial <https://www.mdanalysis.org/MDAnalysisTutorial/>`__
|
||||
* `NetworkX <https://networkx.github.io/>`__
|
||||
@ -123,6 +124,7 @@ Documentation using the sphinxdoc theme
|
||||
* `Pysparse <http://pysparse.sourceforge.net/>`__
|
||||
* `PyTango <https://www.esrf.eu/computing/cs/tango/tango_doc/kernel_doc/pytango/latest/>`__
|
||||
* `Python Wild Magic <https://vmlaker.github.io/pythonwildmagic/>`__ (customized)
|
||||
* `RDKit <https://www.rdkit.org/docs/>`__
|
||||
* `Reteisi <http://www.reteisi.org/contents.html>`__ (customized)
|
||||
* `Sqlkit <http://sqlkit.argolinux.org/>`__ (customized)
|
||||
* `Turbulenz <http://docs.turbulenz.com/>`__
|
||||
@ -167,6 +169,7 @@ Documentation using sphinx_rtd_theme
|
||||
* `ASE <https://wiki.fysik.dtu.dk/ase/>`__
|
||||
* `Autofac <http://docs.autofac.org/>`__
|
||||
* `BigchainDB <https://docs.bigchaindb.com/>`__
|
||||
* `Blender Reference Manual <https://docs.blender.org/manual/>`__
|
||||
* `Blocks <https://blocks.readthedocs.io/>`__
|
||||
* `bootstrap-datepicker <https://bootstrap-datepicker.readthedocs.io/>`__
|
||||
* `Certbot <https://letsencrypt.readthedocs.io/>`__
|
||||
@ -180,17 +183,20 @@ Documentation using sphinx_rtd_theme
|
||||
* `Databricks <https://docs.databricks.com/>`__ (customized)
|
||||
* `Dataiku DSS <https://doc.dataiku.com/>`__
|
||||
* `DNF <https://dnf.readthedocs.io/>`__
|
||||
* `Django-cas-ng <https://djangocas.dev/docs/>`__
|
||||
* `edX <https://docs.edx.org/>`__
|
||||
* `Electrum <http://docs.electrum.org/>`__
|
||||
* `Elemental <http://libelemental.org/documentation/dev/>`__
|
||||
* `ESWP3 <https://eswp3.readthedocs.io/>`__
|
||||
* `Ethereum Homestead <http://www.ethdocs.org/>`__
|
||||
* `Exhale <https://exhale.readthedocs.io/>`__
|
||||
* `Faker <https://faker.readthedocs.io/>`__
|
||||
* `Fidimag <https://fidimag.readthedocs.io/>`__
|
||||
* `Flake8 <http://flake8.pycqa.org/>`__
|
||||
* `Flatpak <http://docs.flatpak.org/>`__
|
||||
* `FluidDyn <https://fluiddyn.readthedocs.io/>`__
|
||||
* `Fluidsim <https://fluidsim.readthedocs.io/>`__
|
||||
* `Gallium <https://gallium.readthedocs.io/>`__
|
||||
* `GeoNode <http://docs.geonode.org/>`__
|
||||
* `Glances <https://glances.readthedocs.io/>`__
|
||||
* `Godot <https://godot.readthedocs.io/>`__
|
||||
@ -206,11 +212,13 @@ Documentation using sphinx_rtd_theme
|
||||
* `Jupyter Notebook <https://jupyter-notebook.readthedocs.io/>`__
|
||||
* `Lasagne <https://lasagne.readthedocs.io/>`__
|
||||
* `latexindent.pl <https://latexindentpl.readthedocs.io/>`__
|
||||
* `Learning Apache Spark with Python <https://runawayhorse001.github.io/LearningApacheSpark>`__
|
||||
* `Linguistica <https://linguistica-uchicago.github.io/lxa5/>`__
|
||||
* `Linux kernel <https://www.kernel.org/doc/html/latest/index.html>`__
|
||||
* `Mailman <http://docs.list.org/>`__
|
||||
* `MathJax <https://docs.mathjax.org/>`__
|
||||
* `MDTraj <http://mdtraj.org/latest/>`__ (customized)
|
||||
* `MICrobial Community Analysis (micca) <http://micca.org/docs/latest/>`__
|
||||
* `micca - MICrobial Community Analysis <https://micca.readthedocs.io/>`__
|
||||
* `MicroPython <https://docs.micropython.org/>`__
|
||||
* `Minds <https://www.minds.org/docs/>`__ (customized)
|
||||
* `Mink <http://mink.behat.org/>`__
|
||||
@ -252,6 +260,7 @@ Documentation using sphinx_rtd_theme
|
||||
* `Sphinx AutoAPI <https://sphinx-autoapi.readthedocs.io/>`__
|
||||
* `sphinx-argparse <https://sphinx-argparse.readthedocs.io/>`__
|
||||
* `Sphinx-Gallery <https://sphinx-gallery.readthedocs.io/>`__ (customized)
|
||||
* `Sphinx with Github Webpages <https://runawayhorse001.github.io/SphinxGithub>`__
|
||||
* `SpotBugs <https://spotbugs.readthedocs.io/>`__
|
||||
* `StarUML <https://docs.staruml.io/>`__
|
||||
* `Sublime Text Unofficial Documentation <http://docs.sublimetext.info/>`__
|
||||
@ -285,6 +294,7 @@ Documentation using sphinx_bootstrap_theme
|
||||
* `Hedge <https://documen.tician.de/hedge/>`__
|
||||
* `ObsPy <https://docs.obspy.org/>`__
|
||||
* `Open Dylan <https://opendylan.org/documentation/>`__
|
||||
* `OPNFV <https://docs.opnfv.org/>`__
|
||||
* `Pootle <http://docs.translatehouse.org/projects/pootle/>`__
|
||||
* `PyUblas <https://documen.tician.de/pyublas/>`__
|
||||
* `seaborn <https://seaborn.pydata.org/>`__
|
||||
@ -321,6 +331,7 @@ Documentation using a custom theme or integrated in a website
|
||||
* `MongoDB <https://docs.mongodb.com/>`__
|
||||
* `Music21 <https://web.mit.edu/music21/doc/>`__
|
||||
* `MyHDL <http://docs.myhdl.org/>`__
|
||||
* `ndnSIM <https://ndnsim.net/current/>`__
|
||||
* `nose <https://nose.readthedocs.io/>`__
|
||||
* `ns-3 <https://www.nsnam.org/documentation/>`__
|
||||
* `NumPy <https://docs.scipy.org/doc/numpy/reference/>`__
|
||||
@ -394,6 +405,7 @@ Books produced using Sphinx
|
||||
* `"Python Professional Programming" (in Japanese) <http://www.amazon.co.jp/dp/4798032948/>`__
|
||||
* `"Python Professional Programming 2nd Edition" (in Japanese) <https://www.amazon.co.jp/dp/479804315X/>`__
|
||||
* `"Python Professional Programming 3rd Edition" (in Japanese) <https://www.amazon.co.jp/dp/4798053821/>`__
|
||||
* `Python Course by Yuri Petrov (Russian) <https://www.yuripetrov.ru/edu/python>`__
|
||||
* `"Real World HTTP -- Learning The Internet and Web Technology via its history and code (Japanese)" <https://www.oreilly.co.jp/books/9784873118048/>`__
|
||||
* `"Redmine Primer 5th Edition (in Japanese)" <https://www.shuwasystem.co.jp/products/7980html/4825.html>`__
|
||||
* `"The repoze.bfg Web Application Framework" <https://www.amazon.com/repoze-bfg-Web-Application-Framework-Version/dp/0615345379>`__
|
||||
|
4
Makefile
4
Makefile
@ -59,6 +59,10 @@ style-check:
|
||||
type-check:
|
||||
mypy sphinx
|
||||
|
||||
.PHONY: doclinter
|
||||
doclinter:
|
||||
python utils/doclinter.py CHANGES *.rst doc/
|
||||
|
||||
.PHONY: pylint
|
||||
pylint:
|
||||
@pylint --rcfile utils/pylintrc sphinx
|
||||
|
@ -26,6 +26,10 @@
|
||||
:target: https://codecov.io/gh/sphinx-doc/sphinx
|
||||
:alt: Code Coverage Status (Codecov)
|
||||
|
||||
.. image:: https://img.shields.io/badge/License-BSD%203--Clause-blue.svg
|
||||
:target: https://opensource.org/licenses/BSD-3-Clause
|
||||
:alt: BSD 3 Clause
|
||||
|
||||
Sphinx is a tool that makes it easy to create intelligent and beautiful
|
||||
documentation for Python projects (or other documents consisting of multiple
|
||||
reStructuredText sources), written by Georg Brandl. It was originally created
|
||||
@ -90,6 +94,10 @@ Get in touch
|
||||
.. _on GitHub: https://github.com/sphinx-doc/sphinx
|
||||
.. _mailing list: https://groups.google.com/forum/#!forum/sphinx-users
|
||||
|
||||
Please adhere to our `code of conduct`__.
|
||||
|
||||
__ http://www.sphinx-doc.org/en/master/code_of_conduct.html
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
|
@ -14,6 +14,13 @@ variable_end_string = %>
|
||||
block_start_string = <%
|
||||
block_end_string = %>
|
||||
|
||||
# Extraction from Jinja2 template files
|
||||
[jinja2: **/templates/latex/**.sty_t]
|
||||
variable_start_string = <%=
|
||||
variable_end_string = %>
|
||||
block_start_string = <%
|
||||
block_end_string = %>
|
||||
|
||||
# Extraction from Jinja2 HTML templates
|
||||
[jinja2: **/themes/**.html]
|
||||
encoding = utf-8
|
||||
|
4
doc/_static/Makefile
vendored
Normal file
4
doc/_static/Makefile
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
translation.png: translation.puml
|
||||
plantuml $<
|
||||
clean:
|
||||
rm translation.png
|
BIN
doc/_static/translation.png
vendored
BIN
doc/_static/translation.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 20 KiB |
16
doc/_static/translation.puml
vendored
Normal file
16
doc/_static/translation.puml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
@startuml
|
||||
file "SphinxProject"
|
||||
file ".rst"
|
||||
database ".pot"
|
||||
database ".po"
|
||||
database ".mo"
|
||||
actor translator
|
||||
file TranslatedBuild
|
||||
translator -l-> .po
|
||||
SphinxProject -r-> .rst
|
||||
.rst -r-> .pot : sphinx-build gettext
|
||||
.pot -r-> .po : Pootle
|
||||
.po -d-> .mo : msgfmt
|
||||
.mo -l-> TranslatedBuild
|
||||
.rst -d-> TranslatedBuild : "sphinx-buid -Dlanguage="
|
||||
@enduml
|
6
doc/_templates/index.html
vendored
6
doc/_templates/index.html
vendored
@ -97,6 +97,8 @@
|
||||
<p>{%trans%}A Japanese book about Sphinx has been published by O'Reilly:
|
||||
<a href="https://www.oreilly.co.jp/books/9784873116488/">Sphinxをはじめよう /
|
||||
Learning Sphinx</a>.{%endtrans%}</p>
|
||||
<p>{%trans%}In 2019 the second edition of a German book about Sphinx was published:
|
||||
<a href="https://literatur.hasecke.com/post/software-dokumentation-mit-sphinx/">Software-Dokumentation mit Sphinx</a>.{%endtrans%}</p>
|
||||
<!-- <p><img src="{{ pathto("_static/bookcover.png", 1) }}"/></p> -->
|
||||
|
||||
|
||||
@ -118,4 +120,8 @@
|
||||
<li>{%trans path=pathto("authors")%}<a href="{{ path }}">Sphinx Authors</a></li>{%endtrans%}
|
||||
</ul>
|
||||
|
||||
<h2>{%trans%}Code of Conduct{%endtrans%}</h2>
|
||||
|
||||
{%trans path=pathto("code_of_conduct")%}Please adhere to our <a href="{{ path }}">Code of Conduct</a>.{%endtrans%}
|
||||
|
||||
{% endblock %}
|
||||
|
2
doc/_themes/sphinx13/layout.html
vendored
2
doc/_themes/sphinx13/layout.html
vendored
@ -30,7 +30,7 @@
|
||||
.related { display: none; }
|
||||
{% endif %}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
// intelligent scrolling of the sidebar content
|
||||
$(window).scroll(function() {
|
||||
var sb = $('.sphinxsidebarwrapper');
|
||||
|
5
doc/_themes/sphinx13/static/sphinx13.css
vendored
5
doc/_themes/sphinx13/static/sphinx13.css
vendored
@ -299,6 +299,11 @@ a.headerlink:hover {
|
||||
color: white!important;
|
||||
}
|
||||
|
||||
/* avoid font-size when :mod: role in headings */
|
||||
h1 code, h2 code, h3 code, h4 code {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
cite, code, tt {
|
||||
font-family: 'Consolas', 'DejaVu Sans Mono',
|
||||
'Bitstream Vera Sans Mono', monospace;
|
||||
|
8
doc/code_of_conduct.rst
Normal file
8
doc/code_of_conduct.rst
Normal file
@ -0,0 +1,8 @@
|
||||
:tocdepth: 2
|
||||
|
||||
.. _code_of_conduct:
|
||||
|
||||
Sphinx Code of Conduct
|
||||
======================
|
||||
|
||||
.. include:: ../CODE_OF_CONDUCT
|
@ -7,7 +7,7 @@ import sphinx
|
||||
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.todo',
|
||||
'sphinx.ext.autosummary', 'sphinx.ext.extlinks',
|
||||
'sphinx.ext.viewcode']
|
||||
'sphinx.ext.viewcode', 'sphinx.ext.inheritance_diagram']
|
||||
|
||||
master_doc = 'contents'
|
||||
templates_path = ['_templates']
|
||||
@ -48,7 +48,7 @@ epub_fix_images = False
|
||||
epub_max_image_width = 0
|
||||
epub_show_urls = 'inline'
|
||||
epub_use_index = False
|
||||
epub_guide = (('toc', 'contents.xhtml', u'Table of Contents'),)
|
||||
epub_guide = (('toc', 'contents.xhtml', 'Table of Contents'),)
|
||||
epub_description = 'Sphinx documentation generator system manual'
|
||||
|
||||
latex_documents = [('contents', 'sphinx.tex', 'Sphinx Documentation',
|
||||
@ -146,6 +146,9 @@ def setup(app):
|
||||
app.add_object_type('confval', 'confval',
|
||||
objname='configuration value',
|
||||
indextemplate='pair: %s; configuration value')
|
||||
app.add_object_type('setuptools-confval', 'setuptools-confval',
|
||||
objname='setuptools configuration value',
|
||||
indextemplate='pair: %s; setuptools configuration value')
|
||||
fdesc = GroupedField('parameter', label='Parameters',
|
||||
names=['param'], can_collapse=True)
|
||||
app.add_object_type('event', 'event', 'pair: %s; event', parse_event,
|
||||
|
@ -34,6 +34,7 @@ Sphinx documentation contents
|
||||
changes
|
||||
examples
|
||||
authors
|
||||
code_of_conduct
|
||||
|
||||
|
||||
|
||||
|
@ -31,10 +31,12 @@ This is the current list of contributed extensions in that repository:
|
||||
- actdiag: embed activity diagrams by using actdiag_
|
||||
- adadomain: an extension for Ada support (Sphinx 1.0 needed)
|
||||
- ansi: parse ANSI color sequences inside documents
|
||||
- argdoc: automatically generate documentation for command-line arguments, descriptions, and help text
|
||||
- argdoc: automatically generate documentation for command-line arguments,
|
||||
descriptions and help text
|
||||
- astah: embed diagram by using astah
|
||||
- autoanysrc: Gather reST documentation from any source files
|
||||
- autorun: Execute code in a ``runblock`` directive
|
||||
- beamer_: A builder for Beamer (LaTeX) output.
|
||||
- blockdiag: embed block diagrams by using blockdiag_
|
||||
- cacoo: embed diagram from Cacoo
|
||||
- cf3domain: a domain for CFEngine 3 policies
|
||||
@ -45,7 +47,8 @@ This is the current list of contributed extensions in that repository:
|
||||
- coffeedomain: a domain for (auto)documenting CoffeeScript source code
|
||||
- context: a builder for ConTeXt
|
||||
- disqus: embed Disqus comments in documents
|
||||
- documentedlist: converts a Python list to a table in the generated documentation
|
||||
- documentedlist: converts a Python list to a table in the generated
|
||||
documentation
|
||||
- doxylink: Link to external Doxygen-generated HTML documentation
|
||||
- domaintools_: A tool for easy domain creation
|
||||
- email: obfuscate email addresses
|
||||
@ -64,7 +67,8 @@ This is the current list of contributed extensions in that repository:
|
||||
- imgur: embed Imgur images, albums, and metadata in documents
|
||||
- inlinesyntaxhighlight_: inline syntax highlighting
|
||||
- lassodomain: a domain for documenting Lasso_ source code
|
||||
- libreoffice: an extension to include any drawing supported by LibreOffice (e.g. odg, vsd, ...)
|
||||
- libreoffice: an extension to include any drawing supported by LibreOffice
|
||||
(e.g. odg, vsd, ...)
|
||||
- lilypond: an extension inserting music scripts from Lilypond_ in PNG format
|
||||
- makedomain_: a domain for `GNU Make`_
|
||||
- matlabdomain: document MATLAB_ code
|
||||
@ -74,7 +78,8 @@ This is the current list of contributed extensions in that repository:
|
||||
- nicovideo: embed videos from nicovideo
|
||||
- nwdiag: embed network diagrams by using nwdiag_
|
||||
- omegat: support tools to collaborate with OmegaT_ (Sphinx 1.1 needed)
|
||||
- osaka: convert standard Japanese doc to Osaka dialect (this is a joke extension)
|
||||
- osaka: convert standard Japanese doc to Osaka dialect (this is a joke
|
||||
extension)
|
||||
- paverutils: an alternate integration of Sphinx with Paver_
|
||||
- phpdomain: an extension for PHP support
|
||||
- plantuml: embed UML diagram by using PlantUML_
|
||||
@ -94,14 +99,15 @@ This is the current list of contributed extensions in that repository:
|
||||
- sword: an extension inserting Bible verses from Sword_
|
||||
- tikz: draw pictures with the `TikZ/PGF LaTeX package`_
|
||||
- traclinks: create TracLinks_ to a Trac_ instance from within Sphinx
|
||||
- versioning: Sphinx extension that allows building versioned docs for self-hosting
|
||||
- versioning: Sphinx extension that allows building versioned docs for
|
||||
self-hosting
|
||||
- whooshindex: whoosh indexer extension
|
||||
- youtube: embed videos from YouTube_
|
||||
- zopeext: provide an ``autointerface`` directive for using `Zope interfaces`_
|
||||
|
||||
|
||||
See the :doc:`extension tutorials <../development/tutorials/index>` on getting started with writing your
|
||||
own extensions.
|
||||
See the :doc:`extension tutorials <../development/tutorials/index>` on getting
|
||||
started with writing your own extensions.
|
||||
|
||||
|
||||
.. _aafigure: https://launchpad.net/aafigure
|
||||
@ -143,3 +149,4 @@ own extensions.
|
||||
.. _domaintools: https://bitbucket.org/klorenz/sphinxcontrib-domaintools
|
||||
.. _restbuilder: https://pypi.org/project/sphinxcontrib-restbuilder/
|
||||
.. _Lasso: http://www.lassosoft.com/
|
||||
.. _beamer: https://pypi.org/project/sphinxcontrib-beamer/
|
||||
|
@ -77,7 +77,7 @@ create directives should extend this class.
|
||||
|
||||
.. seealso::
|
||||
|
||||
`The docutils documentation on creating directives <docutils directives>`_
|
||||
`The docutils documentation on creating directives <docutils directives_>`_
|
||||
|
||||
This class contains a ``run`` method. This method is a requirement and it is
|
||||
part of every directive. It contains the main logic of the directive and it
|
||||
@ -87,7 +87,7 @@ nodes available: text, paragraph, reference, table, etc.
|
||||
|
||||
.. seealso::
|
||||
|
||||
`The docutils documentation on nodes <docutils nodes>`_
|
||||
`The docutils documentation on nodes <docutils nodes_>`_
|
||||
|
||||
The ``nodes.paragraph`` class creates a new paragraph node. A paragraph
|
||||
node typically contains some text that we can set during instantiation using
|
||||
|
@ -23,8 +23,8 @@ We want the extension to add the following to Sphinx:
|
||||
only shown in the output if a new config value is set. Todo entries should not
|
||||
be in the output by default.
|
||||
|
||||
* A ``todolist`` directive that creates a list of all todo entries throughout the
|
||||
documentation.
|
||||
* A ``todolist`` directive that creates a list of all todo entries throughout
|
||||
the documentation.
|
||||
|
||||
For that, we will need to add the following elements to Sphinx:
|
||||
|
||||
@ -107,6 +107,20 @@ is just a "general" node.
|
||||
<http://docutils.sourceforge.net/docs/ref/doctree.html>`__ and :ref:`Sphinx
|
||||
<nodes>`.
|
||||
|
||||
.. attention::
|
||||
|
||||
It is important to know that while you can extend Sphinx without
|
||||
leaving your ``conf.py``, if you declare an inherited node right
|
||||
there, you'll hit an unobvious :py:class:`PickleError`. So if
|
||||
something goes wrong, please make sure that you put inherited nodes
|
||||
into a separate Python module.
|
||||
|
||||
For more details, see:
|
||||
|
||||
- https://github.com/sphinx-doc/sphinx/issues/6751
|
||||
- https://github.com/sphinx-doc/sphinx/issues/1493
|
||||
- https://github.com/sphinx-doc/sphinx/issues/1424
|
||||
|
||||
.. rubric:: The directive classes
|
||||
|
||||
A directive class is a class deriving usually from
|
||||
|
@ -54,8 +54,6 @@ package.
|
||||
|
||||
.. automethod:: Sphinx.add_domain(domain)
|
||||
|
||||
.. automethod:: Sphinx.override_domain(domain)
|
||||
|
||||
.. method:: Sphinx.add_directive_to_domain(domain, name, func, content, arguments, \*\*options)
|
||||
.. automethod:: Sphinx.add_directive_to_domain(domain, name, directiveclass)
|
||||
|
||||
@ -147,9 +145,9 @@ Sphinx core events
|
||||
------------------
|
||||
|
||||
These events are known to the core. The arguments shown are given to the
|
||||
registered event handlers. Use :meth:`.connect` in an extension's ``setup``
|
||||
function (note that ``conf.py`` can also have a ``setup`` function) to connect
|
||||
handlers to the events. Example:
|
||||
registered event handlers. Use :meth:`.Sphinx.connect` in an extension's
|
||||
``setup`` function (note that ``conf.py`` can also have a ``setup`` function) to
|
||||
connect handlers to the events. Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@ -218,6 +216,14 @@ handlers to the events. Example:
|
||||
|
||||
.. versionadded:: 0.5
|
||||
|
||||
.. event:: object-description-transform (app, domain, objtype, contentnode)
|
||||
|
||||
Emitted when an object description directive has run. The *domain* and
|
||||
*objtype* arguments are strings indicating object description of the object.
|
||||
And *contentnode* is a content for the object. It can be modified in-place.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
.. event:: doctree-read (app, doctree)
|
||||
|
||||
Emitted when a doctree has been parsed and read by the environment, and is
|
||||
|
@ -38,3 +38,8 @@ Builder API
|
||||
.. automethod:: write_doc
|
||||
.. automethod:: finish
|
||||
|
||||
**Attributes**
|
||||
|
||||
.. attribute:: events
|
||||
|
||||
An :class:`.EventManager` object.
|
||||
|
1336
doc/extdev/deprecated.rst
Normal file
1336
doc/extdev/deprecated.rst
Normal file
File diff suppressed because it is too large
Load Diff
@ -27,6 +27,10 @@ Build environment API
|
||||
|
||||
Directory for storing pickled doctrees.
|
||||
|
||||
.. attribute:: events
|
||||
|
||||
An :class:`.EventManager` object.
|
||||
|
||||
.. attribute:: found_docs
|
||||
|
||||
A set of all existing docnames.
|
||||
|
@ -15,3 +15,83 @@ i18n API
|
||||
|
||||
.. autofunction:: __
|
||||
|
||||
|
||||
.. _ext-i18n:
|
||||
|
||||
Extension internationalization (`i18n`) and localization (`l10n`) using i18n API
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
.. versionadded:: 1.8
|
||||
|
||||
An extension may naturally come with message translations. This is briefly
|
||||
summarized in :func:`sphinx.locale.get_translation` help.
|
||||
|
||||
In practice, you have to:
|
||||
|
||||
#. Choose a name for your message catalog, which must be unique. Usually
|
||||
the name of your extension is used for the name of message catalog.
|
||||
|
||||
#. Mark in your extension sources all messages as translatable, via
|
||||
:func:`sphinx.locale.get_translation` function, usually renamed ``_()``,
|
||||
e.g.:
|
||||
|
||||
.. code-block:: python
|
||||
:caption: src/__init__.py
|
||||
|
||||
from sphinx.locale import get_translation
|
||||
|
||||
MESSAGE_CATALOG_NAME = 'myextension'
|
||||
_ = get_translation(MESSAGE_CATALOG_NAME)
|
||||
|
||||
translated_text = _('Hello Sphinx!')
|
||||
|
||||
#. Set up your extension to be aware of its dedicated translations:
|
||||
|
||||
.. code-block:: python
|
||||
:caption: src/__init__.py
|
||||
|
||||
def setup(app):
|
||||
package_dir = path.abspath(path.dirname(__file__))
|
||||
locale_dir = os.path.join(package_dir, 'locales')
|
||||
app.add_message_catalog(MESSAGE_CATALOG_NAME, locale_dir)
|
||||
|
||||
#. Generate message catalog template ``*.pot`` file, usually in ``locale/``
|
||||
source directory, for example via `Babel`_:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pybabel extract --output=src/locale/myextension.pot src/
|
||||
|
||||
#. Create message catalogs (``*.po``) for each language which your extension
|
||||
will provide localization, for example via `Babel`_:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pybabel init --input-file=src/locale/myextension.pot --domain=myextension --output-dir=src/locale --locale=fr_FR
|
||||
|
||||
#. Translate message catalogs for each language manually
|
||||
|
||||
#. Compile message catalogs into ``*.mo`` files, for example via `Babel`_:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pybabel compile --directory=src/locale --domain=myextension
|
||||
|
||||
#. Ensure that message catalog files are distributed when your package will
|
||||
be installed, by adding equivalent line in your extension ``MANIFEST.in``:
|
||||
|
||||
.. code-block:: ini
|
||||
:caption: MANIFEST.in
|
||||
|
||||
recursive-include src *.pot *.po *.mo
|
||||
|
||||
|
||||
When the messages on your extension has been changed, you need to also update
|
||||
message catalog template and message catalogs, for example via `Babel`_:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ pybabel extract --output=src/locale/myextension.pot src/
|
||||
$ pybabel update --input-file=src/locale/myextension.pot --domain=myextension --output-dir=src/locale
|
||||
|
||||
.. _Babel: http://babel.pocoo.org/
|
||||
|
@ -97,7 +97,8 @@ extension. These are:
|
||||
|
||||
The config is available as ``app.config`` or ``env.config``.
|
||||
|
||||
To see an example of use of these objects, refer to :doc:`../development/tutorials/index`.
|
||||
To see an example of use of these objects, refer to
|
||||
:doc:`../development/tutorials/index`.
|
||||
|
||||
.. _build-phases:
|
||||
|
||||
@ -143,9 +144,9 @@ in which a Sphinx project is built: this works in several phases.
|
||||
|
||||
Now that the metadata and cross-reference data of all existing documents is
|
||||
known, all temporary nodes are replaced by nodes that can be converted into
|
||||
output using components called transforms. For example, links are created for
|
||||
object references that exist, and simple literal nodes are created for those
|
||||
that don't.
|
||||
output using components called transforms. For example, links are created
|
||||
for object references that exist, and simple literal nodes are created for
|
||||
those that don't.
|
||||
|
||||
**Phase 4: Writing**
|
||||
|
||||
@ -187,6 +188,7 @@ as metadata of the extension. Metadata keys currently recognized are:
|
||||
output files can be used when the extension is loaded. Since extensions
|
||||
usually don't negatively influence the process, this defaults to ``True``.
|
||||
|
||||
|
||||
APIs used for writing extensions
|
||||
--------------------------------
|
||||
|
||||
@ -205,931 +207,4 @@ APIs used for writing extensions
|
||||
logging
|
||||
i18n
|
||||
utils
|
||||
|
||||
.. _dev-deprecated-apis:
|
||||
|
||||
Deprecated APIs
|
||||
---------------
|
||||
|
||||
On developing Sphinx, we are always careful to the compatibility of our APIs.
|
||||
But, sometimes, the change of interface are needed for some reasons. In such
|
||||
cases, we've marked them as deprecated. And they are kept during the two
|
||||
major versions (for more details, please see :ref:`deprecation-policy`).
|
||||
|
||||
The following is a list of deprecated interfaces.
|
||||
|
||||
.. tabularcolumns:: |>{\raggedright}\Y{.4}|>{\centering}\Y{.1}|>{\centering}\Y{.12}|>{\raggedright\arraybackslash}\Y{.38}|
|
||||
|
||||
.. |LaTeXHyphenate| raw:: latex
|
||||
|
||||
\hspace{0pt}
|
||||
|
||||
.. list-table:: deprecated APIs
|
||||
:header-rows: 1
|
||||
:class: deprecated
|
||||
:widths: 40, 10, 10, 40
|
||||
|
||||
* - Target
|
||||
- |LaTeXHyphenate|\ Deprecated
|
||||
- (will be) Removed
|
||||
- Alternatives
|
||||
|
||||
* - ``sphinx.ext.autodoc.importer.MockFinder``
|
||||
- 2.1
|
||||
- 4.0
|
||||
- ``sphinx.ext.autodoc.mock.MockFinder``
|
||||
|
||||
* - ``sphinx.ext.autodoc.importer.MockLoader``
|
||||
- 2.1
|
||||
- 4.0
|
||||
- ``sphinx.ext.autodoc.mock.MockLoader``
|
||||
|
||||
* - ``sphinx.ext.autodoc.importer.mock()``
|
||||
- 2.1
|
||||
- 4.0
|
||||
- ``sphinx.ext.autodoc.mock.mock()``
|
||||
|
||||
* - ``sphinx.ext.autosummary.autolink_role()``
|
||||
- 2.1
|
||||
- 4.0
|
||||
- ``sphinx.ext.autosummary.AutoLink``
|
||||
|
||||
* - ``sphinx.util.i18n.find_catalog()``
|
||||
- 2.1
|
||||
- 4.0
|
||||
- ``sphinx.util.i18n.docname_to_domain()``
|
||||
|
||||
* - ``sphinx.util.i18n.find_catalog_files()``
|
||||
- 2.1
|
||||
- 4.0
|
||||
- ``sphinx.util.i18n.CatalogRepository``
|
||||
|
||||
* - ``sphinx.util.i18n.find_catalog_source_files()``
|
||||
- 2.1
|
||||
- 4.0
|
||||
- ``sphinx.util.i18n.CatalogRepository``
|
||||
|
||||
* - ``encoding`` argument of ``autodoc.Documenter.get_doc()``,
|
||||
``autodoc.DocstringSignatureMixin.get_doc()``,
|
||||
``autodoc.DocstringSignatureMixin._find_signature()``, and
|
||||
``autodoc.ClassDocumenter.get_doc()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - arguments of ``EpubBuilder.build_mimetype()``,
|
||||
``EpubBuilder.build_container()``, ``EpubBuilder.build_content()``,
|
||||
``EpubBuilder.build_toc()`` and ``EpubBuilder.build_epub()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - arguments of ``Epub3Builder.build_navigation_doc()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``nodetype`` argument of
|
||||
``sphinx.search.WordCollector.is_meta_keywords()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``suffix`` argument of ``BuildEnvironment.doc2path()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - string style ``base`` argument of ``BuildEnvironment.doc2path()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``os.path.join()``
|
||||
|
||||
* - ``sphinx.addnodes.abbreviation``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``docutils.nodes.abbreviation``
|
||||
|
||||
* - ``sphinx.builders.applehelp``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinxcontrib.applehelp``
|
||||
|
||||
* - ``sphinx.builders.devhelp``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinxcontrib.devhelp``
|
||||
|
||||
* - ``sphinx.builders.epub3.Epub3Builder.validate_config_value()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.builders.epub3.validate_config_values()``
|
||||
|
||||
* - ``sphinx.builders.html.JSONHTMLBuilder``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.builders.serializinghtml.JSONHTMLBuilder``
|
||||
|
||||
* - ``sphinx.builders.html.PickleHTMLBuilder``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.builders.serializinghtml.PickleHTMLBuilder``
|
||||
|
||||
* - ``sphinx.builders.html.SerializingHTMLBuilder``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.builders.serializinghtml.SerializingHTMLBuilder``
|
||||
|
||||
* - ``sphinx.builders.html.SingleFileHTMLBuilder``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.builders.singlehtml.SingleFileHTMLBuilder``
|
||||
|
||||
* - ``sphinx.builders.html.WebHTMLBuilder``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.builders.serializinghtml.PickleHTMLBuilder``
|
||||
|
||||
* - ``sphinx.builders.htmlhelp``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinxcontrib.htmlhelp``
|
||||
|
||||
* - ``sphinx.builders.htmlhelp.HTMLHelpBuilder.open_file()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``open()``
|
||||
|
||||
* - ``sphinx.builders.qthelp``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinxcontrib.qthelp``
|
||||
|
||||
* - ``sphinx.cmd.quickstart.term_decode()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.cmd.quickstart.TERM_ENCODING``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sys.stdin.encoding``
|
||||
|
||||
* - ``sphinx.config.check_unicode()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.config.string_classes``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``[str]``
|
||||
|
||||
* - ``sphinx.domains.cpp.DefinitionError.description``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``str(exc)``
|
||||
|
||||
* - ``sphinx.domains.cpp.NoOldIdError.description``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``str(exc)``
|
||||
|
||||
* - ``sphinx.domains.cpp.UnsupportedMultiCharacterCharLiteral.decoded``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``str(exc)``
|
||||
|
||||
* - ``sphinx.ext.autosummary.Autosummary.warn()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.ext.autosummary.Autosummary.genopt``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.ext.autosummary.Autosummary.warnings``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.ext.autosummary.Autosummary.result``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.ext.doctest.doctest_encode()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.ext.jsmath``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinxcontrib.jsmath``
|
||||
|
||||
* - ``sphinx.roles.abbr_role()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.roles.Abbreviation``
|
||||
|
||||
* - ``sphinx.roles.emph_literal_role()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.roles.EmphasizedLiteral``
|
||||
|
||||
* - ``sphinx.roles.menusel_role()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.roles.GUILabel`` or ``sphinx.roles.MenuSelection``
|
||||
|
||||
* - ``sphinx.roles.index_role()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.roles.Index``
|
||||
|
||||
* - ``sphinx.roles.indexmarkup_role()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.roles.PEP`` or ``sphinx.roles.RFC``
|
||||
|
||||
* - ``sphinx.testing.util.remove_unicode_literal()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.util.attrdict``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.util.force_decode()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.util.get_matching_docs()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.util.get_matching_files()``
|
||||
|
||||
* - ``sphinx.util.inspect.Parameter``
|
||||
- 2.0
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.util.jsonimpl``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinxcontrib.serializinghtml.jsonimpl``
|
||||
|
||||
* - ``sphinx.util.osutil.EEXIST``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``errno.EEXIST`` or ``FileExistsError``
|
||||
|
||||
* - ``sphinx.util.osutil.EINVAL``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``errno.EINVAL``
|
||||
|
||||
* - ``sphinx.util.osutil.ENOENT``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``errno.ENOENT`` or ``FileNotFoundError``
|
||||
|
||||
* - ``sphinx.util.osutil.EPIPE``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``errno.ENOENT`` or ``BrokenPipeError``
|
||||
|
||||
* - ``sphinx.util.osutil.walk()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``os.walk()``
|
||||
|
||||
* - ``sphinx.util.pycompat.NoneType``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.util.typing.NoneType``
|
||||
|
||||
* - ``sphinx.util.pycompat.TextIOWrapper``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``io.TextIOWrapper``
|
||||
|
||||
* - ``sphinx.util.pycompat.UnicodeMixin``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.util.pycompat.htmlescape()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``html.escape()``
|
||||
|
||||
* - ``sphinx.util.pycompat.indent()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``textwrap.indent()``
|
||||
|
||||
* - ``sphinx.util.pycompat.sys_encoding``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sys.getdefaultencoding()``
|
||||
|
||||
* - ``sphinx.util.pycompat.terminal_safe()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.util.console.terminal_safe()``
|
||||
|
||||
* - ``sphinx.util.pycompat.u``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.util.PeekableIterator``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - Omitting the ``filename`` argument in an overriddent
|
||||
``IndexBuilder.feed()`` method.
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``IndexBuilder.feed(docname, filename, title, doctree)``
|
||||
|
||||
* - ``sphinx.writers.latex.ExtBabel``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``sphinx.builders.latex.util.ExtBabel``
|
||||
|
||||
* - ``sphinx.writers.latex.LaTeXTranslator.babel_defmacro()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.application.Sphinx._setting_up_extension``
|
||||
- 2.0
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - The ``importer`` argument of ``sphinx.ext.autodoc.importer._MockModule``
|
||||
- 2.0
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.ext.autodoc.importer._MockImporter``
|
||||
- 2.0
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.io.SphinxBaseFileInput``
|
||||
- 2.0
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.io.SphinxFileInput.supported``
|
||||
- 2.0
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.io.SphinxRSTFileInput``
|
||||
- 2.0
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.registry.SphinxComponentRegistry.add_source_input()``
|
||||
- 2.0
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.LaTeXTranslator._make_visit_admonition()``
|
||||
- 2.0
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.LaTeXTranslator.collect_footnotes()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.texinfo.TexinfoTranslator._make_visit_admonition()``
|
||||
- 2.0
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.text.TextTranslator._make_depart_admonition()``
|
||||
- 2.0
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.LaTeXTranslator.generate_numfig_format()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - :rst:dir:`highlightlang`
|
||||
- 1.8
|
||||
- 4.0
|
||||
- :rst:dir:`highlight`
|
||||
|
||||
* - :meth:`~sphinx.application.Sphinx.add_stylesheet()`
|
||||
- 1.8
|
||||
- 4.0
|
||||
- :meth:`~sphinx.application.Sphinx.add_css_file()`
|
||||
|
||||
* - :meth:`~sphinx.application.Sphinx.add_javascript()`
|
||||
- 1.8
|
||||
- 4.0
|
||||
- :meth:`~sphinx.application.Sphinx.add_js_file()`
|
||||
|
||||
* - :confval:`autodoc_default_flags`
|
||||
- 1.8
|
||||
- 4.0
|
||||
- :confval:`autodoc_default_options`
|
||||
|
||||
* - ``content`` arguments of ``sphinx.util.image.guess_mimetype()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``gettext_compact`` arguments of
|
||||
``sphinx.util.i18n.find_catalog_source_files()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.io.SphinxI18nReader.set_lineno_for_reporter()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.io.SphinxI18nReader.line``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.directives.other.VersionChanges``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.domains.changeset.VersionChanges``
|
||||
|
||||
* - ``sphinx.highlighting.PygmentsBridge.unhighlight()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``trim_doctest_flags`` arguments of
|
||||
``sphinx.highlighting.PygmentsBridge``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.ext.mathbase``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.ext.mathbase.MathDomain``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.domains.math.MathDomain``
|
||||
|
||||
* - ``sphinx.ext.mathbase.MathDirective``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.directives.patches.MathDirective``
|
||||
|
||||
* - ``sphinx.ext.mathbase.math_role()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``docutils.parsers.rst.roles.math_role()``
|
||||
|
||||
* - ``sphinx.ext.mathbase.setup_math()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- :meth:`~sphinx.application.Sphinx.add_html_math_renderer()`
|
||||
|
||||
* - ``sphinx.ext.mathbase.is_in_section_title()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.ext.mathbase.get_node_equation_number()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.util.math.get_node_equation_number()``
|
||||
|
||||
* - ``sphinx.ext.mathbase.wrap_displaymath()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.util.math.wrap_displaymath()``
|
||||
|
||||
* - ``sphinx.ext.mathbase.math`` (node)
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``docutils.nodes.math``
|
||||
|
||||
* - ``sphinx.ext.mathbase.displaymath`` (node)
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``docutils.nodes.math_block``
|
||||
|
||||
* - ``sphinx.ext.mathbase.eqref`` (node)
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.builders.latex.nodes.math_reference``
|
||||
|
||||
* - ``viewcode_import`` (config value)
|
||||
- 1.8
|
||||
- 3.0
|
||||
- :confval:`viewcode_follow_imported_members`
|
||||
|
||||
* - ``sphinx.writers.latex.Table.caption_footnotetexts``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.Table.header_footnotetexts``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.LaTeXTranslator.footnotestack``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.LaTeXTranslator.in_container_literal_block``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.LaTeXTranslator.next_section_ids``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.LaTeXTranslator.next_hyperlink_ids``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.LaTeXTranslator.restrict_footnote()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.LaTeXTranslator.unrestrict_footnote()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.LaTeXTranslator.push_hyperlink_ids()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.LaTeXTranslator.pop_hyperlink_ids()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.LaTeXTranslator.bibitems``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.LaTeXTranslator.hlsettingstack``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.ExtBabel.get_shorthandoff()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.html.HTMLTranslator.highlightlang()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.html.HTMLTranslator.highlightlang_base()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.html.HTMLTranslator.highlightlangopts()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.html.HTMLTranslator.highlightlinenothreshold()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.html5.HTMLTranslator.highlightlang()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.html5.HTMLTranslator.highlightlang_base()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.html5.HTMLTranslator.highlightlangopts()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.html5.HTMLTranslator.highlightlinenothreshold()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.writers.latex.LaTeXTranslator.check_latex_elements()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- Nothing
|
||||
|
||||
* - ``sphinx.application.CONFIG_FILENAME``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.config.CONFIG_FILENAME``
|
||||
|
||||
* - ``Config.check_unicode()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.config.check_unicode()``
|
||||
|
||||
* - ``Config.check_types()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.config.check_confval_types()``
|
||||
|
||||
* - ``dirname``, ``filename`` and ``tags`` arguments of
|
||||
``Config.__init__()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``Config.read()``
|
||||
|
||||
* - The value of :confval:`html_search_options`
|
||||
- 1.8
|
||||
- 3.0
|
||||
- see :confval:`html_search_options`
|
||||
|
||||
* - ``sphinx.versioning.prepare()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.versioning.UIDTransform``
|
||||
|
||||
* - ``Sphinx.override_domain()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- :meth:`~sphinx.application.Sphinx.add_domain()`
|
||||
|
||||
* - ``Sphinx.import_object()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.util.import_object()``
|
||||
|
||||
* - ``suffix`` argument of
|
||||
:meth:`~sphinx.application.Sphinx.add_source_parser()`
|
||||
- 1.8
|
||||
- 3.0
|
||||
- :meth:`~sphinx.application.Sphinx.add_source_suffix()`
|
||||
|
||||
|
||||
* - ``BuildEnvironment.load()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``pickle.load()``
|
||||
|
||||
* - ``BuildEnvironment.loads()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``pickle.loads()``
|
||||
|
||||
* - ``BuildEnvironment.frompickle()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``pickle.load()``
|
||||
|
||||
* - ``BuildEnvironment.dump()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``pickle.dump()``
|
||||
|
||||
* - ``BuildEnvironment.dumps()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``pickle.dumps()``
|
||||
|
||||
* - ``BuildEnvironment.topickle()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``pickle.dump()``
|
||||
|
||||
* - ``BuildEnvironment._nitpick_ignore``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- :confval:`nitpick_ignore`
|
||||
|
||||
* - ``BuildEnvironment.versionchanges``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``BuildEnvironment.update()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``Builder.read()``
|
||||
|
||||
* - ``BuildEnvironment.read_doc()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``Builder.read_doc()``
|
||||
|
||||
* - ``BuildEnvironment._read_serial()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``Builder.read()``
|
||||
|
||||
* - ``BuildEnvironment._read_parallel()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``Builder.read()``
|
||||
|
||||
* - ``BuildEnvironment.write_doctree()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``Builder.write_doctree()``
|
||||
|
||||
* - ``BuildEnvironment.note_versionchange()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``ChangesDomain.note_changeset()``
|
||||
|
||||
* - ``warn()`` (template helper function)
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``warning()``
|
||||
|
||||
* - :confval:`source_parsers`
|
||||
- 1.8
|
||||
- 3.0
|
||||
- :meth:`~sphinx.application.Sphinx.add_source_parser()`
|
||||
|
||||
* - ``sphinx.util.docutils.directive_helper()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``Directive`` class of docutils
|
||||
|
||||
* - ``sphinx.cmdline``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.cmd.build``
|
||||
|
||||
* - ``sphinx.make_mode``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.cmd.make_mode``
|
||||
|
||||
* - ``sphinx.locale.l_()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- :func:`sphinx.locale._()`
|
||||
|
||||
* - ``sphinx.locale.lazy_gettext()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- :func:`sphinx.locale._()`
|
||||
|
||||
* - ``sphinx.locale.mygettext()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- :func:`sphinx.locale._()`
|
||||
|
||||
* - ``sphinx.util.copy_static_entry()``
|
||||
- 1.5
|
||||
- 3.0
|
||||
- ``sphinx.util.fileutil.copy_asset()``
|
||||
|
||||
* - ``sphinx.build_main()``
|
||||
- 1.7
|
||||
- 2.0
|
||||
- ``sphinx.cmd.build.build_main()``
|
||||
|
||||
* - ``sphinx.ext.intersphinx.debug()``
|
||||
- 1.7
|
||||
- 2.0
|
||||
- ``sphinx.ext.intersphinx.inspect_main()``
|
||||
|
||||
* - ``sphinx.ext.autodoc.format_annotation()``
|
||||
- 1.7
|
||||
- 2.0
|
||||
- ``sphinx.util.inspect.Signature``
|
||||
|
||||
* - ``sphinx.ext.autodoc.formatargspec()``
|
||||
- 1.7
|
||||
- 2.0
|
||||
- ``sphinx.util.inspect.Signature``
|
||||
|
||||
* - ``sphinx.ext.autodoc.AutodocReporter``
|
||||
- 1.7
|
||||
- 2.0
|
||||
- ``sphinx.util.docutils.switch_source_input()``
|
||||
|
||||
* - ``sphinx.ext.autodoc.add_documenter()``
|
||||
- 1.7
|
||||
- 2.0
|
||||
- :meth:`~sphinx.application.Sphinx.add_autodocumenter()`
|
||||
|
||||
* - ``sphinx.ext.autodoc.AutoDirective._register``
|
||||
- 1.7
|
||||
- 2.0
|
||||
- :meth:`~sphinx.application.Sphinx.add_autodocumenter()`
|
||||
|
||||
* - ``AutoDirective._special_attrgetters``
|
||||
- 1.7
|
||||
- 2.0
|
||||
- :meth:`~sphinx.application.Sphinx.add_autodoc_attrgetter()`
|
||||
|
||||
* - ``Sphinx.warn()``, ``Sphinx.info()``
|
||||
- 1.6
|
||||
- 2.0
|
||||
- :ref:`logging-api`
|
||||
|
||||
* - ``BuildEnvironment.set_warnfunc()``
|
||||
- 1.6
|
||||
- 2.0
|
||||
- :ref:`logging-api`
|
||||
|
||||
* - ``BuildEnvironment.note_toctree()``
|
||||
- 1.6
|
||||
- 2.0
|
||||
- ``Toctree.note()`` (in ``sphinx.environment.adapters.toctree``)
|
||||
|
||||
* - ``BuildEnvironment.get_toc_for()``
|
||||
- 1.6
|
||||
- 2.0
|
||||
- ``Toctree.get_toc_for()`` (in ``sphinx.environment.adapters.toctree``)
|
||||
|
||||
* - ``BuildEnvironment.get_toctree_for()``
|
||||
- 1.6
|
||||
- 2.0
|
||||
- ``Toctree.get_toctree_for()`` (in ``sphinx.environment.adapters.toctree``)
|
||||
|
||||
* - ``BuildEnvironment.create_index()``
|
||||
- 1.6
|
||||
- 2.0
|
||||
- ``IndexEntries.create_index()`` (in ``sphinx.environment.adapters.indexentries``)
|
||||
|
||||
* - ``sphinx.websupport``
|
||||
- 1.6
|
||||
- 2.0
|
||||
- `sphinxcontrib-websupport <https://pypi.org/project/sphinxcontrib-websupport/>`_
|
||||
|
||||
* - ``StandaloneHTMLBuilder.css_files``
|
||||
- 1.6
|
||||
- 2.0
|
||||
- :meth:`~sphinx.application.Sphinx.add_stylesheet()`
|
||||
|
||||
* - ``document.settings.gettext_compact``
|
||||
- 1.8
|
||||
- 1.8
|
||||
- :confval:`gettext_compact`
|
||||
|
||||
* - ``Sphinx.status_iterator()``
|
||||
- 1.6
|
||||
- 1.7
|
||||
- ``sphinx.util.status_iterator()``
|
||||
|
||||
* - ``Sphinx.old_status_iterator()``
|
||||
- 1.6
|
||||
- 1.7
|
||||
- ``sphinx.util.old_status_iterator()``
|
||||
|
||||
* - ``Sphinx._directive_helper()``
|
||||
- 1.6
|
||||
- 1.7
|
||||
- ``sphinx.util.docutils.directive_helper()``
|
||||
|
||||
* - ``sphinx.util.compat.Directive``
|
||||
- 1.6
|
||||
- 1.7
|
||||
- ``docutils.parsers.rst.Directive``
|
||||
|
||||
* - ``sphinx.util.compat.docutils_version``
|
||||
- 1.6
|
||||
- 1.7
|
||||
- ``sphinx.util.docutils.__version_info__``
|
||||
|
||||
.. note:: On deprecating on public APIs (internal functions and classes),
|
||||
we also follow the policy as much as possible.
|
||||
deprecated
|
||||
|
@ -56,8 +56,8 @@ Logging API
|
||||
:meth:`SphinxLoggerAdapter.warning`.
|
||||
|
||||
**color**
|
||||
The color of logs. By default, info and verbose level logs are not colored,
|
||||
and debug level ones are colored as ``"darkgray"``.
|
||||
The color of logs. By default, info and verbose level logs are not
|
||||
colored, and debug level ones are colored as ``"darkgray"``.
|
||||
|
||||
.. autofunction:: pending_logging()
|
||||
|
||||
|
@ -138,8 +138,8 @@ Both APIs parse the content into a given node. They are used like this::
|
||||
|
||||
.. deprecated:: 1.7
|
||||
|
||||
Until Sphinx-1.6, ``sphinx.ext.autodoc.AutodocReporter`` is used for this purpose.
|
||||
For now, it is replaced by ``switch_source_input()``.
|
||||
Until Sphinx-1.6, ``sphinx.ext.autodoc.AutodocReporter`` is used for this
|
||||
purpose. For now, it is replaced by ``switch_source_input()``.
|
||||
|
||||
If you don't need the wrapping node, you can use any concrete node type and
|
||||
return ``node.children`` from the Directive.
|
||||
@ -147,5 +147,6 @@ return ``node.children`` from the Directive.
|
||||
|
||||
.. seealso::
|
||||
|
||||
`Creating directives <http://docutils.sourceforge.net/docs/howto/rst-directives.html>`_
|
||||
HOWTO of the Docutils documentation
|
||||
`Creating directives`_ HOWTO of the Docutils documentation
|
||||
|
||||
.. _Creating directives: http://docutils.sourceforge.net/docs/howto/rst-directives.html
|
||||
|
@ -15,6 +15,9 @@ components (e.g. :class:`.Config`, :class:`.BuildEnvironment` and so on) easily.
|
||||
.. autoclass:: sphinx.transforms.SphinxTransform
|
||||
:members:
|
||||
|
||||
.. autoclass:: sphinx.transforms.post_transforms.SphinxPostTransform
|
||||
:members:
|
||||
|
||||
.. autoclass:: sphinx.util.docutils.SphinxDirective
|
||||
:members:
|
||||
|
||||
@ -26,3 +29,9 @@ components (e.g. :class:`.Config`, :class:`.BuildEnvironment` and so on) easily.
|
||||
|
||||
.. autoclass:: sphinx.transforms.post_transforms.images.ImageConverter
|
||||
:members:
|
||||
|
||||
Utility components
|
||||
------------------
|
||||
|
||||
.. autoclass:: sphinx.events.EventManager
|
||||
:members:
|
||||
|
29
doc/faq.rst
29
doc/faq.rst
@ -37,9 +37,6 @@ How do I...
|
||||
You'll still need to mark up classes and such, but the headings and code
|
||||
examples come through cleanly.
|
||||
|
||||
... create HTML slides from Sphinx documents?
|
||||
See the "Hieroglyph" package at https://github.com/nyergler/hieroglyph.
|
||||
|
||||
For many more extensions and other contributed stuff, see the sphinx-contrib_
|
||||
repository.
|
||||
|
||||
@ -51,12 +48,10 @@ Using Sphinx with...
|
||||
--------------------
|
||||
|
||||
Read the Docs
|
||||
https://readthedocs.org is a documentation hosting service based around
|
||||
Sphinx. They will host sphinx documentation, along with supporting a number
|
||||
of other features including version support, PDF generation, and more. The
|
||||
`Getting Started
|
||||
<https://read-the-docs.readthedocs.io/en/latest/getting_started.html>`_
|
||||
guide is a good place to start.
|
||||
`Read the Docs <https://readthedocs.org>`_ is a documentation hosting
|
||||
service based around Sphinx. They will host sphinx documentation, along
|
||||
with supporting a number of other features including version support, PDF
|
||||
generation, and more. The `Getting Started`_ guide is a good place to start.
|
||||
|
||||
Epydoc
|
||||
There's a third-party extension providing an `api role`_ which refers to
|
||||
@ -77,13 +72,13 @@ PyPI
|
||||
https://pythonhosted.org/.
|
||||
|
||||
GitHub Pages
|
||||
Directories starting with underscores are ignored by default which breaks
|
||||
static files in Sphinx. GitHub's preprocessor can be `disabled
|
||||
<https://github.com/blog/572-bypassing-jekyll-on-github-pages>`_ to support
|
||||
Sphinx HTML output properly.
|
||||
Please add :py:mod:`sphinx.ext.githubpages` to your project. It allows you
|
||||
to publish your document in GitHub Pages. It generates helper files for
|
||||
GitHub Pages on building HTML document automatically.
|
||||
|
||||
MediaWiki
|
||||
See https://bitbucket.org/kevindunn/sphinx-wiki/wiki/Home, a project by Kevin Dunn.
|
||||
See https://bitbucket.org/kevindunn/sphinx-wiki/wiki/Home, a project by
|
||||
Kevin Dunn.
|
||||
|
||||
Google Analytics
|
||||
You can use a custom ``layout.html`` template, like this:
|
||||
@ -94,7 +89,7 @@ Google Analytics
|
||||
|
||||
{%- block extrahead %}
|
||||
{{ super() }}
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
var _gaq = _gaq || [];
|
||||
_gaq.push(['_setAccount', 'XXX account number XXX']);
|
||||
_gaq.push(['_trackPageview']);
|
||||
@ -106,7 +101,7 @@ Google Analytics
|
||||
<div class="footer">This page uses <a href="https://analytics.google.com/">
|
||||
Google Analytics</a> to collect statistics. You can disable it by blocking
|
||||
the JavaScript coming from www.google-analytics.com.
|
||||
<script type="text/javascript">
|
||||
<script>
|
||||
(function() {
|
||||
var ga = document.createElement('script');
|
||||
ga.src = ('https:' == document.location.protocol ?
|
||||
@ -137,7 +132,6 @@ Google Search
|
||||
(function() {
|
||||
var cx = '......';
|
||||
var gcse = document.createElement('script');
|
||||
gcse.type = 'text/javascript';
|
||||
gcse.async = true;
|
||||
gcse.src = 'https://cse.google.com/cse.js?cx=' + cx;
|
||||
var s = document.getElementsByTagName('script')[0];
|
||||
@ -149,6 +143,7 @@ Google Search
|
||||
|
||||
3. Add ``searchbox.html`` to the :confval:`html_sidebars` configuration value.
|
||||
|
||||
.. _Getting Started: https://docs.readthedocs.io/en/stable/intro/getting-started-with-sphinx.html
|
||||
.. _api role: https://git.savannah.gnu.org/cgit/kenozooid.git/tree/doc/extapi.py
|
||||
.. _xhtml to reST: http://docutils.sourceforge.net/sandbox/xhtml2rest/xhtml2rest.py
|
||||
|
||||
|
@ -17,10 +17,10 @@ docs have a look at `Epydoc <http://epydoc.sourceforge.net/>`_, which also
|
||||
understands reST.
|
||||
|
||||
For a great "introduction" to writing docs in general -- the whys and hows, see
|
||||
also `Write the docs <https://write-the-docs.readthedocs.io/>`_, written by Eric
|
||||
Holscher.
|
||||
also `Write the docs`_, written by Eric Holscher.
|
||||
|
||||
.. _rinohtype: https://github.com/brechtm/rinohtype
|
||||
.. _Write the docs: http://www.writethedocs.org/guide/writing/beginners-guide-to-docs/
|
||||
|
||||
Conversion from other systems
|
||||
-----------------------------
|
||||
@ -55,9 +55,9 @@ See the :ref:`pertinent section in the FAQ list <usingwith>`.
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
Sphinx needs at least **Python 3.5** to run, as well as the docutils_ and
|
||||
Jinja2_ libraries. Sphinx should work with docutils version 0.12 or some (not
|
||||
broken) SVN trunk snapshot.
|
||||
Sphinx needs at least **Python 3.5** to run.
|
||||
It also depends on 3rd party libraries such as docutils_ and jinja2_, but they
|
||||
are automatically installed when sphinx is installed.
|
||||
|
||||
.. _reStructuredText: http://docutils.sourceforge.net/rst.html
|
||||
.. _docutils: http://docutils.sourceforge.net/
|
||||
|
107
doc/latex.rst
107
doc/latex.rst
@ -226,6 +226,25 @@ into the generated ``.tex`` files. Its ``'sphinxsetup'`` key is described
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
``'extrapackages'``
|
||||
Additional LaTeX packages. For example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
latex_elements = {
|
||||
'packages': r'\usepackage{isodate}'
|
||||
}
|
||||
|
||||
It defaults to empty.
|
||||
|
||||
The specified LaTeX packages will be loaded before
|
||||
hyperref package and packages loaded from Sphinx extensions.
|
||||
|
||||
.. hint:: If you'd like to load additional LaTeX packages after hyperref, use
|
||||
``'preamble'`` key instead.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
``'footer'``
|
||||
Additional footer content (before the indices), default empty.
|
||||
|
||||
@ -289,6 +308,11 @@ into the generated ``.tex`` files. Its ``'sphinxsetup'`` key is described
|
||||
|
||||
.. attention::
|
||||
|
||||
If Greek is main language, do not use this key. Since Sphinx 2.2.1,
|
||||
``xelatex`` will be used automatically as :confval:`latex_engine`.
|
||||
Formerly, Sphinx did not support producing PDF via LaTeX with Greek as
|
||||
main language.
|
||||
|
||||
Prior to 2.0, Unicode Greek letters were escaped to use LaTeX math
|
||||
mark-up. This is not the case anymore, and the above must be used
|
||||
(only in case of ``'pdflatex'`` engine) if the source contains such
|
||||
@ -310,12 +334,19 @@ into the generated ``.tex`` files. Its ``'sphinxsetup'`` key is described
|
||||
.. versionchanged:: 2.0
|
||||
``'lualatex'`` executes
|
||||
``\defaultfontfeatures[\rmfamily,\sffamily]{}`` to disable TeX
|
||||
ligatures.
|
||||
ligatures transforming `<<` and `>>` as escaping working with
|
||||
``pdflatex/xelatex`` failed with ``lualatex``.
|
||||
.. versionchanged:: 2.0
|
||||
Detection of ``LGR``, ``T2A``, ``X2`` to trigger support of
|
||||
occasional Greek or Cyrillic (``'pdflatex'`` only, as this support
|
||||
is provided natively by ``'platex'`` and only requires suitable
|
||||
font with ``'xelatex'/'lualatex'``).
|
||||
.. versionchanged:: 2.3.0
|
||||
``'xelatex'`` also executes
|
||||
``\defaultfontfeatures[\rmfamily,\sffamily]{}`` in order to avoid
|
||||
contractions of ``--`` into en-dash or transforms of straight quotes
|
||||
into curly ones in PDF (in non-literal text paragraphs) despite
|
||||
:confval:`smartquotes` being set to ``False``.
|
||||
|
||||
``'textgreek'``
|
||||
The default (``'pdflatex'`` only) is
|
||||
@ -595,12 +626,15 @@ macros may be significant.
|
||||
default ``true``. Allows linebreaks inside inline literals: but extra
|
||||
potential break-points (additionally to those allowed by LaTeX at spaces
|
||||
or for hyphenation) are currently inserted only after the characters
|
||||
``. , ; ? ! /``. Due to TeX internals, white space in the line will be
|
||||
stretched (or shrunk) in order to accomodate the linebreak.
|
||||
``. , ; ? ! /`` and ``\``. Due to TeX internals, white space in the line
|
||||
will be stretched (or shrunk) in order to accomodate the linebreak.
|
||||
|
||||
.. versionadded:: 1.5
|
||||
set this option value to ``false`` to recover former behaviour.
|
||||
|
||||
.. versionchanged:: 2.3.0
|
||||
added potential breakpoint at ``\`` characters.
|
||||
|
||||
``verbatimvisiblespace``
|
||||
default ``\textcolor{red}{\textvisiblespace}``. When a long code line is
|
||||
split, the last space character from the source code line right before the
|
||||
@ -740,19 +774,41 @@ thus allowing redefinitions. Check the respective files for the defaults.
|
||||
Macros
|
||||
~~~~~~
|
||||
|
||||
- text styling commands ``\sphinx<foo>`` with ``<foo>`` being one of
|
||||
``strong``, ``bfcode``, ``email``, ``tablecontinued``, ``titleref``,
|
||||
``menuselection``, ``accelerator``, ``crossref``, ``termref``, ``optional``.
|
||||
- text styling commands:
|
||||
|
||||
- ``\sphinxstrong``,
|
||||
- ``\sphinxbfcode``,
|
||||
- ``\sphinxemail``,
|
||||
- ``\sphinxtablecontinued``,
|
||||
- ``\sphinxtitleref``,
|
||||
- ``\sphinxmenuselection``,
|
||||
- ``\sphinxaccelerator``,
|
||||
- ``\sphinxcrossref``,
|
||||
- ``\sphinxtermref``,
|
||||
- ``\sphinxoptional``.
|
||||
|
||||
.. versionadded:: 1.4.5
|
||||
Use of ``\sphinx`` prefixed macro names to limit possibilities of conflict
|
||||
with LaTeX packages.
|
||||
- more text styling: ``\sphinxstyle<bar>`` with ``<bar>`` one of
|
||||
``indexentry``, ``indexextra``, ``indexpageref``, ``topictitle``,
|
||||
``sidebartitle``, ``othertitle``, ``sidebarsubtitle``, ``theadfamily``,
|
||||
``emphasis``, ``literalemphasis``, ``strong``, ``literalstrong``,
|
||||
``abbreviation``, ``literalintitle``, ``codecontinued``, ``codecontinues``
|
||||
- more text styling:
|
||||
|
||||
- ``\sphinxstyleindexentry``,
|
||||
- ``\sphinxstyleindexextra``,
|
||||
- ``\sphinxstyleindexpageref``,
|
||||
- ``\sphinxstyletopictitle``,
|
||||
- ``\sphinxstylesidebartitle``,
|
||||
- ``\sphinxstyleothertitle``,
|
||||
- ``\sphinxstylesidebarsubtitle``,
|
||||
- ``\sphinxstyletheadfamily``,
|
||||
- ``\sphinxstyleemphasis``,
|
||||
- ``\sphinxstyleliteralemphasis``,
|
||||
- ``\sphinxstylestrong``,
|
||||
- ``\sphinxstyleliteralstrong``,
|
||||
- ``\sphinxstyleabbreviation``,
|
||||
- ``\sphinxstyleliteralintitle``,
|
||||
- ``\sphinxstylecodecontinued``,
|
||||
- ``\sphinxstylecodecontinues``.
|
||||
|
||||
.. versionadded:: 1.5
|
||||
these macros were formerly hard-coded as non customizable ``\texttt``,
|
||||
``\emph``, etc...
|
||||
@ -761,7 +817,7 @@ Macros
|
||||
multiple paragraphs in header cells of tables.
|
||||
.. versionadded:: 1.6.3
|
||||
``\sphinxstylecodecontinued`` and ``\sphinxstylecodecontinues``.
|
||||
- the table of contents is typeset via ``\sphinxtableofcontents`` which is a
|
||||
- ``\sphinxtableofcontents``: it is a
|
||||
wrapper (defined differently in :file:`sphinxhowto.cls` and in
|
||||
:file:`sphinxmanual.cls`) of standard ``\tableofcontents``. The macro
|
||||
``\sphinxtableofcontentshook`` is executed during its expansion right before
|
||||
@ -774,22 +830,22 @@ Macros
|
||||
done during loading of ``'manual'`` docclass are now executed later via
|
||||
``\sphinxtableofcontentshook``. This macro is also executed by the
|
||||
``'howto'`` docclass, but defaults to empty with it.
|
||||
- a custom ``\sphinxmaketitle`` is defined in the class files
|
||||
- ``\sphinxmaketitle``: it is defined in the class files
|
||||
:file:`sphinxmanual.cls` and :file:`sphinxhowto.cls` and is used as
|
||||
default setting of ``'maketitle'`` :confval:`latex_elements` key.
|
||||
|
||||
.. versionchanged:: 1.8.3
|
||||
formerly, ``\maketitle`` from LaTeX document class was modified by
|
||||
Sphinx.
|
||||
- for ``'manual'`` docclass a macro ``\sphinxbackoftitlepage``, if it is
|
||||
defined, gets executed at end of ``\sphinxmaketitle``, before the final
|
||||
- ``\sphinxbackoftitlepage``: for ``'manual'`` docclass, and if it is
|
||||
defined, it gets executed at end of ``\sphinxmaketitle``, before the final
|
||||
``\clearpage``. Use either the ``'maketitle'`` key or the ``'preamble'`` key
|
||||
of :confval:`latex_elements` to add a custom definition of
|
||||
``\sphinxbackoftitlepage``.
|
||||
|
||||
.. versionadded:: 1.8.3
|
||||
- the citation reference is typeset via ``\sphinxcite`` which is a wrapper
|
||||
of standard ``\cite``.
|
||||
- ``\sphinxcite``: it is a wrapper of standard ``\cite`` for citation
|
||||
references.
|
||||
|
||||
Environments
|
||||
~~~~~~~~~~~~
|
||||
@ -801,12 +857,23 @@ Environments
|
||||
.. versionadded:: 1.5.6
|
||||
formerly, the ``\small`` was hardcoded in LaTeX writer and the ending
|
||||
``\par`` was lacking.
|
||||
- for each admonition type ``<foo>``, the
|
||||
used environment is named ``sphinx<foo>``. They may be ``\renewenvironment``
|
||||
- environments associated with admonitions:
|
||||
|
||||
- ``sphinxnote``,
|
||||
- ``sphinxhint``,
|
||||
- ``sphinximportant``,
|
||||
- ``sphinxtip``,
|
||||
- ``sphinxwarning``,
|
||||
- ``sphinxcaution``,
|
||||
- ``sphinxattention``,
|
||||
- ``sphinxdanger``,
|
||||
- ``sphinxerror``.
|
||||
|
||||
They may be ``\renewenvironment``
|
||||
'd individually, and must then be defined with one argument (it is the heading
|
||||
of the notice, for example ``Warning:`` for :dudir:`warning` directive, if
|
||||
English is the document language). Their default definitions use either the
|
||||
*sphinxheavybox* (for the first listed directives) or the *sphinxlightbox*
|
||||
*sphinxheavybox* (for the last 5 ones) or the *sphinxlightbox*
|
||||
environments, configured to use the parameters (colours, border thickness)
|
||||
specific to each type, which can be set via ``'sphinxsetup'`` string.
|
||||
|
||||
|
@ -4,7 +4,8 @@ sphinx-apidoc
|
||||
Synopsis
|
||||
--------
|
||||
|
||||
**sphinx-apidoc** [*OPTIONS*] -o <*OUTPUT_PATH*> <*MODULE_PATH*> [*EXCLUDE_PATTERN*, ...]
|
||||
**sphinx-apidoc** [*OPTIONS*] -o <*OUTPUT_PATH*> <*MODULE_PATH*>
|
||||
[*EXCLUDE_PATTERN* ...]
|
||||
|
||||
Description
|
||||
-----------
|
||||
@ -38,6 +39,11 @@ Options
|
||||
|
||||
Directory to place the output files. If it does not exist, it is created.
|
||||
|
||||
.. option:: -q
|
||||
|
||||
Do not output anything on standard output, only write warnings and errors to
|
||||
standard error.
|
||||
|
||||
.. option:: -f, --force
|
||||
|
||||
Force overwriting of any existing generated files.
|
||||
@ -125,6 +131,30 @@ These options are used when :option:`--full` is specified:
|
||||
|
||||
Sets the project release to put in generated files (see :confval:`release`).
|
||||
|
||||
.. rubric:: Project templating
|
||||
|
||||
.. versionadded:: 2.2
|
||||
Project templating options for sphinx-apidoc
|
||||
|
||||
.. option:: -t, --templatedir=TEMPLATEDIR
|
||||
|
||||
Template directory for template files. You can modify the templates of
|
||||
sphinx project files generated by apidoc. Following Jinja2 template
|
||||
files are allowed:
|
||||
|
||||
* ``module.rst_t``
|
||||
* ``package.rst_t``
|
||||
* ``toc.rst_t``
|
||||
* ``master_doc.rst_t``
|
||||
* ``conf.py_t``
|
||||
* ``Makefile_t``
|
||||
* ``Makefile.new_t``
|
||||
* ``make.bat_t``
|
||||
* ``make.bat.new_t``
|
||||
|
||||
In detail, please refer the system template files Sphinx provides.
|
||||
(``sphinx/templates/apidoc`` and ``sphinx/templates/quickstart``)
|
||||
|
||||
Environment
|
||||
-----------
|
||||
|
||||
|
@ -302,7 +302,8 @@ variables to customize behavior:
|
||||
|
||||
.. describe:: SPHINXOPTS
|
||||
|
||||
Additional options for :program:`sphinx-build`.
|
||||
Additional options for :program:`sphinx-build`. These options can
|
||||
also be set via the shortcut variable **O** (capital 'o').
|
||||
|
||||
.. _when-deprecation-warnings-are-displayed:
|
||||
|
||||
|
@ -297,7 +297,8 @@ in the future.
|
||||
|
||||
The "page name" of the current file, i.e. either the document name if the
|
||||
file is generated from a reST source, or the equivalent hierarchical name
|
||||
relative to the output directory (``[directory/]filename_without_extension``).
|
||||
relative to the output directory
|
||||
(``[directory/]filename_without_extension``).
|
||||
|
||||
.. data:: project
|
||||
|
||||
@ -354,8 +355,8 @@ are in HTML form), these variables are also available:
|
||||
|
||||
.. data:: body
|
||||
|
||||
A string containing the content of the page in HTML form as produced by the HTML builder,
|
||||
before the theme is applied.
|
||||
A string containing the content of the page in HTML form as produced by the
|
||||
HTML builder, before the theme is applied.
|
||||
|
||||
.. data:: display_toc
|
||||
|
||||
@ -382,8 +383,9 @@ are in HTML form), these variables are also available:
|
||||
|
||||
.. data:: page_source_suffix
|
||||
|
||||
The suffix of the file that was rendered. Since we support a list of :confval:`source_suffix`,
|
||||
this will allow you to properly link to the original source file.
|
||||
The suffix of the file that was rendered. Since we support a list of
|
||||
:confval:`source_suffix`, this will allow you to properly link to the
|
||||
original source file.
|
||||
|
||||
.. data:: parents
|
||||
|
||||
|
@ -49,8 +49,9 @@ Python :mod:`ConfigParser` module) and has the following structure:
|
||||
* The **inherit** setting gives the name of a "base theme", or ``none``. The
|
||||
base theme will be used to locate missing templates (most themes will not have
|
||||
to supply most templates if they use ``basic`` as the base theme), its options
|
||||
will be inherited, and all of its static files will be used as well. If you want
|
||||
to also inherit the stylesheet, include it via CSS' ``@import`` in your own.
|
||||
will be inherited, and all of its static files will be used as well. If you
|
||||
want to also inherit the stylesheet, include it via CSS' ``@import`` in your
|
||||
own.
|
||||
|
||||
* The **stylesheet** setting gives the name of a CSS file which will be
|
||||
referenced in the HTML header. If you need more than one CSS file, either
|
||||
|
@ -12,8 +12,8 @@ in itself. See the :ref:`intl-options` for details on configuration.
|
||||
.. figure:: /_static/translation.png
|
||||
:width: 100%
|
||||
|
||||
Workflow visualization of translations in Sphinx. (The stick-figure is taken
|
||||
from an `XKCD comic <https://xkcd.com/779/>`_.)
|
||||
Workflow visualization of translations in Sphinx. (The figure is created by
|
||||
`plantuml <http://plantuml.com>`_.)
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
@ -57,7 +57,7 @@ Once configured, call this by calling the relevant command on ``setup.py``::
|
||||
Options for setuptools integration
|
||||
----------------------------------
|
||||
|
||||
.. confval:: fresh-env
|
||||
.. setuptools-confval:: fresh-env
|
||||
|
||||
A boolean that determines whether the saved environment should be discarded
|
||||
on build. Default is false.
|
||||
@ -68,7 +68,7 @@ Options for setuptools integration
|
||||
|
||||
$ python setup.py build_sphinx -E
|
||||
|
||||
.. confval:: all-files
|
||||
.. setuptools-confval:: all-files
|
||||
|
||||
A boolean that determines whether all files should be built from scratch.
|
||||
Default is false.
|
||||
@ -79,7 +79,7 @@ Options for setuptools integration
|
||||
|
||||
$ python setup.py build_sphinx -a
|
||||
|
||||
.. confval:: source-dir
|
||||
.. setuptools-confval:: source-dir
|
||||
|
||||
The target source directory. This can be relative to the ``setup.py`` or
|
||||
``setup.cfg`` file, or it can be absolute. It defaults to ``./doc`` or
|
||||
@ -92,12 +92,12 @@ Options for setuptools integration
|
||||
|
||||
$ python setup.py build_sphinx -s $SOURCE_DIR
|
||||
|
||||
.. confval:: build-dir
|
||||
.. setuptools-confval:: build-dir
|
||||
|
||||
The target build directory. This can be relative to the ``setup.py`` or
|
||||
``setup.cfg`` file, or it can be absolute. Default is ``./build/sphinx``.
|
||||
|
||||
.. confval:: config-dir
|
||||
.. setuptools-confval:: config-dir
|
||||
|
||||
Location of the configuration directory. This can be relative to the
|
||||
``setup.py`` or ``setup.cfg`` file, or it can be absolute. Default is to use
|
||||
@ -111,7 +111,7 @@ Options for setuptools integration
|
||||
|
||||
.. versionadded:: 1.0
|
||||
|
||||
.. confval:: builder
|
||||
.. setuptools-confval:: builder
|
||||
|
||||
The builder or list of builders to use. Default is ``html``.
|
||||
|
||||
@ -124,7 +124,7 @@ Options for setuptools integration
|
||||
.. versionchanged:: 1.6
|
||||
This can now be a comma- or space-separated list of builders
|
||||
|
||||
.. confval:: warning-is-error
|
||||
.. setuptools-confval:: warning-is-error
|
||||
|
||||
A boolean that ensures Sphinx warnings will result in a failed build.
|
||||
Default is false.
|
||||
@ -137,32 +137,32 @@ Options for setuptools integration
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
.. confval:: project
|
||||
.. setuptools-confval:: project
|
||||
|
||||
The documented project's name. Default is ``''``.
|
||||
|
||||
.. versionadded:: 1.0
|
||||
|
||||
.. confval:: version
|
||||
.. setuptools-confval:: version
|
||||
|
||||
The short X.Y version. Default is ``''``.
|
||||
|
||||
.. versionadded:: 1.0
|
||||
|
||||
.. confval:: release
|
||||
.. setuptools-confval:: release
|
||||
|
||||
The full version, including alpha/beta/rc tags. Default is ``''``.
|
||||
|
||||
.. versionadded:: 1.0
|
||||
|
||||
.. confval:: today
|
||||
.. setuptools-confval:: today
|
||||
|
||||
How to format the current date, used as the replacement for ``|today|``.
|
||||
Default is ``''``.
|
||||
|
||||
.. versionadded:: 1.0
|
||||
|
||||
.. confval:: link-index
|
||||
.. setuptools-confval:: link-index
|
||||
|
||||
A boolean that ensures index.html will be linked to the master doc. Default
|
||||
is false.
|
||||
@ -175,13 +175,13 @@ Options for setuptools integration
|
||||
|
||||
.. versionadded:: 1.0
|
||||
|
||||
.. confval:: copyright
|
||||
.. setuptools-confval:: copyright
|
||||
|
||||
The copyright string. Default is ``''``.
|
||||
|
||||
.. versionadded:: 1.3
|
||||
|
||||
.. confval:: nitpicky
|
||||
.. setuptools-confval:: nitpicky
|
||||
|
||||
Run in nit-picky mode. Currently, this generates warnings for all missing
|
||||
references. See the config value :confval:`nitpick_ignore` for a way to
|
||||
@ -189,7 +189,7 @@ Options for setuptools integration
|
||||
|
||||
.. versionadded:: 1.8
|
||||
|
||||
.. confval:: pdb
|
||||
.. setuptools-confval:: pdb
|
||||
|
||||
A boolean to configure ``pdb`` on exception. Default is false.
|
||||
|
||||
|
@ -63,7 +63,7 @@ This dict can then be used as context for templates. The goal is to be easy to
|
||||
integrate with your existing templating system. An example using `Jinja2
|
||||
<http://jinja.pocoo.org/>`_ is:
|
||||
|
||||
.. sourcecode:: html+jinja
|
||||
.. code-block:: html+jinja
|
||||
|
||||
{%- extends "layout.html" %}
|
||||
|
||||
|
@ -61,7 +61,7 @@ The builder's "name" must be given to the **-b** command-line option of
|
||||
|
||||
.. versionadded:: 1.0
|
||||
|
||||
.. module:: sphinx.builders.htmlhelp
|
||||
.. module:: sphinxcontrib.htmlhelp
|
||||
.. class:: HTMLHelpBuilder
|
||||
|
||||
This builder produces the same output as the standalone HTML builder, but
|
||||
|
@ -296,25 +296,26 @@ General configuration
|
||||
|
||||
Sphinx supports following warning types:
|
||||
|
||||
* app.add_node
|
||||
* app.add_directive
|
||||
* app.add_role
|
||||
* app.add_generic_role
|
||||
* app.add_source_parser
|
||||
* download.not_readable
|
||||
* image.not_readable
|
||||
* ref.term
|
||||
* ref.ref
|
||||
* ref.numref
|
||||
* ref.keyword
|
||||
* ref.option
|
||||
* ref.citation
|
||||
* ref.footnote
|
||||
* ref.doc
|
||||
* ref.python
|
||||
* misc.highlighting_failure
|
||||
* toc.secnum
|
||||
* epub.unknown_project_files
|
||||
* ``app.add_node``
|
||||
* ``app.add_directive``
|
||||
* ``app.add_role``
|
||||
* ``app.add_generic_role``
|
||||
* ``app.add_source_parser``
|
||||
* ``download.not_readable``
|
||||
* ``image.not_readable``
|
||||
* ``ref.term``
|
||||
* ``ref.ref``
|
||||
* ``ref.numref``
|
||||
* ``ref.keyword``
|
||||
* ``ref.option``
|
||||
* ``ref.citation``
|
||||
* ``ref.footnote``
|
||||
* ``ref.doc``
|
||||
* ``ref.python``
|
||||
* ``misc.highlighting_failure``
|
||||
* ``toc.secnum``
|
||||
* ``epub.unknown_project_files``
|
||||
* ``autosectionlabel.*``
|
||||
|
||||
You can choose from these types.
|
||||
|
||||
@ -334,6 +335,10 @@ General configuration
|
||||
|
||||
Added ``ref.footnote``
|
||||
|
||||
.. versionchanged:: 2.1
|
||||
|
||||
Added ``autosectionlabel.*``
|
||||
|
||||
.. confval:: needs_sphinx
|
||||
|
||||
If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will
|
||||
@ -492,8 +497,27 @@ General configuration
|
||||
direct usage of :program:`sphinx-build` as it caches
|
||||
(in its default usage) the parsed source files in per builder locations.
|
||||
|
||||
.. hint:: An alternative way to effectively deactivate (or customize) the
|
||||
smart quotes for a given builder, for example ``latex``, is to use
|
||||
``make`` this way:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
make latex O="-D smartquotes_action="
|
||||
|
||||
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.
|
||||
|
||||
.. versionadded:: 1.6.6
|
||||
|
||||
.. confval:: user_agent
|
||||
|
||||
A User-Agent of Sphinx. It is used for a header on HTTP access (ex.
|
||||
linkcheck, intersphinx and so on). Default is ``"Sphinx/X.Y.Z
|
||||
requests/X.Y.Z python/X.Y.Z"``.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
.. confval:: tls_verify
|
||||
|
||||
If true, Sphinx verifies server certifications. Default is ``True``.
|
||||
@ -514,7 +538,7 @@ General configuration
|
||||
directory pointed ``REQUESTS_CA_BUNDLE`` environment
|
||||
variable if ``tls_cacerts`` not set.
|
||||
|
||||
.. _requests: http://docs.python-requests.org/en/master/
|
||||
.. _requests: https://requests.readthedocs.io/en/master/
|
||||
|
||||
.. confval:: today
|
||||
today_fmt
|
||||
@ -550,7 +574,7 @@ General configuration
|
||||
A dictionary of options that modify how the lexer specified by
|
||||
:confval:`highlight_language` generates highlighted source code. These are
|
||||
lexer-specific; for the options understood by each, see the
|
||||
`Pygments documentation <http://pygments.org/docs/lexers/>`_.
|
||||
`Pygments documentation <https://pygments.org/docs/lexers.html>`_.
|
||||
|
||||
.. versionadded:: 1.3
|
||||
|
||||
@ -638,12 +662,17 @@ documentation on :ref:`intl` for details.
|
||||
|
||||
Currently supported languages by Sphinx are:
|
||||
|
||||
* ``ar`` -- Arabic
|
||||
* ``bn`` -- Bengali
|
||||
* ``ca`` -- Catalan
|
||||
* ``cak`` -- Kaqchikel
|
||||
* ``cs`` -- Czech
|
||||
* ``cy`` -- Welsh
|
||||
* ``da`` -- Danish
|
||||
* ``de`` -- German
|
||||
* ``el`` -- Greek
|
||||
* ``en`` -- English
|
||||
* ``eo`` -- Esperanto
|
||||
* ``es`` -- Spanish
|
||||
* ``et`` -- Estonian
|
||||
* ``eu`` -- Basque
|
||||
@ -651,6 +680,7 @@ documentation on :ref:`intl` for details.
|
||||
* ``fi`` -- Finnish
|
||||
* ``fr`` -- French
|
||||
* ``he`` -- Hebrew
|
||||
* ``hi`` -- Hindi
|
||||
* ``hr`` -- Croatian
|
||||
* ``hu`` -- Hungarian
|
||||
* ``id`` -- Indonesian
|
||||
@ -664,15 +694,20 @@ documentation on :ref:`intl` for details.
|
||||
* ``ne`` -- Nepali
|
||||
* ``nl`` -- Dutch
|
||||
* ``pl`` -- Polish
|
||||
* ``pt`` -- Portuguese
|
||||
* ``pt_BR`` -- Brazilian Portuguese
|
||||
* ``pt_PT`` -- European Portuguese
|
||||
* ``ro`` -- Romanian
|
||||
* ``ru`` -- Russian
|
||||
* ``si`` -- Sinhala
|
||||
* ``sk`` -- Slovak
|
||||
* ``sl`` -- Slovenian
|
||||
* ``sr`` -- Serbian
|
||||
* ``sv`` -- Swedish
|
||||
* ``ta`` -- Tamil
|
||||
* ``tr`` -- Turkish
|
||||
* ``uk_UA`` -- Ukrainian
|
||||
* ``ur`` -- Urdu
|
||||
* ``vi`` -- Vietnamese
|
||||
* ``zh_CN`` -- Simplified Chinese
|
||||
* ``zh_TW`` -- Traditional Chinese
|
||||
@ -746,7 +781,7 @@ documentation on :ref:`intl` for details.
|
||||
i18n additionally. You can specify below names:
|
||||
|
||||
:index: index terms
|
||||
:literal-block: literal blocks: ``::`` and ``code-block``.
|
||||
:literal-block: literal blocks (``::`` annotation and ``code-block`` directive)
|
||||
:doctest-block: doctest block
|
||||
:raw: raw content
|
||||
:image: image/figure uri and alt
|
||||
@ -914,7 +949,7 @@ that use Sphinx's HTMLWriter class.
|
||||
|
||||
Example::
|
||||
|
||||
html_css_files = ['custom.css'
|
||||
html_css_files = ['custom.css',
|
||||
'https://example.com/css/custom.css',
|
||||
('print.css', {'media': 'print'})]
|
||||
|
||||
@ -1812,6 +1847,7 @@ These options influence LaTeX output.
|
||||
* ``'xelatex'`` -- XeLaTeX
|
||||
* ``'lualatex'`` -- LuaLaTeX
|
||||
* ``'platex'`` -- pLaTeX (default if :confval:`language` is ``'ja'``)
|
||||
* ``'uplatex'`` -- upLaTeX (experimental)
|
||||
|
||||
``'pdflatex'``\ 's support for Unicode characters is limited.
|
||||
|
||||
@ -1825,7 +1861,21 @@ These options influence LaTeX output.
|
||||
``'xelatex'`` or ``'lualatex'`` and making sure to use an OpenType font
|
||||
with wide-enough glyph coverage is often easier than trying to make
|
||||
``'pdflatex'`` work with the extra Unicode characters. Since Sphinx 2.0
|
||||
the default is the GNU FreeFont which covers well Latin, Cyrillic and Greek.
|
||||
the default is the GNU FreeFont which covers well Latin, Cyrillic and
|
||||
Greek.
|
||||
|
||||
.. versionchanged:: 2.1.0
|
||||
|
||||
Use ``xelatex`` (and LaTeX package ``xeCJK``) by default for Chinese
|
||||
documents.
|
||||
|
||||
.. versionchanged:: 2.2.1
|
||||
|
||||
Use ``xelatex`` by default for Greek documents.
|
||||
|
||||
.. versionchanged:: 2.3
|
||||
|
||||
Add ``uplatex`` support.
|
||||
|
||||
Contrarily to :ref:`MathJaX math rendering in HTML output <math-support>`,
|
||||
LaTeX requires some extra configuration to support Unicode literals in
|
||||
@ -2330,6 +2380,34 @@ Options for the linkcheck builder
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
.. confval:: linkcheck_auth
|
||||
|
||||
Pass authentication information when doing a ``linkcheck`` build.
|
||||
|
||||
A list of ``(regex_pattern, auth_info)`` tuples where the items are:
|
||||
|
||||
*regex_pattern*
|
||||
A regular expression that matches a URI.
|
||||
*auth_info*
|
||||
Authentication information to use for that URI. The value can be anything
|
||||
that is understood by the ``requests`` library (see `requests
|
||||
Authentication <requests-auth>`_ for details).
|
||||
|
||||
.. _requests-auth: https://requests.readthedocs.io/en/master/user/authentication/
|
||||
|
||||
The ``linkcheck`` builder will use the first matching ``auth_info`` value
|
||||
it can find in the :confval:`linkcheck_auth` list, so values earlier in the
|
||||
list have higher priority.
|
||||
|
||||
Example::
|
||||
|
||||
linkcheck_auth = [
|
||||
('https://foo\.yourcompany\.com/.+', ('johndoe', 'secret')),
|
||||
('https://.+\.yourcompany\.com/.+', HTTPDigestAuth(...)),
|
||||
]
|
||||
|
||||
.. versionadded:: 2.3
|
||||
|
||||
|
||||
Options for the XML builder
|
||||
---------------------------
|
||||
|
@ -40,10 +40,8 @@ you can also enable the :mod:`napoleon <sphinx.ext.napoleon>` extension.
|
||||
:mod:`napoleon <sphinx.ext.napoleon>` is a preprocessor that converts your
|
||||
docstrings to correct reStructuredText before :mod:`autodoc` processes them.
|
||||
|
||||
.. _Google:
|
||||
https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings
|
||||
.. _NumPy:
|
||||
https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
|
||||
.. _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
|
||||
|
||||
|
||||
Directives
|
||||
@ -142,6 +140,20 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
|
||||
|
||||
.. versionadded:: 1.1
|
||||
|
||||
* autodoc considers a member private if its docstring contains
|
||||
``:meta private:`` in its :ref:`info-field-lists`.
|
||||
For example:
|
||||
|
||||
.. code-block:: rst
|
||||
|
||||
def my_function(my_arg, my_other_arg):
|
||||
"""blah blah blah
|
||||
|
||||
:meta private:
|
||||
"""
|
||||
|
||||
.. versionadded:: 3.0
|
||||
|
||||
* Python "special" members (that is, those named like ``__special__``) will
|
||||
be included if the ``special-members`` flag option is given::
|
||||
|
||||
@ -159,7 +171,7 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
|
||||
|
||||
* For classes and exceptions, members inherited from base classes will be
|
||||
left out when documenting all members, unless you give the
|
||||
``inherited-members`` flag option, in addition to ``members``::
|
||||
``inherited-members`` option, in addition to ``members``::
|
||||
|
||||
.. autoclass:: Noodle
|
||||
:members:
|
||||
@ -168,11 +180,29 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
|
||||
This can be combined with ``undoc-members`` to document *all* available
|
||||
members of the class or module.
|
||||
|
||||
It can take an anchestor class not to document inherited members from it.
|
||||
By default, members of ``object`` class are not documented. To show them
|
||||
all, give ``None`` to the option.
|
||||
|
||||
For example; If your class ``Foo`` is derived from ``list`` class and
|
||||
you don't want to document ``list.__len__()``, you should specify a
|
||||
option ``:inherited-members: list`` to avoid special members of list
|
||||
class.
|
||||
|
||||
Another example; If your class Foo has ``__str__`` special method and
|
||||
autodoc directive has both ``inherited-members`` and ``special-members``,
|
||||
``__str__`` will be documented as in the past, but other special method
|
||||
that are not implemented in your class ``Foo``.
|
||||
|
||||
Note: this will lead to markup errors if the inherited members come from a
|
||||
module whose docstrings are not reST formatted.
|
||||
|
||||
.. versionadded:: 0.3
|
||||
|
||||
.. versionchanged:: 3.0
|
||||
|
||||
It takes an anchestor class name as an argument.
|
||||
|
||||
* It's possible to override the signature for explicitly documented callable
|
||||
objects (functions, methods, classes) with the regular syntax that will
|
||||
override the signature gained from introspection::
|
||||
@ -245,21 +275,23 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
|
||||
These work exactly like :rst:dir:`autoclass` etc.,
|
||||
but do not offer the options used for automatic member documentation.
|
||||
|
||||
:rst:dir:`autodata` and :rst:dir:`autoattribute` support
|
||||
the ``annotation`` option.
|
||||
Without this option, the representation of the object
|
||||
will be shown in the documentation.
|
||||
When the option is given without arguments,
|
||||
only the name of the object will be printed::
|
||||
:rst:dir:`autodata` and :rst:dir:`autoattribute` support the ``annotation``
|
||||
option. The option controls how the value of variable is shown. If specified
|
||||
without arguments, only the name of the variable will be printed, and its value
|
||||
is not shown::
|
||||
|
||||
.. autodata:: CD_DRIVE
|
||||
:annotation:
|
||||
|
||||
You can tell sphinx what should be printed after the name::
|
||||
If the option specified with arguments, it is printed after the name as a value
|
||||
of the variable::
|
||||
|
||||
.. autodata:: CD_DRIVE
|
||||
:annotation: = your CD device name
|
||||
|
||||
By default, without ``annotation`` option, Sphinx tries to obtain the value of
|
||||
the variable and print it after the name.
|
||||
|
||||
For module data members and class attributes, documentation can either be put
|
||||
into a comment with special formatting (using a ``#:`` to start the comment
|
||||
instead of just ``#``), or in a docstring *after* the definition. Comments
|
||||
@ -315,7 +347,7 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
There are also new config values that you can set:
|
||||
There are also config values that you can set:
|
||||
|
||||
.. confval:: autoclass_content
|
||||
|
||||
@ -387,14 +419,17 @@ There are also new config values that you can set:
|
||||
|
||||
The supported options are ``'members'``, ``'member-order'``,
|
||||
``'undoc-members'``, ``'private-members'``, ``'special-members'``,
|
||||
``'inherited-members'``, ``'show-inheritance'``, ``'ignore-module-all'`` and
|
||||
``'exclude-members'``.
|
||||
``'inherited-members'``, ``'show-inheritance'``, ``'ignore-module-all'``,
|
||||
``'imported-members'`` and ``'exclude-members'``.
|
||||
|
||||
.. versionadded:: 1.8
|
||||
|
||||
.. versionchanged:: 2.0
|
||||
Accepts ``True`` as a value.
|
||||
|
||||
.. versionchanged:: 2.1
|
||||
Added ``'imported-members'``.
|
||||
|
||||
.. confval:: autodoc_docstring_signature
|
||||
|
||||
Functions imported from C modules cannot be introspected, and therefore the
|
||||
@ -428,6 +463,16 @@ There are also new config values that you can set:
|
||||
This config value only requires to declare the top-level modules that
|
||||
should be mocked.
|
||||
|
||||
.. confval:: autodoc_typehints
|
||||
|
||||
This value controls how to represents typehints. The setting takes the
|
||||
following values:
|
||||
|
||||
* ``'signature'`` -- Show typehints as its signature (default)
|
||||
* ``'none'`` -- Do not show typehints
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
.. confval:: autodoc_warningiserror
|
||||
|
||||
This value controls the behavior of :option:`sphinx-build -W` during
|
||||
@ -481,6 +526,17 @@ autodoc provides the following additional events:
|
||||
auto directive
|
||||
:param lines: the lines of the docstring, see above
|
||||
|
||||
.. event:: autodoc-before-process-signature (app, obj, bound_method)
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
Emitted before autodoc formats a signature for an object. The event handler
|
||||
can modify an object to change its signature.
|
||||
|
||||
:param app: the Sphinx application object
|
||||
:param obj: the object itself
|
||||
:param bound_method: a boolean indicates an object is bound method or not
|
||||
|
||||
.. event:: autodoc-process-signature (app, what, name, obj, options, signature, return_annotation)
|
||||
|
||||
.. versionadded:: 0.5
|
||||
@ -543,3 +599,24 @@ member should be included in the documentation by using the following event:
|
||||
``inherited_members``, ``undoc_members``, ``show_inheritance`` and
|
||||
``noindex`` that are true if the flag option of same name was given to the
|
||||
auto directive
|
||||
|
||||
Generating documents from type annotations
|
||||
------------------------------------------
|
||||
|
||||
As an experimental feature, autodoc provides ``sphinx.ext.autodoc.typehints`` as
|
||||
an additional extension. It extends autodoc itself to generate function document
|
||||
from its type annotations.
|
||||
|
||||
To enable the feature, please add ``sphinx.ext.autodoc.typehints`` to list of
|
||||
extensions and set `'description'` to :confval:`autodoc_typehints`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.autodoc.typehints']
|
||||
|
||||
autodoc_typehints = 'description'
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
Added as an experimental feature. This will be integrated into autodoc core
|
||||
in Sphinx-3.0.
|
||||
|
@ -131,7 +131,7 @@ Generating stub pages automatically
|
||||
-----------------------------------
|
||||
|
||||
If you do not want to create stub pages with :program:`sphinx-autogen`, you can
|
||||
also use this new config value:
|
||||
also use these config values:
|
||||
|
||||
.. confval:: autosummary_generate
|
||||
|
||||
@ -143,12 +143,34 @@ also use this new config value:
|
||||
The new files will be placed in the directories specified in the
|
||||
``:toctree:`` options of the directives.
|
||||
|
||||
.. versionchanged:: 2.3
|
||||
|
||||
Emits :event:`autodoc-skip-member` event as :mod:`~sphinx.ext.autodoc`
|
||||
does.
|
||||
|
||||
.. confval:: autosummary_generate_overwrite
|
||||
|
||||
If true, autosummary already overwrites stub files by generated contents.
|
||||
Defaults to true (enabled).
|
||||
|
||||
.. versionadded:: 3.0
|
||||
|
||||
.. confval:: autosummary_mock_imports
|
||||
|
||||
This value contains a list of modules to be mocked up. See
|
||||
:confval:`autodoc_mock_imports` for more details. It defaults to
|
||||
:confval:`autodoc_mock_imports`.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
.. confval:: autosummary_imported_members
|
||||
|
||||
A boolean flag indicating whether to document classes and functions imported
|
||||
in modules. Default is ``False``
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
|
||||
Customizing templates
|
||||
---------------------
|
||||
|
||||
|
@ -13,7 +13,7 @@ This extension features one additional builder, the :class:`CoverageBuilder`.
|
||||
|
||||
.. todo:: Write this section.
|
||||
|
||||
Several new configuration values can be used to specify what the builder
|
||||
Several configuration values can be used to specify what the builder
|
||||
should check:
|
||||
|
||||
.. confval:: coverage_ignore_modules
|
||||
@ -22,6 +22,16 @@ should check:
|
||||
|
||||
.. confval:: coverage_ignore_classes
|
||||
|
||||
.. confval:: coverage_ignore_pyobjects
|
||||
|
||||
List of `Python regular expressions`_.
|
||||
|
||||
If any of these regular expressions matches any part of the full import path
|
||||
of a Python object, that Python object is excluded from the documentation
|
||||
coverage report.
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
.. confval:: coverage_c_path
|
||||
|
||||
.. confval:: coverage_c_regexes
|
||||
@ -40,3 +50,5 @@ should check:
|
||||
``False`` by default.
|
||||
|
||||
.. versionadded:: 1.1
|
||||
|
||||
.. _Python regular expressions: https://docs.python.org/library/re
|
@ -11,11 +11,15 @@
|
||||
pair: testing; snippets
|
||||
|
||||
|
||||
This extension allows you to test snippets in the documentation in a natural
|
||||
way. It works by collecting specially-marked up code blocks and running them as
|
||||
doctest tests.
|
||||
It is often helpful to include snippets of code in your documentation and
|
||||
demonstrate the results of executing them. But it is important to ensure that
|
||||
the documentation stays up-to-date with the code.
|
||||
|
||||
Within one document, test code is partitioned in *groups*, where each group
|
||||
This extension allows you to test such code snippets in the documentation in
|
||||
a natural way. If you mark the code blocks as shown here, the ``doctest``
|
||||
builder will collect them and run them as doctest tests.
|
||||
|
||||
Within each document, you can assign each snippet to a *group*. Each group
|
||||
consists of:
|
||||
|
||||
* zero or more *setup code* blocks (e.g. importing the module to test)
|
||||
|
11
doc/usage/extensions/duration.rst
Normal file
11
doc/usage/extensions/duration.rst
Normal file
@ -0,0 +1,11 @@
|
||||
:mod:`sphinx.ext.duration` -- Measure durations of Sphinx processing
|
||||
====================================================================
|
||||
|
||||
.. module:: sphinx.ext.duration
|
||||
:synopsis: Measure durations of Sphinx processing
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
This extension measures durations of Sphinx processing and show its
|
||||
result at end of the build. It is useful for inspecting what document
|
||||
is slowly built.
|
@ -18,7 +18,7 @@ tracker, at :samp:`https://github.com/sphinx-doc/sphinx/issues/{num}`. Typing
|
||||
this URL again and again is tedious, so you can use :mod:`~sphinx.ext.extlinks`
|
||||
to avoid repeating yourself.
|
||||
|
||||
The extension adds one new config value:
|
||||
The extension adds a config value:
|
||||
|
||||
.. confval:: extlinks
|
||||
|
||||
|
@ -39,6 +39,56 @@ It adds these directives:
|
||||
.. versionchanged:: 1.1
|
||||
Added support for external files.
|
||||
|
||||
.. rubric:: options
|
||||
|
||||
.. rst:directive:option:: alt: alternate text
|
||||
:type: text
|
||||
|
||||
The alternate text of the graph. By default, the graph code is used to
|
||||
the alternate text.
|
||||
|
||||
.. versionadded:: 1.0
|
||||
|
||||
.. rst:directive:option:: align: alignment of the graph
|
||||
:type: left, center or right
|
||||
|
||||
The horizontal alignment of the graph.
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
.. rst:directive:option:: caption: caption of the graph
|
||||
:type: text
|
||||
|
||||
The caption of the graph.
|
||||
|
||||
.. versionadded:: 1.1
|
||||
|
||||
.. rst:directive:option:: layout: layout type of the graph
|
||||
:type: text
|
||||
|
||||
The layout of the graph (ex. ``dot``, ``neato`` and so on). A path to the
|
||||
graphviz commands are also allowed. By default, :confval:`graphviz_dot`
|
||||
is used.
|
||||
|
||||
.. versionadded:: 1.4
|
||||
.. versionchanged:: 2.2
|
||||
|
||||
Renamed from ``graphviz_dot``
|
||||
|
||||
.. rst:directive:option:: name: label
|
||||
:type: text
|
||||
|
||||
The label of the graph.
|
||||
|
||||
.. versionadded:: 1.6
|
||||
|
||||
.. rst:directive:option:: class: class names
|
||||
:type: a list of class names separeted by spaces
|
||||
|
||||
The class name of the graph.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. rst:directive:: graph
|
||||
|
||||
@ -56,6 +106,45 @@ It adds these directives:
|
||||
non-alphanumeric characters (e.g. a dash), you will have to double-quote
|
||||
it.
|
||||
|
||||
.. rubric:: options
|
||||
|
||||
Same as :rst:dir:`graphviz`.
|
||||
|
||||
.. rst:directive:option:: alt: alternate text
|
||||
:type: text
|
||||
|
||||
.. versionadded:: 1.0
|
||||
|
||||
.. rst:directive:option:: align: alignment of the graph
|
||||
:type: left, center or right
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
.. rst:directive:option:: caption: caption of the graph
|
||||
:type: text
|
||||
|
||||
.. versionadded:: 1.1
|
||||
|
||||
.. rst:directive:option:: layout: layout type of the graph
|
||||
:type: text
|
||||
|
||||
.. versionadded:: 1.4
|
||||
.. versionchanged:: 2.2
|
||||
|
||||
Renamed from ``graphviz_dot``
|
||||
|
||||
.. rst:directive:option:: name: label
|
||||
:type: text
|
||||
|
||||
.. versionadded:: 1.6
|
||||
|
||||
.. rst:directive:option:: class: class names
|
||||
:type: a list of class names separeted by spaces
|
||||
|
||||
The class name of the graph.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
.. rst:directive:: digraph
|
||||
|
||||
@ -69,28 +158,47 @@ It adds these directives:
|
||||
|
||||
"bar" -> "baz" -> "quux";
|
||||
|
||||
.. rubric:: options
|
||||
|
||||
.. versionadded:: 1.0
|
||||
All three directives support an ``alt`` option that determines the image's
|
||||
alternate text for HTML output. If not given, the alternate text defaults to
|
||||
the graphviz code.
|
||||
Same as :rst:dir:`graphviz`.
|
||||
|
||||
.. versionadded:: 1.1
|
||||
All three directives support a ``caption`` option that can be used to give a
|
||||
caption to the diagram.
|
||||
.. rst:directive:option:: alt: alternate text
|
||||
:type: text
|
||||
|
||||
.. versionchanged:: 1.4
|
||||
All three directives support a ``graphviz_dot`` option that can be switch the
|
||||
``dot`` command within the directive.
|
||||
.. versionadded:: 1.0
|
||||
|
||||
.. versionadded:: 1.5
|
||||
All three directives support a ``align`` option to align the graph horizontal.
|
||||
The values "left", "center", "right" are allowed.
|
||||
.. rst:directive:option:: align: alignment of the graph
|
||||
:type: left, center or right
|
||||
|
||||
.. versionadded:: 1.6
|
||||
All three directives support a ``name`` option to set the label to graph.
|
||||
.. versionadded:: 1.5
|
||||
|
||||
There are also these new config values:
|
||||
.. rst:directive:option:: caption: caption of the graph
|
||||
:type: text
|
||||
|
||||
.. versionadded:: 1.1
|
||||
|
||||
.. rst:directive:option:: layout: layout type of the graph
|
||||
:type: text
|
||||
|
||||
.. versionadded:: 1.4
|
||||
.. versionchanged:: 2.2
|
||||
|
||||
Renamed from ``graphviz_dot``
|
||||
|
||||
.. rst:directive:option:: name: label
|
||||
:type: text
|
||||
|
||||
.. versionadded:: 1.6
|
||||
|
||||
.. rst:directive:option:: class: class names
|
||||
:type: a list of class names separeted by spaces
|
||||
|
||||
The class name of the graph.
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
There are also these config values:
|
||||
|
||||
.. confval:: graphviz_dot
|
||||
|
||||
|
@ -8,6 +8,11 @@
|
||||
|
||||
This extension is quite simple, and features only one directive:
|
||||
|
||||
.. warning::
|
||||
|
||||
This directive is designed to control only content of document. It could
|
||||
not control sections, labels and so on.
|
||||
|
||||
.. rst:directive:: ifconfig
|
||||
|
||||
Include content of the directive only if the Python expression given as an
|
||||
@ -28,6 +33,6 @@ This extension is quite simple, and features only one directive:
|
||||
def setup(app):
|
||||
app.add_config_value('releaselevel', '', 'env')
|
||||
|
||||
The second argument is the default value, the third should always be ``'env'``
|
||||
for such values (it selects if Sphinx re-reads the documents if the value
|
||||
changes).
|
||||
The second argument is the default value, the third should always be
|
||||
``'env'`` for such values (it selects if Sphinx re-reads the documents if the
|
||||
value changes).
|
||||
|
@ -23,6 +23,7 @@ These extensions are built in and can be activated by respective entries in the
|
||||
autosummary
|
||||
coverage
|
||||
doctest
|
||||
duration
|
||||
extlinks
|
||||
githubpages
|
||||
graphviz
|
||||
|
@ -25,13 +25,19 @@ It adds this directive:
|
||||
graph.
|
||||
|
||||
This directive supports an option called ``parts`` that, if given, must be an
|
||||
integer, advising the directive to remove that many parts of module names
|
||||
from the displayed names. (For example, if all your class names start with
|
||||
``lib.``, you can give ``:parts: 1`` to remove that prefix from the displayed
|
||||
node names.)
|
||||
integer, advising the directive to keep that many dot-separated parts
|
||||
in the displayed names (from right to left). For example, ``parts=1`` will
|
||||
only display class names, without the names of the modules that contain
|
||||
them.
|
||||
|
||||
It also supports a ``private-bases`` flag option; if given, private base
|
||||
classes (those whose name starts with ``_``) will be included.
|
||||
.. versionchanged:: 2.0
|
||||
The value of for ``parts`` can also be negative, indicating how many
|
||||
parts to drop from the left. For example, if all your class names start
|
||||
with ``lib.``, you can give ``:parts: -1`` to remove that prefix from the
|
||||
displayed node names.
|
||||
|
||||
The directive also supports a ``private-bases`` flag option; if given,
|
||||
private base classes (those whose name starts with ``_``) will be included.
|
||||
|
||||
You can use ``caption`` option to give a caption to the diagram.
|
||||
|
||||
@ -92,6 +98,41 @@ It adds this directive:
|
||||
Added ``top-classes`` option to limit the scope of inheritance graphs.
|
||||
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
The following are different inheritance diagrams for the internal
|
||||
``InheritanceDiagram`` class that implements the directive.
|
||||
|
||||
With full names::
|
||||
|
||||
.. inheritance-diagram:: sphinx.ext.inheritance_diagram.InheritanceDiagram
|
||||
|
||||
.. inheritance-diagram:: sphinx.ext.inheritance_diagram.InheritanceDiagram
|
||||
|
||||
|
||||
Showing class names only::
|
||||
|
||||
.. inheritance-diagram:: sphinx.ext.inheritance_diagram.InheritanceDiagram
|
||||
:parts: 1
|
||||
|
||||
.. inheritance-diagram:: sphinx.ext.inheritance_diagram.InheritanceDiagram
|
||||
:parts: 1
|
||||
|
||||
Stopping the diagram at :class:`sphinx.util.docutils.SphinxDirective` (the
|
||||
highest superclass still part of Sphinx), and dropping the common left-most
|
||||
part (``sphinx``) from all names::
|
||||
|
||||
.. inheritance-diagram:: sphinx.ext.inheritance_diagram.InheritanceDiagram
|
||||
:top-classes: sphinx.util.docutils.SphinxDirective
|
||||
:parts: -1
|
||||
|
||||
.. inheritance-diagram:: sphinx.ext.inheritance_diagram.InheritanceDiagram
|
||||
:top-classes: sphinx.util.docutils.SphinxDirective
|
||||
:parts: -1
|
||||
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
|
@ -43,7 +43,7 @@ Configuration
|
||||
-------------
|
||||
|
||||
To use Intersphinx linking, add ``'sphinx.ext.intersphinx'`` to your
|
||||
:confval:`extensions` config value, and use these new config values to activate
|
||||
:confval:`extensions` config value, and use these config values to activate
|
||||
linking:
|
||||
|
||||
.. confval:: intersphinx_mapping
|
||||
@ -148,3 +148,13 @@ project. The following example prints the Intersphinx mapping of the Python 3
|
||||
documentation::
|
||||
|
||||
$ python -msphinx.ext.intersphinx https://docs.python.org/3/objects.inv
|
||||
|
||||
Using Intersphinx with inventory file under Basic Authorization
|
||||
---------------------------------------------------------------
|
||||
|
||||
Intersphinx supports Basic Authorization like this::
|
||||
|
||||
intersphinx_mapping = {'python': ('https://user:password@docs.python.org/3',
|
||||
None)}
|
||||
|
||||
The user and password will be stripped from the URL when generating the links.
|
||||
|
@ -15,7 +15,8 @@ Math support for HTML outputs in Sphinx
|
||||
So mathbase extension is no longer needed.
|
||||
|
||||
Since mathematical notation isn't natively supported by HTML in any way, Sphinx
|
||||
gives a math support to HTML document with several extensions.
|
||||
gives a math support to HTML document with several extensions. These use the
|
||||
reStructuredText math :rst:dir:`directive <math>` and :rst:role:`role <math>`.
|
||||
|
||||
:mod:`sphinx.ext.imgmath` -- Render math as images
|
||||
--------------------------------------------------
|
||||
@ -29,13 +30,39 @@ This extension renders math via LaTeX and dvipng_ or dvisvgm_ into PNG or SVG
|
||||
images. This of course means that the computer where the docs are built must
|
||||
have both programs available.
|
||||
|
||||
There are various config values you can set to influence how the images are
|
||||
built:
|
||||
There are various configuration values you can set to influence how the images
|
||||
are built:
|
||||
|
||||
.. confval:: imgmath_image_format
|
||||
|
||||
The output image format. The default is ``'png'``. It should be either
|
||||
``'png'`` or ``'svg'``.
|
||||
The output image format. The default is ``'png'``. It should be either
|
||||
``'png'`` or ``'svg'``. The image is produced by first executing ``latex``
|
||||
on the TeX mathematical mark-up then (depending on the requested format)
|
||||
either `dvipng`_ or `dvisvgm`_.
|
||||
|
||||
.. confval:: imgmath_use_preview
|
||||
|
||||
``dvipng`` and ``dvisvgm`` both have the ability to collect from LaTeX the
|
||||
"depth" of the rendered math: an inline image should use this "depth" in a
|
||||
``vertical-align`` style to get correctly aligned with surrounding text.
|
||||
|
||||
This mechanism requires the `LaTeX preview package`_ (available as
|
||||
``preview-latex-style`` on Ubuntu xenial). Therefore, the default for this
|
||||
option is ``False`` but it is strongly recommended to set it to ``True``.
|
||||
|
||||
.. versionchanged:: 2.2
|
||||
|
||||
This option can be used with the ``'svg'`` :confval:`imgmath_image_format`.
|
||||
|
||||
.. confval:: imgmath_add_tooltips
|
||||
|
||||
Default: ``True``. If false, do not add the LaTeX code as an "alt" attribute
|
||||
for math images.
|
||||
|
||||
.. confval:: imgmath_font_size
|
||||
|
||||
The font size (in ``pt``) of the displayed math. The default value is
|
||||
``12``. It must be a positive integer.
|
||||
|
||||
.. confval:: imgmath_latex
|
||||
|
||||
@ -53,19 +80,13 @@ built:
|
||||
This value should only contain the path to the latex executable, not further
|
||||
arguments; use :confval:`imgmath_latex_args` for that purpose.
|
||||
|
||||
.. confval:: imgmath_dvipng
|
||||
.. hint::
|
||||
|
||||
The command name with which to invoke ``dvipng``. The default is
|
||||
``'dvipng'``; you may need to set this to a full path if ``dvipng`` is not in
|
||||
the executable search path. This option is only used when
|
||||
``imgmath_image_format`` is set to ``'png'``.
|
||||
|
||||
.. confval:: imgmath_dvisvgm
|
||||
|
||||
The command name with which to invoke ``dvisvgm``. The default is
|
||||
``'dvisvgm'``; you may need to set this to a full path if ``dvisvgm`` is not
|
||||
in the executable search path. This option is only used when
|
||||
``imgmath_image_format`` is ``'svg'``.
|
||||
Some fancy LaTeX mark-up (an example was reported which used TikZ to add
|
||||
various decorations to the equation) require multiple runs of the LaTeX
|
||||
executable. To handle this, set this configuration setting to
|
||||
``'latexmk'`` (or a full path to it) as this Perl script reliably
|
||||
chooses dynamically how many latex runs are needed.
|
||||
|
||||
.. confval:: imgmath_latex_args
|
||||
|
||||
@ -74,48 +95,43 @@ built:
|
||||
|
||||
.. confval:: imgmath_latex_preamble
|
||||
|
||||
Additional LaTeX code to put into the preamble of the short LaTeX files that
|
||||
are used to translate the math snippets. This is empty by default. Use it
|
||||
e.g. to add more packages whose commands you want to use in the math.
|
||||
Additional LaTeX code to put into the preamble of the LaTeX files used to
|
||||
translate the math snippets. This is left empty by default. Use it
|
||||
e.g. to add packages which modify the fonts used for math, such as
|
||||
``'\\usepackage{newtxsf}'`` for sans-serif fonts, or
|
||||
``'\\usepackage{fouriernc}'`` for serif fonts. Indeed, the default LaTeX
|
||||
math fonts have rather thin glyphs which (in HTML output) often do not
|
||||
match well with the font for text.
|
||||
|
||||
.. confval:: imgmath_dvipng
|
||||
|
||||
The command name to invoke ``dvipng``. The default is
|
||||
``'dvipng'``; you may need to set this to a full path if ``dvipng`` is not in
|
||||
the executable search path. This option is only used when
|
||||
``imgmath_image_format`` is set to ``'png'``.
|
||||
|
||||
.. confval:: imgmath_dvipng_args
|
||||
|
||||
Additional arguments to give to dvipng, as a list. The default value is
|
||||
``['-gamma', '1.5', '-D', '110', '-bg', 'Transparent']`` which makes the
|
||||
image a bit darker and larger then it is by default, and produces PNGs with a
|
||||
image a bit darker and larger then it is by default (this compensates
|
||||
somewhat for the thinness of default LaTeX math fonts), and produces PNGs with a
|
||||
transparent background. This option is used only when
|
||||
``imgmath_image_format`` is ``'png'``.
|
||||
|
||||
.. confval:: imgmath_dvisvgm
|
||||
|
||||
The command name to invoke ``dvisvgm``. The default is
|
||||
``'dvisvgm'``; you may need to set this to a full path if ``dvisvgm`` is not
|
||||
in the executable search path. This option is only used when
|
||||
``imgmath_image_format`` is ``'svg'``.
|
||||
|
||||
.. confval:: imgmath_dvisvgm_args
|
||||
|
||||
Additional arguments to give to dvisvgm, as a list. The default value is
|
||||
``['--no-fonts']``. This option is used only when ``imgmath_image_format``
|
||||
is ``'svg'``.
|
||||
|
||||
.. confval:: imgmath_use_preview
|
||||
|
||||
``dvipng`` has the ability to determine the "depth" of the rendered text: for
|
||||
example, when typesetting a fraction inline, the baseline of surrounding text
|
||||
should not be flush with the bottom of the image, rather the image should
|
||||
extend a bit below the baseline. This is what TeX calls "depth". When this
|
||||
is enabled, the images put into the HTML document will get a
|
||||
``vertical-align`` style that correctly aligns the baselines.
|
||||
|
||||
Unfortunately, this only works when the `preview-latex package`_ is
|
||||
installed. Therefore, the default for this option is ``False``.
|
||||
|
||||
Currently this option is only used when ``imgmath_image_format`` is
|
||||
``'png'``.
|
||||
|
||||
.. confval:: imgmath_add_tooltips
|
||||
|
||||
Default: ``True``. If false, do not add the LaTeX code as an "alt" attribute
|
||||
for math images.
|
||||
|
||||
.. confval:: imgmath_font_size
|
||||
|
||||
The font size (in ``pt``) of the displayed math. The default value is
|
||||
``12``. It must be a positive integer.
|
||||
Additional arguments to give to dvisvgm, as a list. The default value is
|
||||
``['--no-fonts']``, which means that ``dvisvgm`` will render glyphs as path
|
||||
elements (cf the `dvisvgm FAQ`_). This option is used only when
|
||||
``imgmath_image_format`` is ``'svg'``.
|
||||
|
||||
|
||||
:mod:`sphinx.ext.mathjax` -- Render math via JavaScript
|
||||
@ -131,7 +147,13 @@ MathJax_ is then loaded and transforms the LaTeX markup to readable math live in
|
||||
the browser.
|
||||
|
||||
Because MathJax (and the necessary fonts) is very large, it is not included in
|
||||
Sphinx.
|
||||
Sphinx but is set to automatically include it from a third-party site.
|
||||
|
||||
.. attention::
|
||||
|
||||
You should use the math :rst:dir:`directive <math>` and
|
||||
:rst:role:`role <math>`, not the native MathJax ``$$``, ``\(``, etc.
|
||||
|
||||
|
||||
.. confval:: mathjax_path
|
||||
|
||||
@ -140,8 +162,9 @@ Sphinx.
|
||||
|
||||
The default is the ``https://`` URL that loads the JS files from the
|
||||
`cdnjs`__ Content Delivery Network. See the `MathJax Getting Started
|
||||
page`__ for details. If you want MathJax to be available offline, you have
|
||||
to download it and set this value to a different path.
|
||||
page`__ for details. If you want MathJax to be available offline or
|
||||
without including resources from a third-party site, you have to
|
||||
download it and set this value to a different path.
|
||||
|
||||
__ https://cdnjs.com
|
||||
|
||||
@ -168,6 +191,8 @@ Sphinx.
|
||||
|
||||
The default is empty (``{}``).
|
||||
|
||||
.. versionadded:: 1.8
|
||||
|
||||
.. confval:: mathjax_config
|
||||
|
||||
The inline configuration options for mathjax. The value is used as a
|
||||
@ -183,6 +208,8 @@ Sphinx.
|
||||
|
||||
The default is empty (not configured).
|
||||
|
||||
.. versionadded:: 1.8
|
||||
|
||||
.. _Using in-line configuration options: https://docs.mathjax.org/en/latest/configuration.html#using-in-line-configuration-options
|
||||
|
||||
:mod:`sphinx.ext.jsmath` -- Render math via JavaScript
|
||||
@ -209,7 +236,8 @@ package jsMath_. It provides this config value:
|
||||
|
||||
|
||||
.. _dvipng: https://savannah.nongnu.org/projects/dvipng/
|
||||
.. _dvisvgm: http://dvisvgm.bplaced.net/
|
||||
.. _dvisvgm: https://dvisvgm.de/
|
||||
.. _dvisvgm FAQ: https://dvisvgm.de/FAQ
|
||||
.. _MathJax: https://www.mathjax.org/
|
||||
.. _jsMath: http://www.math.union.edu/~dpvc/jsmath/
|
||||
.. _preview-latex package: https://www.gnu.org/software/auctex/preview-latex.html
|
||||
.. _LaTeX preview package: https://www.gnu.org/software/auctex/preview-latex.html
|
||||
|
@ -56,7 +56,7 @@ source code files.
|
||||
.. _Google:
|
||||
https://google.github.io/styleguide/pyguide.html#Comments
|
||||
.. _NumPy:
|
||||
https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
|
||||
https://numpydoc.readthedocs.io/en/latest/format.html#docstring-standard
|
||||
.. _Khan Academy:
|
||||
https://github.com/Khan/style-guides/blob/master/style/python.md#docstrings
|
||||
|
||||
|
@ -17,8 +17,9 @@ There are two additional directives when using this extension:
|
||||
``True``.
|
||||
|
||||
.. versionadded:: 1.3.2
|
||||
This directive supports an ``class`` option that determines the class attribute
|
||||
for HTML output. If not given, the class defaults to ``admonition-todo``.
|
||||
This directive supports an ``class`` option that determines the class
|
||||
attribute for HTML output. If not given, the class defaults to
|
||||
``admonition-todo``.
|
||||
|
||||
|
||||
.. rst:directive:: todolist
|
||||
@ -46,8 +47,8 @@ Configuration
|
||||
|
||||
.. confval:: todo_link_only
|
||||
|
||||
If this is ``True``, :rst:dir:`todolist` produce output without file path and line,
|
||||
The default is ``False``.
|
||||
If this is ``True``, :rst:dir:`todolist` produce output without file path and
|
||||
line, The default is ``False``.
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
@ -57,5 +58,5 @@ autodoc provides the following an additional event:
|
||||
|
||||
.. versionadded:: 1.5
|
||||
|
||||
Emitted when a todo is defined. *node* is the defined ``sphinx.ext.todo.todo_node``
|
||||
node.
|
||||
Emitted when a todo is defined. *node* is the defined
|
||||
``sphinx.ext.todo.todo_node`` node.
|
||||
|
@ -108,12 +108,13 @@ Windows
|
||||
.. todo:: Could we start packaging this?
|
||||
|
||||
Most Windows users do not have Python installed by default, so we begin with
|
||||
the installation of Python itself. If you are unsure, open the *Command
|
||||
Prompt* (:kbd:`⊞Win-r` and type :command:`cmd`). Once the command prompt is
|
||||
open, type :command:`python --version` and press Enter. If Python is
|
||||
available, you will see the version of Python printed to the screen. If you do
|
||||
not have Python installed, refer to the `Hitchhikers Guide to Python's`__
|
||||
Python on Windows installation guides. You must install `Python 3`__.
|
||||
the installation of Python itself. To check if you already have Python
|
||||
installed, open the *Command Prompt* (:kbd:`⊞Win-r` and type :command:`cmd`).
|
||||
Once the command prompt is open, type :command:`python --version` and press
|
||||
Enter. If Python is installed, you will see the version of Python printed to
|
||||
the screen. If you do not have Python installed, refer to the `Hitchhikers
|
||||
Guide to Python's`__ Python on Windows installation guides. You must install
|
||||
`Python 3`__.
|
||||
|
||||
Once Python is installed, you can install Sphinx using :command:`pip`. Refer
|
||||
to the :ref:`pip installation instructions <install-pypi>` below for more
|
||||
|
@ -6,7 +6,7 @@ Once Sphinx is :doc:`installed </usage/installation>`, you can proceed with
|
||||
setting up your first Sphinx project. To ease the process of getting started,
|
||||
Sphinx provides a tool, :program:`sphinx-quickstart`, which will generate a
|
||||
documentation source directory and populate it with some defaults. We're going
|
||||
to use the :program:`sphinx-quickstart` tool here, though it's use by no means
|
||||
to use the :program:`sphinx-quickstart` tool here, though its use is by no means
|
||||
necessary.
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ configuration values from a few questions it asks you. To use this, run:
|
||||
|
||||
$ sphinx-quickstart
|
||||
|
||||
Answer each question asked. Be sure to say yes to the ``autodoc`` extension, as
|
||||
Answer each question asked. Be sure to say "yes" to the ``autodoc`` extension, as
|
||||
we will use this later.
|
||||
|
||||
There is also an automatic "API documentation" generator called
|
||||
@ -103,7 +103,7 @@ In Sphinx source files, you can use most features of standard
|
||||
For example, you can add cross-file references in a portable way (which works
|
||||
for all output types) using the :rst:role:`ref` role.
|
||||
|
||||
For an example, if you are viewing the HTML version you can look at the source
|
||||
For an example, if you are viewing the HTML version, you can look at the source
|
||||
for this document -- use the "Show Source" link in the sidebar.
|
||||
|
||||
.. todo:: Update the below link when we add new guides on these.
|
||||
|
@ -372,7 +372,8 @@ Docutils supports the following directives:
|
||||
|
||||
* HTML specifics:
|
||||
|
||||
- :dudir:`meta` (generation of HTML ``<meta>`` tags)
|
||||
- :dudir:`meta`
|
||||
(generation of HTML ``<meta>`` tags, see also :ref:`html-meta` below)
|
||||
- :dudir:`title <metadata-document-title>` (override document title)
|
||||
|
||||
* Influencing markup:
|
||||
@ -538,6 +539,45 @@ You can indent text after a comment start to form multiline comments::
|
||||
Still in the comment.
|
||||
|
||||
|
||||
.. _html-meta:
|
||||
|
||||
HTML Metadata
|
||||
-------------
|
||||
|
||||
The :rst:dir:`meta` directive (:dudir:`ref <meta>`) allows specifying the HTML
|
||||
`metadata element`_ of a Sphinx documentation page. For example, the
|
||||
directive::
|
||||
|
||||
.. meta::
|
||||
:description: The Sphinx documentation builder
|
||||
:keywords: Sphinx, documentation, builder
|
||||
|
||||
will generate the following HTML output:
|
||||
|
||||
.. code:: html
|
||||
|
||||
<meta name="description" content="The Sphinx documentation builder">
|
||||
<meta name="keywords" content="Sphinx, documentation, builder">
|
||||
|
||||
Also, Sphinx will add the keywords as specified in the meta directive to the
|
||||
search index. Thereby, the ``lang`` attribute of the meta element is
|
||||
considered. For example, the directive::
|
||||
|
||||
.. meta::
|
||||
:keywords: backup
|
||||
:keywords lang=en: pleasefindthiskey pleasefindthiskeytoo
|
||||
:keywords lang=de: bittediesenkeyfinden
|
||||
|
||||
adds the following words to the search indices of builds with different language
|
||||
configurations:
|
||||
|
||||
* ``pleasefindthiskey``, ``pleasefindthiskeytoo`` to *English* builds;
|
||||
* ``bittediesenkeyfinden`` to *German* builds;
|
||||
* ``backup`` to builds in all languages.
|
||||
|
||||
.. _metadata element: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta
|
||||
|
||||
|
||||
Source encoding
|
||||
---------------
|
||||
|
||||
|
@ -36,8 +36,8 @@ tables of contents. The ``toctree`` directive is the central element.
|
||||
|
||||
.. note::
|
||||
|
||||
For local tables of contents, use the standard reST :dudir:`contents
|
||||
directive <table-of-contents>`.
|
||||
To create table of contents for current document (.rst file), use the
|
||||
standard reST :dudir:`contents directive <table-of-contents>`.
|
||||
|
||||
.. rst:directive:: toctree
|
||||
|
||||
@ -441,7 +441,7 @@ If highlighting with the selected language fails (i.e. Pygments emits an
|
||||
want to ensure consistent highlighting, you should fix your version of
|
||||
Pygments.
|
||||
|
||||
__ http://pygments.org/docs/lexers/
|
||||
__ http://pygments.org/docs/lexers
|
||||
|
||||
.. rst:directive:: .. highlight:: language
|
||||
|
||||
@ -453,15 +453,29 @@ __ http://pygments.org/docs/lexers/
|
||||
As discussed previously, *language* can be any lexer alias supported by
|
||||
Pygments.
|
||||
|
||||
**Additional options**
|
||||
.. rubric:: options
|
||||
|
||||
Pygments can generate line numbers for code blocks. To enable this, use the
|
||||
``linenothreshold`` option. ::
|
||||
.. rst:directive:option:: linenothreshold: threshold
|
||||
:type: number (optional)
|
||||
|
||||
.. highlight:: python
|
||||
:linenothreshold: 5
|
||||
Enable to generate line numbers for code blocks.
|
||||
|
||||
This will produce line numbers for all code blocks longer than five lines.
|
||||
This option takes an optional number as threshold parameter. If any
|
||||
threshold given, the directive will produce line numbers only for the code
|
||||
blocks longer than N lines. If not given, line numbers will be produced
|
||||
for all of code blocks.
|
||||
|
||||
Example::
|
||||
|
||||
.. highlight:: python
|
||||
:linenothreshold: 5
|
||||
|
||||
.. rst:directive:option:: force
|
||||
:type: no value
|
||||
|
||||
If given, minor errors on highlighting are ignored.
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
.. rst:directive:: .. code-block:: [language]
|
||||
|
||||
@ -477,67 +491,99 @@ __ http://pygments.org/docs/lexers/
|
||||
:rst:dir:`highlight` directive will be used. If not set,
|
||||
:confval:`highlight_language` will be used.
|
||||
|
||||
**Additional options**
|
||||
|
||||
Pygments can generate line numbers for code blocks. To enable this for, use
|
||||
the ``linenos`` flag option. ::
|
||||
|
||||
.. code-block:: ruby
|
||||
:linenos:
|
||||
|
||||
Some more Ruby code.
|
||||
|
||||
The first line number can be selected with the ``lineno-start`` option. If
|
||||
present, ``linenos`` flag is automatically activated::
|
||||
|
||||
.. code-block:: ruby
|
||||
:lineno-start: 10
|
||||
|
||||
Some more Ruby code, with line numbering starting at 10.
|
||||
|
||||
Additionally, an ``emphasize-lines`` option can be given to have Pygments
|
||||
emphasize particular lines::
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 3,5
|
||||
|
||||
def some_function():
|
||||
interesting = False
|
||||
print 'This line is highlighted.'
|
||||
print 'This one is not...'
|
||||
print '...but this one is.'
|
||||
|
||||
A ``caption`` option can be given to show that name before the code block.
|
||||
A ``name`` option can be provided implicit target name that can be
|
||||
referenced by using :rst:role:`ref`. For example::
|
||||
|
||||
.. code-block:: python
|
||||
:caption: this.py
|
||||
:name: this-py
|
||||
|
||||
print 'Explicit is better than implicit.'
|
||||
|
||||
A ``dedent`` option can be given to strip indentation characters from the
|
||||
code block. For example::
|
||||
|
||||
.. code-block:: ruby
|
||||
:dedent: 4
|
||||
|
||||
some ruby code
|
||||
|
||||
.. versionchanged:: 1.1
|
||||
The ``emphasize-lines`` option has been added.
|
||||
|
||||
.. versionchanged:: 1.3
|
||||
The ``lineno-start``, ``caption``, ``name`` and ``dedent`` options have
|
||||
been added.
|
||||
|
||||
.. versionchanged:: 1.6.6
|
||||
LaTeX supports the ``emphasize-lines`` option.
|
||||
|
||||
.. versionchanged:: 2.0
|
||||
The ``language`` argument becomes optional.
|
||||
|
||||
.. rubric:: options
|
||||
|
||||
.. rst:directive:option:: linenos
|
||||
:type: no value
|
||||
|
||||
Enable to generate line numbers for the code block::
|
||||
|
||||
.. code-block:: ruby
|
||||
:linenos:
|
||||
|
||||
Some more Ruby code.
|
||||
|
||||
.. rst:directive:option:: lineno-start: number
|
||||
:type: number
|
||||
|
||||
Set the first line number of the code block. If present, ``linenos``
|
||||
option is also automatically activated::
|
||||
|
||||
.. code-block:: ruby
|
||||
:lineno-start: 10
|
||||
|
||||
Some more Ruby code, with line numbering starting at 10.
|
||||
|
||||
.. versionadded:: 1.3
|
||||
|
||||
.. rst:directive:option:: emphasize-lines: line numbers
|
||||
:type: comma separated numbers
|
||||
|
||||
Emphasize particular lines of the code block::
|
||||
|
||||
.. code-block:: python
|
||||
:emphasize-lines: 3,5
|
||||
|
||||
def some_function():
|
||||
interesting = False
|
||||
print 'This line is highlighted.'
|
||||
print 'This one is not...'
|
||||
print '...but this one is.'
|
||||
|
||||
.. versionadded:: 1.1
|
||||
.. versionchanged:: 1.6.6
|
||||
LaTeX supports the ``emphasize-lines`` option.
|
||||
|
||||
.. rst:directive:option: force
|
||||
:type: no value
|
||||
|
||||
Ignore minor errors on highlighting
|
||||
|
||||
.. versionchanged:: 2.1
|
||||
|
||||
.. rst:directive:option:: caption: caption of code block
|
||||
:type: text
|
||||
|
||||
Set a caption to the code block.
|
||||
|
||||
.. versionadded:: 1.3
|
||||
|
||||
.. rst:directive:option:: name: a label for hyperlink
|
||||
:type: text
|
||||
|
||||
Define implicit target name that can be referenced by using
|
||||
:rst:role:`ref`. For example::
|
||||
|
||||
.. code-block:: python
|
||||
:caption: this.py
|
||||
:name: this-py
|
||||
|
||||
print 'Explicit is better than implicit.'
|
||||
|
||||
.. versionadded:: 1.3
|
||||
|
||||
.. rst:directive:option:: dedent: number
|
||||
:type: number
|
||||
|
||||
Strip indentation characters from the code block. For example::
|
||||
|
||||
.. code-block:: ruby
|
||||
:dedent: 4
|
||||
|
||||
some ruby code
|
||||
|
||||
.. versionadded:: 1.3
|
||||
|
||||
.. rst:directive:option:: force
|
||||
:type: no value
|
||||
|
||||
If given, minor errors on highlighting are ignored.
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
.. rst:directive:: .. literalinclude:: filename
|
||||
|
||||
Longer displays of verbatim text may be included by storing the example text
|
||||
@ -630,6 +676,8 @@ __ http://pygments.org/docs/lexers/
|
||||
This shows the diff between ``example.py`` and ``example.py.orig`` with
|
||||
unified diff format.
|
||||
|
||||
A ``force`` option can ignore minor errors on highlighting.
|
||||
|
||||
.. versionchanged:: 0.4.3
|
||||
Added the ``encoding`` option.
|
||||
|
||||
@ -651,6 +699,9 @@ __ http://pygments.org/docs/lexers/
|
||||
With both ``start-after`` and ``lines`` in use, the first line as per
|
||||
``start-after`` is considered to be with line number ``1`` for ``lines``.
|
||||
|
||||
.. versionchanged:: 2.1
|
||||
Added the ``force`` option.
|
||||
|
||||
.. _glossary-directive:
|
||||
|
||||
Glossary
|
||||
@ -686,8 +737,8 @@ Glossary
|
||||
|
||||
(When the glossary is sorted, the first term determines the sort order.)
|
||||
|
||||
If you want to specify "grouping key" for general index entries, you can put a "key"
|
||||
as "term : key". For example::
|
||||
If you want to specify "grouping key" for general index entries, you can put
|
||||
a "key" as "term : key". For example::
|
||||
|
||||
.. glossary::
|
||||
|
||||
@ -697,12 +748,12 @@ Glossary
|
||||
|
||||
Note that "key" is used for grouping key as is.
|
||||
The "key" isn't normalized; key "A" and "a" become different groups.
|
||||
The whole characters in "key" is used instead of a first character; it is used for
|
||||
"Combining Character Sequence" and "Surrogate Pairs" grouping key.
|
||||
The whole characters in "key" is used instead of a first character; it is
|
||||
used for "Combining Character Sequence" and "Surrogate Pairs" grouping key.
|
||||
|
||||
In i18n situation, you can specify "localized term : key" even if original text only
|
||||
have "term" part. In this case, translated "localized term" will be categorized in
|
||||
"key" group.
|
||||
In i18n situation, you can specify "localized term : key" even if original
|
||||
text only have "term" part. In this case, translated "localized term" will be
|
||||
categorized in "key" group.
|
||||
|
||||
.. versionadded:: 0.6
|
||||
You can now give the glossary directive a ``:sorted:`` flag that will
|
||||
@ -958,16 +1009,16 @@ this reason, the following directive exists:
|
||||
.. warning::
|
||||
|
||||
Tables with more than 30 rows are rendered using ``longtable``, not
|
||||
``tabulary``, in order to allow pagebreaks. The ``L``, ``R``, ... specifiers
|
||||
do not work for these tables.
|
||||
``tabulary``, in order to allow pagebreaks. The ``L``, ``R``, ...
|
||||
specifiers do not work for these tables.
|
||||
|
||||
Tables that contain list-like elements such as object descriptions,
|
||||
blockquotes or any kind of lists cannot be set out of the box with
|
||||
``tabulary``. They are therefore set with the standard LaTeX ``tabular`` (or
|
||||
``longtable``) environment if you don't give a ``tabularcolumns`` directive.
|
||||
If you do, the table will be set with ``tabulary`` but you must use the
|
||||
``p{width}`` construct (or Sphinx's ``\X`` and ``\Y`` specifiers described
|
||||
below) for the columns containing these elements.
|
||||
``tabulary``. They are therefore set with the standard LaTeX ``tabular``
|
||||
(or ``longtable``) environment if you don't give a ``tabularcolumns``
|
||||
directive. If you do, the table will be set with ``tabulary`` but you
|
||||
must use the ``p{width}`` construct (or Sphinx's ``\X`` and ``\Y``
|
||||
specifiers described below) for the columns containing these elements.
|
||||
|
||||
Literal blocks do not work with ``tabulary`` at all, so tables containing
|
||||
a literal block are always set with ``tabular``. The verbatim environment
|
||||
@ -996,10 +1047,11 @@ this reason, the following directive exists:
|
||||
.. versionchanged:: 1.6
|
||||
|
||||
Merged cells from complex grid tables (either multi-row, multi-column, or
|
||||
both) now allow blockquotes, lists, literal blocks, ... as do regular cells.
|
||||
both) now allow blockquotes, lists, literal blocks, ... as do regular
|
||||
cells.
|
||||
|
||||
Sphinx's merged cells interact well with ``p{width}``, ``\X{a}{b}``, ``Y{f}``
|
||||
and tabulary's columns.
|
||||
Sphinx's merged cells interact well with ``p{width}``, ``\X{a}{b}``,
|
||||
``\Y{f}`` and tabulary's columns.
|
||||
|
||||
.. note::
|
||||
|
||||
@ -1087,7 +1139,7 @@ derived forms), but provides enough to allow context-free grammars to be
|
||||
displayed in a way that causes uses of a symbol to be rendered as hyperlinks to
|
||||
the definition of the symbol. There is this directive:
|
||||
|
||||
.. rst:directive:: .. productionlist:: [name]
|
||||
.. rst:directive:: .. productionlist:: [productionGroup]
|
||||
|
||||
This directive is used to enclose a group of productions. Each production
|
||||
is given on a single line and consists of a name, separated by a colon from
|
||||
@ -1095,16 +1147,24 @@ the definition of the symbol. There is this directive:
|
||||
continuation line must begin with a colon placed at the same column as in
|
||||
the first line.
|
||||
|
||||
The argument to :rst:dir:`productionlist` serves to distinguish different
|
||||
sets of production lists that belong to different grammars.
|
||||
The *productionGroup* argument to :rst:dir:`productionlist` serves to
|
||||
distinguish different sets of production lists that belong to different
|
||||
grammars. Multiple production lists with the same *productionGroup* thus
|
||||
define rules in the same scope.
|
||||
|
||||
Blank lines are not allowed within ``productionlist`` directive arguments.
|
||||
|
||||
The definition can contain token names which are marked as interpreted text
|
||||
(e.g. ``sum ::= `integer` "+" `integer```) -- this generates
|
||||
(e.g. "``sum ::= `integer` "+" `integer```") -- this generates
|
||||
cross-references to the productions of these tokens. Outside of the
|
||||
production list, you can reference to token productions using
|
||||
:rst:role:`token`.
|
||||
However, if you have given a *productionGroup* argument you must prefix the
|
||||
token name in the cross-reference with the group name and a colon,
|
||||
e.g., "``myGroup:sum``" instead of just "``sum``".
|
||||
If the group should not be shown in the title of the link either
|
||||
an explicit title can be given (e.g., "``myTitle <myGroup:sum>``"),
|
||||
or the target can be prefixed with a tilde (e.g., "``~myGroup:sum``").
|
||||
|
||||
Note that no further reST parsing is done in the production, so that you
|
||||
don't have to escape ``*`` or ``|`` characters.
|
||||
|
@ -128,17 +128,28 @@ declarations:
|
||||
|
||||
This directive will also cause an entry in the global module index.
|
||||
|
||||
The ``platform`` option, if present, is a comma-separated list of the
|
||||
platforms on which the module is available (if it is available on all
|
||||
platforms, the option should be omitted). The keys are short identifiers;
|
||||
examples that are in use include "IRIX", "Mac", "Windows", and "Unix". It is
|
||||
important to use a key which has already been used when applicable.
|
||||
.. rubric:: options
|
||||
|
||||
The ``synopsis`` option should consist of one sentence describing the
|
||||
module's purpose -- it is currently only used in the Global Module Index.
|
||||
.. rst:directive:option:: platform: platforms
|
||||
:type: comma separated list
|
||||
|
||||
The ``deprecated`` option can be given (with no value) to mark a module as
|
||||
deprecated; it will be designated as such in various locations then.
|
||||
Indicate platforms which the module is available (if it is available on
|
||||
all platforms, the option should be omitted). The keys are short
|
||||
identifiers; examples that are in use include "IRIX", "Mac", "Windows"
|
||||
and "Unix". It is important to use a key which has already been used when
|
||||
applicable.
|
||||
|
||||
.. rst:directive:option:: synopsis: purpose
|
||||
:type: text
|
||||
|
||||
Consist of one sentence describing the module's purpose -- it is currently
|
||||
only used in the Global Module Index.
|
||||
|
||||
.. rst:directive:option:: deprecated
|
||||
:type: no argument
|
||||
|
||||
Mark a module as deprecated; it will be designated as such in various
|
||||
locations then.
|
||||
|
||||
.. rst:directive:: .. py:currentmodule:: name
|
||||
|
||||
@ -169,12 +180,33 @@ The following directives are provided for module and class contents:
|
||||
This information can (in any ``py`` directive) optionally be given in a
|
||||
structured form, see :ref:`info-field-lists`.
|
||||
|
||||
.. rubric:: options
|
||||
|
||||
.. rst:directive:option:: async
|
||||
:type: no value
|
||||
|
||||
Indicate the function is an async function.
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
.. rst:directive:: .. py:data:: name
|
||||
|
||||
Describes global data in a module, including both variables and values used
|
||||
as "defined constants." Class and object attributes are not documented
|
||||
using this environment.
|
||||
|
||||
.. rubric:: options
|
||||
|
||||
.. rst:directive:option:: type: type of the variable
|
||||
:type: text
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
.. rst:directive:option:: value: initial value of the variable
|
||||
:type: text
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
.. rst:directive:: .. py:exception:: name
|
||||
|
||||
Describes an exception class. The signature can, but need not include
|
||||
@ -209,6 +241,18 @@ The following directives are provided for module and class contents:
|
||||
information about the type of the data to be expected and whether it may be
|
||||
changed directly.
|
||||
|
||||
.. rubric:: options
|
||||
|
||||
.. rst:directive:option:: type: type of the attribute
|
||||
:type: text
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
.. rst:directive:option:: value: initial value of the attribute
|
||||
:type: text
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
.. rst:directive:: .. py:method:: name(parameters)
|
||||
|
||||
Describes an object method. The parameters should not include the ``self``
|
||||
@ -216,6 +260,44 @@ The following directives are provided for module and class contents:
|
||||
described for ``function``. See also :ref:`signatures` and
|
||||
:ref:`info-field-lists`.
|
||||
|
||||
.. rubric:: options
|
||||
|
||||
.. rst:directive:option:: abstractmethod
|
||||
:type: no value
|
||||
|
||||
Indicate the method is an abstract method.
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
.. rst:directive:option:: async
|
||||
:type: no value
|
||||
|
||||
Indicate the method is an async method.
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
.. rst:directive:option:: classmethod
|
||||
:type: no value
|
||||
|
||||
Indicate the method is a class method.
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
.. rst:directive:option:: property
|
||||
:type: no value
|
||||
|
||||
Indicate the method is a property.
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
.. rst:directive:option:: staticmethod
|
||||
:type: no value
|
||||
|
||||
Indicate the method is a static method.
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
|
||||
.. rst:directive:: .. py:staticmethod:: name(parameters)
|
||||
|
||||
Like :rst:dir:`py:method`, but indicates that the method is a static method.
|
||||
@ -296,6 +378,9 @@ Info field lists
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
.. versionadded:: 0.4
|
||||
.. versionchanged:: 3.0
|
||||
|
||||
meta fields are added.
|
||||
|
||||
Inside Python object description directives, reST field lists with these fields
|
||||
are recognized and formatted nicely:
|
||||
@ -309,6 +394,10 @@ are recognized and formatted nicely:
|
||||
* ``vartype``: Type of a variable. Creates a link if possible.
|
||||
* ``returns``, ``return``: Description of the return value.
|
||||
* ``rtype``: Return type. Creates a link if possible.
|
||||
* ``meta``: Add metadata to description of the python object. The metadata will
|
||||
not be shown on output document. For example, ``:meta private:`` indicates
|
||||
the python object is private member. It is used in
|
||||
:py:mod:`sphinx.ext.autodoc` for filtering members.
|
||||
|
||||
.. note::
|
||||
|
||||
@ -699,7 +788,8 @@ visibility statement (``public``, ``private`` or ``protected``).
|
||||
|
||||
.. cpp:enum-struct:: protected MyScopedVisibilityEnum : std::underlying_type<MySpecificEnum>::type
|
||||
|
||||
A scoped enum with non-default visibility, and with a specified underlying type.
|
||||
A scoped enum with non-default visibility, and with a specified
|
||||
underlying type.
|
||||
|
||||
.. rst:directive:: .. cpp:enumerator:: name
|
||||
.. cpp:enumerator:: name = constant
|
||||
@ -739,7 +829,8 @@ visibility statement (``public``, ``private`` or ``protected``).
|
||||
**Valid Expressions**
|
||||
|
||||
- :cpp:expr:`*r`, when :cpp:expr:`r` is dereferenceable.
|
||||
- :cpp:expr:`++r`, with return type :cpp:expr:`It&`, when :cpp:expr:`r` is incrementable.
|
||||
- :cpp:expr:`++r`, with return type :cpp:expr:`It&`, when
|
||||
:cpp:expr:`r` is incrementable.
|
||||
|
||||
This will render as follows:
|
||||
|
||||
@ -778,11 +869,12 @@ Anonymous Entities
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
C++ supports anonymous namespaces, classes, enums, and unions.
|
||||
For the sake of documentation they must be given some name that starts with ``@``,
|
||||
e.g., ``@42`` or ``@data``.
|
||||
For the sake of documentation they must be given some name that starts with
|
||||
``@``, e.g., ``@42`` or ``@data``.
|
||||
These names can also be used in cross-references and (type) expressions,
|
||||
though nested symbols will be found even when omitted.
|
||||
The ``@...`` name will always be rendered as **[anonymous]** (possibly as a link).
|
||||
The ``@...`` name will always be rendered as **[anonymous]** (possibly as a
|
||||
link).
|
||||
|
||||
Example::
|
||||
|
||||
@ -814,8 +906,8 @@ Explicit ref: :cpp:var:`Data::@data::a`. Short-hand ref: :cpp:var:`Data::a`.
|
||||
Aliasing Declarations
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Sometimes it may be helpful list declarations elsewhere than their main documentation,
|
||||
e.g., when creating a synopsis of a class interface.
|
||||
Sometimes it may be helpful list declarations elsewhere than their main
|
||||
documentation, e.g., when creating a synopsis of a class interface.
|
||||
The following directive can be used for this purpose.
|
||||
|
||||
.. rst:directive:: .. cpp:alias:: name or function signature
|
||||
@ -1058,19 +1150,21 @@ These roles link to the given declaration types:
|
||||
be properly qualified relative to the position of the link.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
The :rst:role:`cpp:struct` role as alias for the :rst:role:`cpp:class` role.
|
||||
The :rst:role:`cpp:struct` role as alias for the :rst:role:`cpp:class`
|
||||
role.
|
||||
|
||||
.. admonition:: Note on References with Templates Parameters/Arguments
|
||||
|
||||
These roles follow the Sphinx :ref:`xref-syntax` rules. This means care must be
|
||||
taken when referencing a (partial) template specialization, e.g. if the link looks like
|
||||
this: ``:cpp:class:`MyClass<int>```.
|
||||
These roles follow the Sphinx :ref:`xref-syntax` rules. This means care must
|
||||
be taken when referencing a (partial) template specialization, e.g. if the
|
||||
link looks like this: ``:cpp:class:`MyClass<int>```.
|
||||
This is interpreted as a link to ``int`` with a title of ``MyClass``.
|
||||
In this case, escape the opening angle bracket with a backslash,
|
||||
like this: ``:cpp:class:`MyClass\<int>```.
|
||||
|
||||
When a custom title is not needed it may be useful to use the roles for inline expressions,
|
||||
:rst:role:`cpp:expr` and :rst:role:`cpp:texpr`, where angle brackets do not need escaping.
|
||||
When a custom title is not needed it may be useful to use the roles for
|
||||
inline expressions, :rst:role:`cpp:expr` and :rst:role:`cpp:texpr`, where
|
||||
angle brackets do not need escaping.
|
||||
|
||||
Declarations without template parameters and template arguments
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -1084,7 +1178,7 @@ Overloaded (member) functions
|
||||
|
||||
When a (member) function is referenced using just its name, the reference
|
||||
will point to an arbitrary matching overload.
|
||||
The :rst:role:`cpp:any` and :rst:role:`cpp:func` roles will an alternative
|
||||
The :rst:role:`cpp:any` and :rst:role:`cpp:func` roles use an alternative
|
||||
format, which simply is a complete function declaration.
|
||||
This will resolve to the exact matching overload.
|
||||
As example, consider the following class declaration:
|
||||
@ -1104,7 +1198,8 @@ References using the :rst:role:`cpp:func` role:
|
||||
- Specific overload: ``void C::f()``, :cpp:func:`void C::f()`
|
||||
- Specific overload: ``void C::f(int)``, :cpp:func:`void C::f(int)`
|
||||
- Specific overload: ``void C::f(double)``, :cpp:func:`void C::f(double)`
|
||||
- Specific overload: ``void C::f(double) const``, :cpp:func:`void C::f(double) const`
|
||||
- Specific overload: ``void C::f(double) const``,
|
||||
:cpp:func:`void C::f(double) const`
|
||||
|
||||
Note that the :confval:`add_function_parentheses` configuration variable
|
||||
does not influence specific overload references.
|
||||
@ -1133,8 +1228,9 @@ and template arguments for the prefix of qualified names. For example:
|
||||
- ``template\<typename TOuter> template\<typename TInner> Wrapper::Outer<TOuter>::Inner``
|
||||
(:cpp:class:`template\<typename TOuter> template\<typename TInner> Wrapper::Outer<TOuter>::Inner`)
|
||||
|
||||
Currently the lookup only succeed if the template parameter identifiers are equal strings.
|
||||
That is, ``template\<typename UOuter> Wrapper::Outer`` will not work.
|
||||
Currently the lookup only succeed if the template parameter identifiers are
|
||||
equal strings. That is, ``template\<typename UOuter> Wrapper::Outer`` will not
|
||||
work.
|
||||
|
||||
As a shorthand notation, if a template parameter list is omitted,
|
||||
then the lookup will assume either a primary template or a non-template,
|
||||
@ -1295,8 +1391,6 @@ The JavaScript domain (name **js**) provides the following directives:
|
||||
specified. If this option is specified, the directive will only update the
|
||||
current module name.
|
||||
|
||||
To clear the current module, set the module name to ``null`` or ``None``
|
||||
|
||||
.. versionadded:: 1.6
|
||||
|
||||
.. rst:directive:: .. js:function:: name(signature)
|
||||
@ -1404,6 +1498,43 @@ The reStructuredText domain (name **rst**) provides the following directives:
|
||||
|
||||
Bar description.
|
||||
|
||||
.. rst:directive:: .. rst:directive:option:: name
|
||||
|
||||
Describes an option for reST directive. The *name* can be a single option
|
||||
name or option name with arguments which separated with colon (``:``).
|
||||
For example::
|
||||
|
||||
.. rst:directive:: toctree
|
||||
|
||||
.. rst:directive:option:: caption: caption of ToC
|
||||
|
||||
.. rst:directive:option:: glob
|
||||
|
||||
will be rendered as:
|
||||
|
||||
.. rst:directive:: toctree
|
||||
:noindex:
|
||||
|
||||
.. rst:directive:option:: caption: caption of ToC
|
||||
|
||||
.. rst:directive:option:: glob
|
||||
|
||||
.. rubric:: options
|
||||
|
||||
.. rst:directive:option:: type: description of argument
|
||||
:type: text
|
||||
|
||||
Describe the type of option value.
|
||||
|
||||
For example::
|
||||
|
||||
.. rst:directive:: toctree
|
||||
|
||||
.. rst:directive:option:: maxdepth
|
||||
:type: integer or no value
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
.. rst:directive:: .. rst:role:: name
|
||||
|
||||
Describes a reST role. For example::
|
||||
@ -1430,7 +1561,7 @@ These roles are provided to refer to the described objects:
|
||||
The Math Domain
|
||||
---------------
|
||||
|
||||
The math domain (name **math**) provides the following roles::
|
||||
The math domain (name **math**) provides the following roles:
|
||||
|
||||
.. rst:role:: math:numref
|
||||
|
||||
|
@ -30,6 +30,12 @@ At the moment, these metadata fields are recognized:
|
||||
|
||||
:tocdepth: 2
|
||||
|
||||
.. note::
|
||||
|
||||
This metadata effects to the depth of local toctree. But it does not
|
||||
effect to the depth of *global* toctree. So this would not be change
|
||||
the sidebar of some themes which uses global one.
|
||||
|
||||
.. versionadded:: 0.4
|
||||
|
||||
``nocomments``
|
||||
|
@ -189,8 +189,8 @@ Referencing downloadable files
|
||||
|
||||
When you use this role, the referenced file is automatically marked for
|
||||
inclusion in the output when building (obviously, for HTML output only).
|
||||
All downloadable files are put into the ``_downloads`` subdirectory of the
|
||||
output directory; duplicate filenames are handled.
|
||||
All downloadable files are put into a ``_downloads/<unique hash>/``
|
||||
subdirectory of the output directory; duplicate filenames are handled.
|
||||
|
||||
An example::
|
||||
|
||||
|
@ -151,6 +151,10 @@ These themes are:
|
||||
dimension string such as '70em' or '50%'. Use 'none' if you don't
|
||||
want a width limit. Defaults may depend on the theme (often 800px).
|
||||
|
||||
- **navigation_with_keys** (true or false): Allow navigating to the
|
||||
previous/next page using the keyboard's left and right arrows. Defaults to
|
||||
``False``.
|
||||
|
||||
**alabaster**
|
||||
`Alabaster theme`_ is a modified "Kr" Sphinx theme from @kennethreitz
|
||||
(especially as used in his Requests project), which was itself originally
|
||||
@ -237,6 +241,8 @@ These themes are:
|
||||
- **documentwidth** (CSS length): Width of the document (without sidebar),
|
||||
default 50em.
|
||||
- **sidebarwidth** (CSS length): Width of the sidebar, default 20em.
|
||||
- **rightsidebar** (true or false): Put the sidebar on the right side.
|
||||
Defaults to ``True``.
|
||||
- **bgcolor** (CSS color): Background color.
|
||||
- **headerbg** (CSS value for "background"): background for the header area,
|
||||
default a grayish gradient.
|
||||
|
2323
package-lock.json
generated
2323
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -11,10 +11,10 @@
|
||||
"url": "https://github.com/sphinx-doc/sphinx/issues"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jasmine-core": "^3.1.0",
|
||||
"karma": "^3.0.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"jasmine-core": "^3.4.0",
|
||||
"karma": "^4.0.0",
|
||||
"karma-chrome-launcher": "^3.0.0",
|
||||
"karma-firefox-launcher": "^1.1.0",
|
||||
"karma-jasmine": "^1.1.2"
|
||||
"karma-jasmine": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
10
setup.cfg
10
setup.cfg
@ -5,9 +5,6 @@ license_file = LICENSE
|
||||
tag_build = .dev
|
||||
tag_date = true
|
||||
|
||||
[bdist_wheel]
|
||||
universal = 1
|
||||
|
||||
[aliases]
|
||||
release = egg_info -Db ''
|
||||
upload = upload --sign --identity=36580288
|
||||
@ -43,6 +40,8 @@ paths =
|
||||
.
|
||||
|
||||
[mypy]
|
||||
python_version = 3.5
|
||||
disallow_incomplete_defs = True
|
||||
show_column_numbers = True
|
||||
show_error_context = True
|
||||
ignore_missing_imports = True
|
||||
@ -55,6 +54,11 @@ strict_optional = False
|
||||
filterwarnings =
|
||||
all
|
||||
ignore::DeprecationWarning:docutils.io
|
||||
markers =
|
||||
sphinx
|
||||
apidoc
|
||||
setup_command
|
||||
test_params
|
||||
|
||||
[coverage:run]
|
||||
branch = True
|
||||
|
27
setup.py
27
setup.py
@ -25,7 +25,7 @@ install_requires = [
|
||||
'Pygments>=2.0',
|
||||
'docutils>=0.12',
|
||||
'snowballstemmer>=1.1',
|
||||
'babel>=1.3,!=2.0',
|
||||
'babel>=1.3',
|
||||
'alabaster>=0.7,<0.8',
|
||||
'imagesize',
|
||||
'requests>=2.5.0',
|
||||
@ -38,16 +38,21 @@ extras_require = {
|
||||
':sys_platform=="win32"': [
|
||||
'colorama>=0.3.5',
|
||||
],
|
||||
'test': [
|
||||
'mock',
|
||||
'pytest',
|
||||
'pytest-cov',
|
||||
'html5lib',
|
||||
'docs': [
|
||||
'sphinxcontrib-websupport',
|
||||
],
|
||||
'lint': [
|
||||
'flake8>=3.5.0',
|
||||
'flake8-import-order',
|
||||
'mypy>=0.590',
|
||||
'mypy>=0.761',
|
||||
'docutils-stubs',
|
||||
],
|
||||
'test': [
|
||||
'pytest < 5.3.3',
|
||||
'pytest-cov',
|
||||
'html5lib',
|
||||
'typed_ast', # for py35-37
|
||||
],
|
||||
}
|
||||
|
||||
# Provide a "compile_catalog" command that also creates the translated
|
||||
@ -173,6 +178,11 @@ setup(
|
||||
author_email='georg@python.org',
|
||||
description='Python documentation generator',
|
||||
long_description=long_desc,
|
||||
long_description_content_type='text/x-rst',
|
||||
project_urls={
|
||||
"Code": "https://github.com/sphinx-doc/sphinx",
|
||||
"Issue tracker": "https://github.com/sphinx-doc/sphinx/issues",
|
||||
},
|
||||
zip_safe=False,
|
||||
classifiers=[
|
||||
'Development Status :: 5 - Production/Stable',
|
||||
@ -213,6 +223,9 @@ setup(
|
||||
],
|
||||
platforms='any',
|
||||
packages=find_packages(exclude=['tests', 'utils']),
|
||||
package_data = {
|
||||
'sphinx': ['py.typed'],
|
||||
},
|
||||
include_package_data=True,
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
The Sphinx documentation toolchain.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -32,8 +32,8 @@ if 'PYTHONWARNINGS' not in os.environ:
|
||||
warnings.filterwarnings('ignore', "'U' mode is deprecated",
|
||||
DeprecationWarning, module='docutils.io')
|
||||
|
||||
__version__ = '2.1.0+'
|
||||
__released__ = '2.1.0' # used when Sphinx builds its own docs
|
||||
__version__ = '3.0.0+'
|
||||
__released__ = '3.0.0' # used when Sphinx builds its own docs
|
||||
|
||||
#: Version info for better programmatic use.
|
||||
#:
|
||||
@ -43,7 +43,7 @@ __released__ = '2.1.0' # used when Sphinx builds its own docs
|
||||
#:
|
||||
#: .. versionadded:: 1.2
|
||||
#: Before version 1.2, check the string ``sphinx.__version__``.
|
||||
version_info = (2, 1, 0, 'beta', 0)
|
||||
version_info = (3, 0, 0, 'beta', 0)
|
||||
|
||||
package_dir = path.abspath(path.dirname(__file__))
|
||||
|
||||
@ -56,8 +56,8 @@ if __version__.endswith('+'):
|
||||
__version__ = __version__[:-1] # remove '+' for PEP-440 version spec.
|
||||
try:
|
||||
ret = subprocess.run(['git', 'show', '-s', '--pretty=format:%h'],
|
||||
stdout=PIPE, stderr=PIPE, encoding='ascii')
|
||||
stdout=PIPE, stderr=PIPE)
|
||||
if ret.stdout:
|
||||
__display_version__ += '/' + ret.stdout.strip()
|
||||
__display_version__ += '/' + ret.stdout.decode('ascii').strip()
|
||||
except Exception:
|
||||
pass
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
The Sphinx documentation toolchain.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -4,20 +4,21 @@
|
||||
|
||||
Additional docutils nodes.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import warnings
|
||||
from typing import Any, Dict, List, Sequence
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.nodes import Node
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx30Warning, RemovedInSphinx40Warning
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, List, Sequence # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.application import Sphinx
|
||||
|
||||
|
||||
class translatable(nodes.Node):
|
||||
@ -34,18 +35,15 @@ class translatable(nodes.Node):
|
||||
Because they are used at final step; extraction.
|
||||
"""
|
||||
|
||||
def preserve_original_messages(self):
|
||||
# type: () -> None
|
||||
def preserve_original_messages(self) -> None:
|
||||
"""Preserve original translatable messages."""
|
||||
raise NotImplementedError
|
||||
|
||||
def apply_translated_message(self, original_message, translated_message):
|
||||
# type: (str, str) -> None
|
||||
def apply_translated_message(self, original_message: str, translated_message: str) -> None:
|
||||
"""Apply translated message."""
|
||||
raise NotImplementedError
|
||||
|
||||
def extract_original_messages(self):
|
||||
# type: () -> Sequence[str]
|
||||
def extract_original_messages(self) -> Sequence[str]:
|
||||
"""Extract translation messages.
|
||||
|
||||
:returns: list of extracted messages or messages generator
|
||||
@ -61,22 +59,37 @@ class not_smartquotable:
|
||||
class toctree(nodes.General, nodes.Element, translatable):
|
||||
"""Node for inserting a "TOC tree"."""
|
||||
|
||||
def preserve_original_messages(self):
|
||||
# type: () -> None
|
||||
def preserve_original_messages(self) -> None:
|
||||
# toctree entries
|
||||
rawentries = self.setdefault('rawentries', [])
|
||||
for title, docname in self['entries']:
|
||||
if title:
|
||||
rawentries.append(title)
|
||||
|
||||
# :caption: option
|
||||
if self.get('caption'):
|
||||
self['rawcaption'] = self['caption']
|
||||
|
||||
def apply_translated_message(self, original_message, translated_message):
|
||||
# type: (str, str) -> None
|
||||
def apply_translated_message(self, original_message: str, translated_message: str) -> None:
|
||||
# toctree entries
|
||||
for i, (title, docname) in enumerate(self['entries']):
|
||||
if title == original_message:
|
||||
self['entries'][i] = (translated_message, docname)
|
||||
|
||||
# :caption: option
|
||||
if self.get('rawcaption') == original_message:
|
||||
self['caption'] = translated_message
|
||||
|
||||
def extract_original_messages(self):
|
||||
# type: () -> List[str]
|
||||
def extract_original_messages(self) -> List[str]:
|
||||
messages = [] # type: List[str]
|
||||
|
||||
# toctree entries
|
||||
messages.extend(self.get('rawentries', []))
|
||||
|
||||
# :caption: option
|
||||
if 'rawcaption' in self:
|
||||
return [self['rawcaption']]
|
||||
else:
|
||||
return []
|
||||
messages.append(self['rawcaption'])
|
||||
return messages
|
||||
|
||||
|
||||
# domain-specific object descriptions (class, function etc.)
|
||||
@ -125,8 +138,7 @@ class desc_type(nodes.Part, nodes.Inline, nodes.FixedTextElement):
|
||||
|
||||
class desc_returns(desc_type):
|
||||
"""Node for a "returns" annotation (a la -> in Python)."""
|
||||
def astext(self):
|
||||
# type: () -> str
|
||||
def astext(self) -> str:
|
||||
return ' -> ' + super().astext()
|
||||
|
||||
|
||||
@ -147,8 +159,7 @@ class desc_optional(nodes.Part, nodes.Inline, nodes.FixedTextElement):
|
||||
"""Node for marking optional parts of the parameter list."""
|
||||
child_text_separator = ', '
|
||||
|
||||
def astext(self):
|
||||
# type: () -> str
|
||||
def astext(self) -> str:
|
||||
return '[' + super().astext() + ']'
|
||||
|
||||
|
||||
@ -188,59 +199,6 @@ class production(nodes.Part, nodes.Inline, nodes.FixedTextElement):
|
||||
"""Node for a single grammar production rule."""
|
||||
|
||||
|
||||
# math nodes
|
||||
|
||||
|
||||
class math(nodes.math):
|
||||
"""Node for inline equations.
|
||||
|
||||
.. warning:: This node is provided to keep compatibility only.
|
||||
It will be removed in nearly future. Don't use this from your extension.
|
||||
|
||||
.. deprecated:: 1.8
|
||||
Use ``docutils.nodes.math`` instead.
|
||||
"""
|
||||
|
||||
def __getitem__(self, key):
|
||||
"""Special accessor for supporting ``node['latex']``."""
|
||||
if key == 'latex' and 'latex' not in self.attributes:
|
||||
warnings.warn("math node for Sphinx was replaced by docutils'. "
|
||||
"Therefore please use ``node.astext()`` to get an equation instead.",
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
return self.astext()
|
||||
else:
|
||||
return super().__getitem__(key)
|
||||
|
||||
|
||||
class math_block(nodes.math_block):
|
||||
"""Node for block level equations.
|
||||
|
||||
.. warning:: This node is provided to keep compatibility only.
|
||||
It will be removed in nearly future. Don't use this from your extension.
|
||||
|
||||
.. deprecated:: 1.8
|
||||
"""
|
||||
|
||||
def __getitem__(self, key):
|
||||
if key == 'latex' and 'latex' not in self.attributes:
|
||||
warnings.warn("displaymath node for Sphinx was replaced by docutils'. "
|
||||
"Therefore please use ``node.astext()`` to get an equation instead.",
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
return self.astext()
|
||||
else:
|
||||
return super().__getitem__(key)
|
||||
|
||||
|
||||
class displaymath(math_block):
|
||||
"""Node for block level equations.
|
||||
|
||||
.. warning:: This node is provided to keep compatibility only.
|
||||
It will be removed in nearly future. Don't use this from your extension.
|
||||
|
||||
.. deprecated:: 1.8
|
||||
"""
|
||||
|
||||
|
||||
# other directive-level nodes
|
||||
|
||||
class index(nodes.Invisible, nodes.Inline, nodes.TextElement):
|
||||
@ -348,8 +306,8 @@ class abbreviation(nodes.abbreviation):
|
||||
.. deprecated:: 2.0
|
||||
"""
|
||||
|
||||
def __init__(self, rawsource='', text='', *children, **attributes):
|
||||
# type: (str, str, *nodes.Node, **Any) -> None
|
||||
def __init__(self, rawsource: str = '', text: str = '',
|
||||
*children: Node, **attributes: Any) -> None:
|
||||
warnings.warn("abbrevition node for Sphinx was replaced by docutils'.",
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
|
||||
@ -360,8 +318,7 @@ class manpage(nodes.Inline, nodes.FixedTextElement):
|
||||
"""Node for references to manpages."""
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: "Sphinx") -> Dict[str, Any]:
|
||||
app.add_node(toctree)
|
||||
app.add_node(desc)
|
||||
app.add_node(desc_signature)
|
||||
@ -379,7 +336,6 @@ def setup(app):
|
||||
app.add_node(seealso)
|
||||
app.add_node(productionlist)
|
||||
app.add_node(production)
|
||||
app.add_node(displaymath)
|
||||
app.add_node(index)
|
||||
app.add_node(centered)
|
||||
app.add_node(acks)
|
||||
|
@ -6,58 +6,59 @@
|
||||
|
||||
Gracefully adapted from the TextPress system by Armin.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pickle
|
||||
import platform
|
||||
import sys
|
||||
import warnings
|
||||
from collections import deque
|
||||
from inspect import isclass
|
||||
from io import StringIO
|
||||
from os import path
|
||||
from typing import Any, Callable, Dict, IO, List, Tuple, Union
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.nodes import Element, TextElement
|
||||
from docutils.parsers.rst import Directive, roles
|
||||
from docutils.transforms import Transform
|
||||
from pygments.lexer import Lexer
|
||||
|
||||
import sphinx
|
||||
from sphinx import package_dir, locale
|
||||
from sphinx.config import Config
|
||||
from sphinx.config import CONFIG_FILENAME # NOQA # for compatibility (RemovedInSphinx30)
|
||||
from sphinx.deprecation import (
|
||||
RemovedInSphinx30Warning, RemovedInSphinx40Warning
|
||||
)
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning
|
||||
from sphinx.domains import Domain, Index
|
||||
from sphinx.environment import BuildEnvironment
|
||||
from sphinx.environment.collectors import EnvironmentCollector
|
||||
from sphinx.errors import ApplicationError, ConfigError, VersionRequirementError
|
||||
from sphinx.events import EventManager
|
||||
from sphinx.extension import Extension
|
||||
from sphinx.highlighting import lexer_classes, lexers
|
||||
from sphinx.locale import __
|
||||
from sphinx.project import Project
|
||||
from sphinx.registry import SphinxComponentRegistry
|
||||
from sphinx.roles import XRefRole
|
||||
from sphinx.theming import Theme
|
||||
from sphinx.util import docutils
|
||||
from sphinx.util import import_object, progress_message
|
||||
from sphinx.util import logging
|
||||
from sphinx.util import progress_message
|
||||
from sphinx.util.build_phase import BuildPhase
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.docutils import directive_helper
|
||||
from sphinx.util.i18n import CatalogRepository
|
||||
from sphinx.util.logging import prefixed_warnings
|
||||
from sphinx.util.osutil import abspath, ensuredir, relpath
|
||||
from sphinx.util.tags import Tags
|
||||
from sphinx.util.typing import RoleFunction, TitleGetter
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Callable, Dict, IO, Iterable, Iterator, List, Tuple, Type, Union # NOQA
|
||||
from docutils import nodes # NOQA
|
||||
from docutils.parsers import Parser # NOQA
|
||||
from docutils.transforms import Transform # NOQA
|
||||
from sphinx.builders import Builder # NOQA
|
||||
from sphinx.domains import Domain, Index # NOQA
|
||||
from sphinx.environment.collectors import EnvironmentCollector # NOQA
|
||||
from sphinx.extension import Extension # NOQA
|
||||
from sphinx.roles import XRefRole # NOQA
|
||||
from sphinx.theming import Theme # NOQA
|
||||
from sphinx.util.typing import RoleFunction, TitleGetter # NOQA
|
||||
from docutils.nodes import Node # NOQA
|
||||
from typing import Type # for python3.5.1
|
||||
from sphinx.builders import Builder
|
||||
|
||||
|
||||
builtin_extensions = (
|
||||
'sphinx.addnodes',
|
||||
@ -77,7 +78,9 @@ builtin_extensions = (
|
||||
'sphinx.config',
|
||||
'sphinx.domains.c',
|
||||
'sphinx.domains.changeset',
|
||||
'sphinx.domains.citation',
|
||||
'sphinx.domains.cpp',
|
||||
'sphinx.domains.index',
|
||||
'sphinx.domains.javascript',
|
||||
'sphinx.domains.math',
|
||||
'sphinx.domains.python',
|
||||
@ -91,18 +94,21 @@ builtin_extensions = (
|
||||
'sphinx.parsers',
|
||||
'sphinx.registry',
|
||||
'sphinx.roles',
|
||||
'sphinx.transforms',
|
||||
'sphinx.transforms.compact_bullet_list',
|
||||
'sphinx.transforms.i18n',
|
||||
'sphinx.transforms.references',
|
||||
'sphinx.transforms.post_transforms',
|
||||
'sphinx.transforms.post_transforms.code',
|
||||
'sphinx.transforms.post_transforms.images',
|
||||
'sphinx.transforms.post_transforms.compat',
|
||||
'sphinx.util.compat',
|
||||
'sphinx.versioning',
|
||||
# collectors should be loaded by specific order
|
||||
'sphinx.environment.collectors.dependencies',
|
||||
'sphinx.environment.collectors.asset',
|
||||
'sphinx.environment.collectors.metadata',
|
||||
'sphinx.environment.collectors.title',
|
||||
'sphinx.environment.collectors.toctree',
|
||||
'sphinx.environment.collectors.indexentries',
|
||||
# 1st party extensions
|
||||
'sphinxcontrib.applehelp',
|
||||
'sphinxcontrib.devhelp',
|
||||
@ -128,11 +134,11 @@ class Sphinx:
|
||||
:ivar outdir: Directory for storing build documents.
|
||||
"""
|
||||
|
||||
def __init__(self, srcdir, confdir, outdir, doctreedir, buildername,
|
||||
confoverrides=None, status=sys.stdout, warning=sys.stderr,
|
||||
freshenv=False, warningiserror=False, tags=None, verbosity=0,
|
||||
parallel=0, keep_going=False):
|
||||
# type: (str, str, str, str, str, Dict, IO, IO, bool, bool, List[str], int, int, bool) -> None # NOQA
|
||||
def __init__(self, srcdir: str, confdir: str, outdir: str, doctreedir: str,
|
||||
buildername: str, confoverrides: Dict = None,
|
||||
status: IO = sys.stdout, warning: IO = sys.stderr,
|
||||
freshenv: bool = False, warningiserror: bool = False, tags: List[str] = None,
|
||||
verbosity: int = 0, parallel: int = 0, keep_going: bool = False) -> None:
|
||||
self.phase = BuildPhase.INITIALIZATION
|
||||
self.verbosity = verbosity
|
||||
self.extensions = {} # type: Dict[str, Extension]
|
||||
@ -182,7 +188,7 @@ class Sphinx:
|
||||
self.warningiserror = warningiserror
|
||||
logging.setup(self, self._status, self._warning)
|
||||
|
||||
self.events = EventManager()
|
||||
self.events = EventManager(self)
|
||||
|
||||
# keep last few messages for traceback
|
||||
# This will be filled by sphinx.util.logging.LastMessagesWriter
|
||||
@ -191,6 +197,12 @@ class Sphinx:
|
||||
# say hello to the world
|
||||
logger.info(bold(__('Running Sphinx v%s') % sphinx.__display_version__))
|
||||
|
||||
# notice for parallel build on macOS and py38+
|
||||
if sys.version_info > (3, 8) and platform.system() == 'Darwin' and parallel > 1:
|
||||
logger.info(bold(__("For security reason, parallel mode is disabled on macOS and "
|
||||
"python3.8 and above. For more details, please read "
|
||||
"https://github.com/sphinx-doc/sphinx/issues/6803")))
|
||||
|
||||
# status code for command-line application
|
||||
self.statuscode = 0
|
||||
|
||||
@ -249,7 +261,7 @@ class Sphinx:
|
||||
|
||||
# now that we know all config values, collect them from conf.py
|
||||
self.config.init_values()
|
||||
self.emit('config-inited', self.config)
|
||||
self.events.emit('config-inited', self.config)
|
||||
|
||||
# create the project
|
||||
self.project = Project(self.srcdir, self.config.source_suffix)
|
||||
@ -260,8 +272,7 @@ class Sphinx:
|
||||
# set up the builder
|
||||
self._init_builder()
|
||||
|
||||
def _init_i18n(self):
|
||||
# type: () -> None
|
||||
def _init_i18n(self) -> None:
|
||||
"""Load translated strings from the configured localedirs if enabled in
|
||||
the configuration.
|
||||
"""
|
||||
@ -286,8 +297,7 @@ class Sphinx:
|
||||
else:
|
||||
logger.info(__('not available for built-in messages'))
|
||||
|
||||
def _init_env(self, freshenv):
|
||||
# type: (bool) -> None
|
||||
def _init_env(self, freshenv: bool) -> None:
|
||||
filename = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
|
||||
if freshenv or not os.path.exists(filename):
|
||||
self.env = BuildEnvironment()
|
||||
@ -303,28 +313,24 @@ class Sphinx:
|
||||
logger.info(__('failed: %s'), err)
|
||||
self._init_env(freshenv=True)
|
||||
|
||||
def preload_builder(self, name):
|
||||
# type: (str) -> None
|
||||
def preload_builder(self, name: str) -> None:
|
||||
self.registry.preload_builder(self, name)
|
||||
|
||||
def create_builder(self, name):
|
||||
# type: (str) -> Builder
|
||||
def create_builder(self, name: str) -> "Builder":
|
||||
if name is None:
|
||||
logger.info(__('No builder selected, using default: html'))
|
||||
name = 'html'
|
||||
|
||||
return self.registry.create_builder(self, name)
|
||||
|
||||
def _init_builder(self):
|
||||
# type: () -> None
|
||||
def _init_builder(self) -> None:
|
||||
self.builder.set_environment(self.env)
|
||||
self.builder.init()
|
||||
self.emit('builder-inited')
|
||||
self.events.emit('builder-inited')
|
||||
|
||||
# ---- main "build" method -------------------------------------------------
|
||||
|
||||
def build(self, force_all=False, filenames=None):
|
||||
# type: (bool, List[str]) -> None
|
||||
def build(self, force_all: bool = False, filenames: List[str] = None) -> None:
|
||||
self.phase = BuildPhase.READING
|
||||
try:
|
||||
if force_all:
|
||||
@ -340,12 +346,19 @@ class Sphinx:
|
||||
if self._warncount and self.keep_going:
|
||||
self.statuscode = 1
|
||||
|
||||
status = (self.statuscode == 0 and
|
||||
__('succeeded') or __('finished with problems'))
|
||||
status = (__('succeeded') if self.statuscode == 0
|
||||
else __('finished with problems'))
|
||||
if self._warncount:
|
||||
logger.info(bold(__('build %s, %s warning.',
|
||||
'build %s, %s warnings.', self._warncount) %
|
||||
(status, self._warncount)))
|
||||
if self.warningiserror:
|
||||
msg = __('build %s, %s warning (with warnings treated as errors).',
|
||||
'build %s, %s warnings (with warnings treated as errors).',
|
||||
self._warncount)
|
||||
else:
|
||||
msg = __('build %s, %s warning.',
|
||||
'build %s, %s warnings.',
|
||||
self._warncount)
|
||||
|
||||
logger.info(bold(msg % (status, self._warncount)))
|
||||
else:
|
||||
logger.info(bold(__('build %s.') % status))
|
||||
|
||||
@ -360,16 +373,15 @@ class Sphinx:
|
||||
envfile = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
|
||||
if path.isfile(envfile):
|
||||
os.unlink(envfile)
|
||||
self.emit('build-finished', err)
|
||||
self.events.emit('build-finished', err)
|
||||
raise
|
||||
else:
|
||||
self.emit('build-finished', None)
|
||||
self.events.emit('build-finished', None)
|
||||
self.builder.cleanup()
|
||||
|
||||
# ---- general extensibility interface -------------------------------------
|
||||
|
||||
def setup_extension(self, extname):
|
||||
# type: (str) -> None
|
||||
def setup_extension(self, extname: str) -> None:
|
||||
"""Import and setup a Sphinx extension module.
|
||||
|
||||
Load the extension given by the module *name*. Use this if your
|
||||
@ -379,8 +391,7 @@ class Sphinx:
|
||||
logger.debug('[app] setting up extension: %r', extname)
|
||||
self.registry.load_extension(self, extname)
|
||||
|
||||
def require_sphinx(self, version):
|
||||
# type: (str) -> None
|
||||
def require_sphinx(self, version: str) -> None:
|
||||
"""Check the Sphinx version if requested.
|
||||
|
||||
Compare *version* (which must be a ``major.minor`` version string, e.g.
|
||||
@ -392,68 +403,53 @@ class Sphinx:
|
||||
if version > sphinx.__display_version__[:3]:
|
||||
raise VersionRequirementError(version)
|
||||
|
||||
def import_object(self, objname, source=None):
|
||||
# type: (str, str) -> Any
|
||||
"""Import an object from a ``module.name`` string.
|
||||
|
||||
.. deprecated:: 1.8
|
||||
Use ``sphinx.util.import_object()`` instead.
|
||||
"""
|
||||
warnings.warn('app.import_object() is deprecated. '
|
||||
'Use sphinx.util.add_object_type() instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
return import_object(objname, source=None)
|
||||
|
||||
# event interface
|
||||
def connect(self, event, callback):
|
||||
# type: (str, Callable) -> int
|
||||
def connect(self, event: str, callback: Callable, priority: int = 500) -> int:
|
||||
"""Register *callback* to be called when *event* is emitted.
|
||||
|
||||
For details on available core events and the arguments of callback
|
||||
functions, please see :ref:`events`.
|
||||
|
||||
Registered callbacks will be invoked on event in the order of *priority* and
|
||||
registration. The priority is ascending order.
|
||||
|
||||
The method returns a "listener ID" that can be used as an argument to
|
||||
:meth:`disconnect`.
|
||||
|
||||
.. versionchanged:: 3.0
|
||||
|
||||
Support *priority*
|
||||
"""
|
||||
listener_id = self.events.connect(event, callback)
|
||||
logger.debug('[app] connecting event %r: %r [id=%s]', event, callback, listener_id)
|
||||
listener_id = self.events.connect(event, callback, priority)
|
||||
logger.debug('[app] connecting event %r (%d): %r [id=%s]',
|
||||
event, priority, callback, listener_id)
|
||||
return listener_id
|
||||
|
||||
def disconnect(self, listener_id):
|
||||
# type: (int) -> None
|
||||
def disconnect(self, listener_id: int) -> None:
|
||||
"""Unregister callback by *listener_id*."""
|
||||
logger.debug('[app] disconnecting event: [id=%s]', listener_id)
|
||||
self.events.disconnect(listener_id)
|
||||
|
||||
def emit(self, event, *args):
|
||||
# type: (str, Any) -> List
|
||||
def emit(self, event: str, *args: Any) -> List:
|
||||
"""Emit *event* and pass *arguments* to the callback functions.
|
||||
|
||||
Return the return values of all callbacks as a list. Do not emit core
|
||||
Sphinx events in extensions!
|
||||
"""
|
||||
try:
|
||||
logger.debug('[app] emitting event: %r%s', event, repr(args)[:100])
|
||||
except Exception:
|
||||
# not every object likes to be repr()'d (think
|
||||
# random stuff coming via autodoc)
|
||||
pass
|
||||
return self.events.emit(event, self, *args)
|
||||
return self.events.emit(event, *args)
|
||||
|
||||
def emit_firstresult(self, event, *args):
|
||||
# type: (str, Any) -> Any
|
||||
def emit_firstresult(self, event: str, *args: Any) -> Any:
|
||||
"""Emit *event* and pass *arguments* to the callback functions.
|
||||
|
||||
Return the result of the first callback that doesn't return ``None``.
|
||||
|
||||
.. versionadded:: 0.5
|
||||
"""
|
||||
return self.events.emit_firstresult(event, self, *args)
|
||||
return self.events.emit_firstresult(event, *args)
|
||||
|
||||
# registering addon parts
|
||||
|
||||
def add_builder(self, builder, override=False):
|
||||
# type: (Type[Builder], bool) -> None
|
||||
def add_builder(self, builder: "Type[Builder]", override: bool = False) -> None:
|
||||
"""Register a new builder.
|
||||
|
||||
*builder* must be a class that inherits from
|
||||
@ -465,8 +461,8 @@ class Sphinx:
|
||||
self.registry.add_builder(builder, override=override)
|
||||
|
||||
# TODO(stephenfin): Describe 'types' parameter
|
||||
def add_config_value(self, name, default, rebuild, types=()):
|
||||
# type: (str, Any, Union[bool, str], Any) -> None
|
||||
def add_config_value(self, name: str, default: Any, rebuild: Union[bool, str],
|
||||
types: Any = ()) -> None:
|
||||
"""Register a configuration value.
|
||||
|
||||
This is necessary for Sphinx to recognize new values and set default
|
||||
@ -495,11 +491,10 @@ class Sphinx:
|
||||
logger.debug('[app] adding config value: %r',
|
||||
(name, default, rebuild) + ((types,) if types else ())) # type: ignore
|
||||
if rebuild in (False, True):
|
||||
rebuild = rebuild and 'env' or ''
|
||||
rebuild = 'env' if rebuild else ''
|
||||
self.config.add(name, default, rebuild, types)
|
||||
|
||||
def add_event(self, name):
|
||||
# type: (str) -> None
|
||||
def add_event(self, name: str) -> None:
|
||||
"""Register an event called *name*.
|
||||
|
||||
This is needed to be able to emit it.
|
||||
@ -507,8 +502,8 @@ class Sphinx:
|
||||
logger.debug('[app] adding event: %r', name)
|
||||
self.events.add(name)
|
||||
|
||||
def set_translator(self, name, translator_class, override=False):
|
||||
# type: (str, Type[nodes.NodeVisitor], bool) -> None
|
||||
def set_translator(self, name: str, translator_class: "Type[nodes.NodeVisitor]",
|
||||
override: bool = False) -> None:
|
||||
"""Register or override a Docutils translator class.
|
||||
|
||||
This is used to register a custom output translator or to replace a
|
||||
@ -521,8 +516,8 @@ class Sphinx:
|
||||
"""
|
||||
self.registry.add_translator(name, translator_class, override=override)
|
||||
|
||||
def add_node(self, node, override=False, **kwds):
|
||||
# type: (Type[nodes.Element], bool, Any) -> None
|
||||
def add_node(self, node: "Type[Element]", override: bool = False,
|
||||
**kwargs: Tuple[Callable, Callable]) -> None:
|
||||
"""Register a Docutils node class.
|
||||
|
||||
This is necessary for Docutils internals. It may also be used in the
|
||||
@ -552,16 +547,17 @@ class Sphinx:
|
||||
.. versionchanged:: 0.5
|
||||
Added the support for keyword arguments giving visit functions.
|
||||
"""
|
||||
logger.debug('[app] adding node: %r', (node, kwds))
|
||||
logger.debug('[app] adding node: %r', (node, kwargs))
|
||||
if not override and docutils.is_node_registered(node):
|
||||
logger.warning(__('node class %r is already registered, '
|
||||
'its visitors will be overridden'),
|
||||
node.__name__, type='app', subtype='add_node')
|
||||
docutils.register_node(node)
|
||||
self.registry.add_translation_handlers(node, **kwds)
|
||||
self.registry.add_translation_handlers(node, **kwargs)
|
||||
|
||||
def add_enumerable_node(self, node, figtype, title_getter=None, override=False, **kwds):
|
||||
# type: (Type[nodes.Element], str, TitleGetter, bool, Any) -> None
|
||||
def add_enumerable_node(self, node: "Type[Element]", figtype: str,
|
||||
title_getter: TitleGetter = None, override: bool = False,
|
||||
**kwargs: Tuple[Callable, Callable]) -> None:
|
||||
"""Register a Docutils node class as a numfig target.
|
||||
|
||||
Sphinx numbers the node automatically. And then the users can refer it
|
||||
@ -586,38 +582,15 @@ class Sphinx:
|
||||
.. versionadded:: 1.4
|
||||
"""
|
||||
self.registry.add_enumerable_node(node, figtype, title_getter, override=override)
|
||||
self.add_node(node, override=override, **kwds)
|
||||
self.add_node(node, override=override, **kwargs)
|
||||
|
||||
@property
|
||||
def enumerable_nodes(self):
|
||||
# type: () -> Dict[Type[nodes.Node], Tuple[str, TitleGetter]]
|
||||
warnings.warn('app.enumerable_nodes() is deprecated. '
|
||||
'Use app.get_domain("std").enumerable_nodes instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
return self.registry.enumerable_nodes
|
||||
|
||||
def add_directive(self, name, obj, content=None, arguments=None, override=False, **options): # NOQA
|
||||
# type: (str, Any, bool, Tuple[int, int, bool], bool, Any) -> None
|
||||
def add_directive(self, name: str, cls: "Type[Directive]", override: bool = False) -> None:
|
||||
"""Register a Docutils directive.
|
||||
|
||||
*name* must be the prospective directive name. There are two possible
|
||||
ways to write a directive:
|
||||
|
||||
- In the docutils 0.4 style, *obj* is the directive function.
|
||||
*content*, *arguments* and *options* are set as attributes on the
|
||||
function and determine whether the directive has content, arguments
|
||||
and options, respectively. **This style is deprecated.**
|
||||
|
||||
- In the docutils 0.5 style, *obj* is the directive class.
|
||||
It must already have attributes named *has_content*,
|
||||
*required_arguments*, *optional_arguments*,
|
||||
*final_argument_whitespace* and *option_spec* that correspond to the
|
||||
options for the function way. See `the Docutils docs
|
||||
<http://docutils.sourceforge.net/docs/howto/rst-directives.html>`_
|
||||
for details.
|
||||
|
||||
The directive class must inherit from the class
|
||||
``docutils.parsers.rst.Directive``.
|
||||
*name* must be the prospective directive name. *cls* is a directive
|
||||
class which inherits ``docutils.parsers.rst.Directive``. For more
|
||||
details, see `the Docutils docs
|
||||
<http://docutils.sourceforge.net/docs/howto/rst-directives.html>`_ .
|
||||
|
||||
For example, the (already existing) :rst:dir:`literalinclude` directive
|
||||
would be added like this:
|
||||
@ -648,20 +621,14 @@ class Sphinx:
|
||||
.. versionchanged:: 1.8
|
||||
Add *override* keyword.
|
||||
"""
|
||||
logger.debug('[app] adding directive: %r',
|
||||
(name, obj, content, arguments, options))
|
||||
logger.debug('[app] adding directive: %r', (name, cls))
|
||||
if not override and docutils.is_directive_registered(name):
|
||||
logger.warning(__('directive %r is already registered, it will be overridden'),
|
||||
name, type='app', subtype='add_directive')
|
||||
|
||||
if not isclass(obj) or not issubclass(obj, Directive):
|
||||
directive = directive_helper(obj, content, arguments, **options)
|
||||
docutils.register_directive(name, directive)
|
||||
else:
|
||||
docutils.register_directive(name, obj)
|
||||
docutils.register_directive(name, cls)
|
||||
|
||||
def add_role(self, name, role, override=False):
|
||||
# type: (str, Any, bool) -> None
|
||||
def add_role(self, name: str, role: Any, override: bool = False) -> None:
|
||||
"""Register a Docutils role.
|
||||
|
||||
*name* must be the role name that occurs in the source, *role* the role
|
||||
@ -678,8 +645,7 @@ class Sphinx:
|
||||
name, type='app', subtype='add_role')
|
||||
docutils.register_role(name, role)
|
||||
|
||||
def add_generic_role(self, name, nodeclass, override=False):
|
||||
# type: (str, Any, bool) -> None
|
||||
def add_generic_role(self, name: str, nodeclass: Any, override: bool = False) -> None:
|
||||
"""Register a generic Docutils role.
|
||||
|
||||
Register a Docutils role that does nothing but wrap its contents in the
|
||||
@ -698,8 +664,7 @@ class Sphinx:
|
||||
role = roles.GenericRole(name, nodeclass)
|
||||
docutils.register_role(name, role)
|
||||
|
||||
def add_domain(self, domain, override=False):
|
||||
# type: (Type[Domain], bool) -> None
|
||||
def add_domain(self, domain: "Type[Domain]", override: bool = False) -> None:
|
||||
"""Register a domain.
|
||||
|
||||
Make the given *domain* (which must be a class; more precisely, a
|
||||
@ -711,26 +676,8 @@ class Sphinx:
|
||||
"""
|
||||
self.registry.add_domain(domain, override=override)
|
||||
|
||||
def override_domain(self, domain):
|
||||
# type: (Type[Domain]) -> None
|
||||
"""Override a registered domain.
|
||||
|
||||
Make the given *domain* class known to Sphinx, assuming that there is
|
||||
already a domain with its ``.name``. The new domain must be a subclass
|
||||
of the existing one.
|
||||
|
||||
.. versionadded:: 1.0
|
||||
.. deprecated:: 1.8
|
||||
Integrated to :meth:`add_domain`.
|
||||
"""
|
||||
warnings.warn('app.override_domain() is deprecated. '
|
||||
'Use app.add_domain() with override option instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
self.registry.add_domain(domain, override=True)
|
||||
|
||||
def add_directive_to_domain(self, domain, name, obj, has_content=None, argument_spec=None,
|
||||
override=False, **option_spec):
|
||||
# type: (str, str, Any, bool, Any, bool, Any) -> None
|
||||
def add_directive_to_domain(self, domain: str, name: str,
|
||||
cls: "Type[Directive]", override: bool = False) -> None:
|
||||
"""Register a Docutils directive in a domain.
|
||||
|
||||
Like :meth:`add_directive`, but the directive is added to the domain
|
||||
@ -740,12 +687,10 @@ class Sphinx:
|
||||
.. versionchanged:: 1.8
|
||||
Add *override* keyword.
|
||||
"""
|
||||
self.registry.add_directive_to_domain(domain, name, obj,
|
||||
has_content, argument_spec, override=override,
|
||||
**option_spec)
|
||||
self.registry.add_directive_to_domain(domain, name, cls, override=override)
|
||||
|
||||
def add_role_to_domain(self, domain, name, role, override=False):
|
||||
# type: (str, str, Union[RoleFunction, XRefRole], bool) -> None
|
||||
def add_role_to_domain(self, domain: str, name: str, role: Union[RoleFunction, XRefRole],
|
||||
override: bool = False) -> None:
|
||||
"""Register a Docutils role in a domain.
|
||||
|
||||
Like :meth:`add_role`, but the role is added to the domain named
|
||||
@ -757,8 +702,8 @@ class Sphinx:
|
||||
"""
|
||||
self.registry.add_role_to_domain(domain, name, role, override=override)
|
||||
|
||||
def add_index_to_domain(self, domain, index, override=False):
|
||||
# type: (str, Type[Index], bool) -> None
|
||||
def add_index_to_domain(self, domain: str, index: "Type[Index]", override: bool = False
|
||||
) -> None:
|
||||
"""Register a custom index for a domain.
|
||||
|
||||
Add a custom *index* class to the domain named *domain*. *index* must
|
||||
@ -770,10 +715,10 @@ class Sphinx:
|
||||
"""
|
||||
self.registry.add_index_to_domain(domain, index)
|
||||
|
||||
def add_object_type(self, directivename, rolename, indextemplate='',
|
||||
parse_node=None, ref_nodeclass=None, objname='',
|
||||
doc_field_types=[], override=False):
|
||||
# type: (str, str, str, Callable, Type[nodes.TextElement], str, List, bool) -> None
|
||||
def add_object_type(self, directivename: str, rolename: str, indextemplate: str = '',
|
||||
parse_node: Callable = None, ref_nodeclass: "Type[TextElement]" = None,
|
||||
objname: str = '', doc_field_types: List = [], override: bool = False
|
||||
) -> None:
|
||||
"""Register a new object type.
|
||||
|
||||
This method is a very convenient way to add a new :term:`object` type
|
||||
@ -827,9 +772,6 @@ class Sphinx:
|
||||
For the role content, you have the same syntactical possibilities as
|
||||
for standard Sphinx roles (see :ref:`xref-syntax`).
|
||||
|
||||
This method is also available under the deprecated alias
|
||||
:meth:`add_description_unit`.
|
||||
|
||||
.. versionchanged:: 1.8
|
||||
Add *override* keyword.
|
||||
"""
|
||||
@ -837,9 +779,9 @@ class Sphinx:
|
||||
ref_nodeclass, objname, doc_field_types,
|
||||
override=override)
|
||||
|
||||
def add_crossref_type(self, directivename, rolename, indextemplate='',
|
||||
ref_nodeclass=None, objname='', override=False):
|
||||
# type: (str, str, str, Type[nodes.TextElement], str, bool) -> None
|
||||
def add_crossref_type(self, directivename: str, rolename: str, indextemplate: str = '',
|
||||
ref_nodeclass: "Type[TextElement]" = None, objname: str = '',
|
||||
override: bool = False) -> None:
|
||||
"""Register a new crossref object type.
|
||||
|
||||
This method is very similar to :meth:`add_object_type` except that the
|
||||
@ -873,8 +815,7 @@ class Sphinx:
|
||||
indextemplate, ref_nodeclass, objname,
|
||||
override=override)
|
||||
|
||||
def add_transform(self, transform):
|
||||
# type: (Type[Transform]) -> None
|
||||
def add_transform(self, transform: "Type[Transform]") -> None:
|
||||
"""Register a Docutils transform to be applied after parsing.
|
||||
|
||||
Add the standard docutils :class:`Transform` subclass *transform* to
|
||||
@ -907,8 +848,7 @@ class Sphinx:
|
||||
""" # NOQA
|
||||
self.registry.add_transform(transform)
|
||||
|
||||
def add_post_transform(self, transform):
|
||||
# type: (Type[Transform]) -> None
|
||||
def add_post_transform(self, transform: "Type[Transform]") -> None:
|
||||
"""Register a Docutils transform to be applied before writing.
|
||||
|
||||
Add the standard docutils :class:`Transform` subclass *transform* to
|
||||
@ -917,22 +857,22 @@ class Sphinx:
|
||||
"""
|
||||
self.registry.add_post_transform(transform)
|
||||
|
||||
def add_javascript(self, filename, **kwargs):
|
||||
# type: (str, **str) -> None
|
||||
def add_javascript(self, filename: str, **kwargs: str) -> None:
|
||||
"""An alias of :meth:`add_js_file`."""
|
||||
warnings.warn('The app.add_javascript() is deprecated. '
|
||||
'Please use app.add_js_file() instead.',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
self.add_js_file(filename, **kwargs)
|
||||
|
||||
def add_js_file(self, filename, **kwargs):
|
||||
# type: (str, **str) -> None
|
||||
def add_js_file(self, filename: str, **kwargs: str) -> None:
|
||||
"""Register a JavaScript file to include in the HTML output.
|
||||
|
||||
Add *filename* to the list of JavaScript files that the default HTML
|
||||
template will include. The filename must be relative to the HTML
|
||||
static path , or a full URI with scheme. The keyword arguments are
|
||||
also accepted for attributes of ``<script>`` tag.
|
||||
static path , or a full URI with scheme. If the keyword argument
|
||||
``body`` is given, its value will be added between the
|
||||
``<script>`` tags. Extra keyword arguments are included as
|
||||
attributes of the ``<script>`` tag.
|
||||
|
||||
Example::
|
||||
|
||||
@ -942,6 +882,9 @@ class Sphinx:
|
||||
app.add_js_file('example.js', async="async")
|
||||
# => <script src="_static/example.js" async="async"></script>
|
||||
|
||||
app.add_js_file(None, body="var myVariable = 'foo';")
|
||||
# => <script>var myVariable = 'foo';</script>
|
||||
|
||||
.. versionadded:: 0.5
|
||||
|
||||
.. versionchanged:: 1.8
|
||||
@ -952,8 +895,7 @@ class Sphinx:
|
||||
if hasattr(self.builder, 'add_js_file'):
|
||||
self.builder.add_js_file(filename, **kwargs) # type: ignore
|
||||
|
||||
def add_css_file(self, filename, **kwargs):
|
||||
# type: (str, **str) -> None
|
||||
def add_css_file(self, filename: str, **kwargs: str) -> None:
|
||||
"""Register a stylesheet to include in the HTML output.
|
||||
|
||||
Add *filename* to the list of CSS files that the default HTML template
|
||||
@ -992,8 +934,8 @@ class Sphinx:
|
||||
if hasattr(self.builder, 'add_css_file'):
|
||||
self.builder.add_css_file(filename, **kwargs) # type: ignore
|
||||
|
||||
def add_stylesheet(self, filename, alternate=False, title=None):
|
||||
# type: (str, bool, str) -> None
|
||||
def add_stylesheet(self, filename: str, alternate: bool = False, title: str = None
|
||||
) -> None:
|
||||
"""An alias of :meth:`add_css_file`."""
|
||||
warnings.warn('The app.add_stylesheet() is deprecated. '
|
||||
'Please use app.add_css_file() instead.',
|
||||
@ -1010,8 +952,7 @@ class Sphinx:
|
||||
|
||||
self.add_css_file(filename, **attributes)
|
||||
|
||||
def add_latex_package(self, packagename, options=None):
|
||||
# type: (str, str) -> None
|
||||
def add_latex_package(self, packagename: str, options: str = None) -> None:
|
||||
r"""Register a package to include in the LaTeX source code.
|
||||
|
||||
Add *packagename* to the list of packages that LaTeX source code will
|
||||
@ -1029,23 +970,26 @@ class Sphinx:
|
||||
"""
|
||||
self.registry.add_latex_package(packagename, options)
|
||||
|
||||
def add_lexer(self, alias, lexer):
|
||||
# type: (str, Any) -> None
|
||||
def add_lexer(self, alias: str, lexer: Union[Lexer, "Type[Lexer]"]) -> None:
|
||||
"""Register a new lexer for source code.
|
||||
|
||||
Use *lexer*, which must be an instance of a Pygments lexer class, to
|
||||
highlight code blocks with the given language *alias*.
|
||||
Use *lexer* to highlight code blocks with the given language *alias*.
|
||||
|
||||
.. versionadded:: 0.6
|
||||
.. versionchanged:: 2.1
|
||||
Take a lexer class as an argument. An instance of lexers are
|
||||
still supported until Sphinx-3.x.
|
||||
"""
|
||||
logger.debug('[app] adding lexer: %r', (alias, lexer))
|
||||
from sphinx.highlighting import lexers
|
||||
if lexers is None:
|
||||
return
|
||||
lexers[alias] = lexer
|
||||
if isinstance(lexer, Lexer):
|
||||
warnings.warn('app.add_lexer() API changed; '
|
||||
'Please give lexer class instead instance',
|
||||
RemovedInSphinx40Warning)
|
||||
lexers[alias] = lexer
|
||||
else:
|
||||
lexer_classes[alias] = lexer
|
||||
|
||||
def add_autodocumenter(self, cls):
|
||||
# type: (Any) -> None
|
||||
def add_autodocumenter(self, cls: Any, override: bool = False) -> None:
|
||||
"""Register a new documenter class for the autodoc extension.
|
||||
|
||||
Add *cls* as a new documenter class for the :mod:`sphinx.ext.autodoc`
|
||||
@ -1057,14 +1001,16 @@ class Sphinx:
|
||||
.. todo:: Add real docs for Documenter and subclassing
|
||||
|
||||
.. versionadded:: 0.6
|
||||
.. versionchanged:: 2.2
|
||||
Add *override* keyword.
|
||||
"""
|
||||
logger.debug('[app] adding autodocumenter: %r', cls)
|
||||
from sphinx.ext.autodoc.directive import AutodocDirective
|
||||
self.registry.add_documenter(cls.objtype, cls)
|
||||
self.add_directive('auto' + cls.objtype, AutodocDirective)
|
||||
self.add_directive('auto' + cls.objtype, AutodocDirective, override=override)
|
||||
|
||||
def add_autodoc_attrgetter(self, typ, getter):
|
||||
# type: (Type, Callable[[Any, str, Any], Any]) -> None
|
||||
def add_autodoc_attrgetter(self, typ: "Type", getter: Callable[[Any, str, Any], Any]
|
||||
) -> None:
|
||||
"""Register a new ``getattr``-like function for the autodoc extension.
|
||||
|
||||
Add *getter*, which must be a function with an interface compatible to
|
||||
@ -1078,8 +1024,7 @@ class Sphinx:
|
||||
logger.debug('[app] adding autodoc attrgetter: %r', (typ, getter))
|
||||
self.registry.add_autodoc_attrgetter(typ, getter)
|
||||
|
||||
def add_search_language(self, cls):
|
||||
# type: (Any) -> None
|
||||
def add_search_language(self, cls: Any) -> None:
|
||||
"""Register a new language for the HTML search index.
|
||||
|
||||
Add *cls*, which must be a subclass of
|
||||
@ -1095,8 +1040,7 @@ class Sphinx:
|
||||
assert issubclass(cls, SearchLanguage)
|
||||
languages[cls.lang] = cls
|
||||
|
||||
def add_source_suffix(self, suffix, filetype, override=False):
|
||||
# type: (str, str, bool) -> None
|
||||
def add_source_suffix(self, suffix: str, filetype: str, override: bool = False) -> None:
|
||||
"""Register a suffix of source files.
|
||||
|
||||
Same as :confval:`source_suffix`. The users can override this
|
||||
@ -1106,8 +1050,7 @@ class Sphinx:
|
||||
"""
|
||||
self.registry.add_source_suffix(suffix, filetype, override=override)
|
||||
|
||||
def add_source_parser(self, *args, **kwargs):
|
||||
# type: (Any, Any) -> None
|
||||
def add_source_parser(self, *args: Any, **kwargs: Any) -> None:
|
||||
"""Register a parser class.
|
||||
|
||||
.. versionadded:: 1.4
|
||||
@ -1119,8 +1062,7 @@ class Sphinx:
|
||||
"""
|
||||
self.registry.add_source_parser(*args, **kwargs)
|
||||
|
||||
def add_env_collector(self, collector):
|
||||
# type: (Type[EnvironmentCollector]) -> None
|
||||
def add_env_collector(self, collector: "Type[EnvironmentCollector]") -> None:
|
||||
"""Register an environment collector class.
|
||||
|
||||
Refer to :ref:`collector-api`.
|
||||
@ -1130,8 +1072,7 @@ class Sphinx:
|
||||
logger.debug('[app] adding environment collector: %r', collector)
|
||||
collector().enable(self)
|
||||
|
||||
def add_html_theme(self, name, theme_path):
|
||||
# type: (str, str) -> None
|
||||
def add_html_theme(self, name: str, theme_path: str) -> None:
|
||||
"""Register a HTML Theme.
|
||||
|
||||
The *name* is a name of theme, and *path* is a full path to the theme
|
||||
@ -1142,8 +1083,9 @@ class Sphinx:
|
||||
logger.debug('[app] adding HTML theme: %r, %r', name, theme_path)
|
||||
self.html_themes[name] = theme_path
|
||||
|
||||
def add_html_math_renderer(self, name, inline_renderers=None, block_renderers=None):
|
||||
# type: (str, Tuple[Callable, Callable], Tuple[Callable, Callable]) -> None
|
||||
def add_html_math_renderer(self, name: str,
|
||||
inline_renderers: Tuple[Callable, Callable] = None,
|
||||
block_renderers: Tuple[Callable, Callable] = None) -> None:
|
||||
"""Register a math renderer for HTML.
|
||||
|
||||
The *name* is a name of math renderer. Both *inline_renderers* and
|
||||
@ -1157,8 +1099,7 @@ class Sphinx:
|
||||
"""
|
||||
self.registry.add_html_math_renderer(name, inline_renderers, block_renderers)
|
||||
|
||||
def add_message_catalog(self, catalog, locale_dir):
|
||||
# type: (str, str) -> None
|
||||
def add_message_catalog(self, catalog: str, locale_dir: str) -> None:
|
||||
"""Register a message catalog.
|
||||
|
||||
The *catalog* is a name of catalog, and *locale_dir* is a base path
|
||||
@ -1171,45 +1112,41 @@ class Sphinx:
|
||||
locale.init_console(locale_dir, catalog)
|
||||
|
||||
# ---- other methods -------------------------------------------------
|
||||
def is_parallel_allowed(self, typ):
|
||||
# type: (str) -> bool
|
||||
def is_parallel_allowed(self, typ: str) -> bool:
|
||||
"""Check parallel processing is allowed or not.
|
||||
|
||||
``typ`` is a type of processing; ``'read'`` or ``'write'``.
|
||||
"""
|
||||
if typ == 'read':
|
||||
attrname = 'parallel_read_safe'
|
||||
message = __("the %s extension does not declare if it is safe "
|
||||
"for parallel reading, assuming it isn't - please "
|
||||
"ask the extension author to check and make it "
|
||||
"explicit")
|
||||
message_not_declared = __("the %s extension does not declare if it "
|
||||
"is safe for parallel reading, assuming "
|
||||
"it isn't - please ask the extension author "
|
||||
"to check and make it explicit")
|
||||
message_not_safe = __("the %s extension is not safe for parallel reading")
|
||||
elif typ == 'write':
|
||||
attrname = 'parallel_write_safe'
|
||||
message = __("the %s extension does not declare if it is safe "
|
||||
"for parallel writing, assuming it isn't - please "
|
||||
"ask the extension author to check and make it "
|
||||
"explicit")
|
||||
message_not_declared = __("the %s extension does not declare if it "
|
||||
"is safe for parallel writing, assuming "
|
||||
"it isn't - please ask the extension author "
|
||||
"to check and make it explicit")
|
||||
message_not_safe = __("the %s extension is not safe for parallel writing")
|
||||
else:
|
||||
raise ValueError('parallel type %s is not supported' % typ)
|
||||
|
||||
for ext in self.extensions.values():
|
||||
allowed = getattr(ext, attrname, None)
|
||||
if allowed is None:
|
||||
logger.warning(message, ext.name)
|
||||
logger.warning(message_not_declared, ext.name)
|
||||
logger.warning(__('doing serial %s'), typ)
|
||||
return False
|
||||
elif not allowed:
|
||||
logger.warning(message_not_safe, ext.name)
|
||||
logger.warning(__('doing serial %s'), typ)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
@property
|
||||
def _setting_up_extension(self):
|
||||
# type: () -> List[str]
|
||||
warnings.warn('app._setting_up_extension is deprecated.',
|
||||
RemovedInSphinx30Warning)
|
||||
return ['?']
|
||||
|
||||
|
||||
class TemplateBridge:
|
||||
"""
|
||||
@ -1217,8 +1154,7 @@ class TemplateBridge:
|
||||
that renders templates given a template name and a context.
|
||||
"""
|
||||
|
||||
def init(self, builder, theme=None, dirs=None):
|
||||
# type: (Builder, Theme, List[str]) -> None
|
||||
def init(self, builder: "Builder", theme: Theme = None, dirs: List[str] = None) -> None:
|
||||
"""Called by the builder to initialize the template system.
|
||||
|
||||
*builder* is the builder object; you'll probably want to look at the
|
||||
@ -1229,23 +1165,20 @@ class TemplateBridge:
|
||||
"""
|
||||
raise NotImplementedError('must be implemented in subclasses')
|
||||
|
||||
def newest_template_mtime(self):
|
||||
# type: () -> float
|
||||
def newest_template_mtime(self) -> float:
|
||||
"""Called by the builder to determine if output files are outdated
|
||||
because of template changes. Return the mtime of the newest template
|
||||
file that was changed. The default implementation returns ``0``.
|
||||
"""
|
||||
return 0
|
||||
|
||||
def render(self, template, context):
|
||||
# type: (str, Dict) -> None
|
||||
def render(self, template: str, context: Dict) -> None:
|
||||
"""Called by the builder to render a template given as a filename with
|
||||
a specified context (a Python dictionary).
|
||||
"""
|
||||
raise NotImplementedError('must be implemented in subclasses')
|
||||
|
||||
def render_string(self, template, context):
|
||||
# type: (str, Dict) -> str
|
||||
def render_string(self, template: str, context: Dict) -> str:
|
||||
"""Called by the builder to render a template given as a string with a
|
||||
specified context (a Python dictionary).
|
||||
"""
|
||||
|
@ -4,29 +4,34 @@
|
||||
|
||||
Builder superclass for all builders.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import pickle
|
||||
import time
|
||||
from os import path
|
||||
from typing import Any, Dict, Iterable, List, Sequence, Set, Tuple, Union
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.nodes import Node
|
||||
|
||||
from sphinx.environment import CONFIG_OK, CONFIG_CHANGED_REASON
|
||||
from sphinx.config import Config
|
||||
from sphinx.environment import BuildEnvironment, CONFIG_OK, CONFIG_CHANGED_REASON
|
||||
from sphinx.environment.adapters.asset import ImageAdapter
|
||||
from sphinx.errors import SphinxError
|
||||
from sphinx.events import EventManager
|
||||
from sphinx.io import read_doc
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import import_object, logging, rst, progress_message, status_iterator
|
||||
from sphinx.util.build_phase import BuildPhase
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.docutils import sphinx_domains
|
||||
from sphinx.util.i18n import CatalogRepository, docname_to_domain
|
||||
from sphinx.util.i18n import CatalogInfo, CatalogRepository, docname_to_domain
|
||||
from sphinx.util.osutil import SEP, ensuredir, relative_uri, relpath
|
||||
from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, \
|
||||
parallel_available
|
||||
from sphinx.util.tags import Tags
|
||||
|
||||
# side effect: registers roles and directives
|
||||
from sphinx import roles # noqa
|
||||
@ -39,12 +44,8 @@ except ImportError:
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Callable, Dict, Iterable, List, Sequence, Set, Tuple, Type, Union # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
from sphinx.util.i18n import CatalogInfo # NOQA
|
||||
from sphinx.util.tags import Tags # NOQA
|
||||
from typing import Type # for python3.5.1
|
||||
from sphinx.application import Sphinx
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -83,8 +84,7 @@ class Builder:
|
||||
#: The builder supports data URIs or not.
|
||||
supported_data_uri_images = False
|
||||
|
||||
def __init__(self, app):
|
||||
# type: (Sphinx) -> None
|
||||
def __init__(self, app: "Sphinx") -> None:
|
||||
self.srcdir = app.srcdir
|
||||
self.confdir = app.confdir
|
||||
self.outdir = app.outdir
|
||||
@ -93,6 +93,7 @@ class Builder:
|
||||
|
||||
self.app = app # type: Sphinx
|
||||
self.env = None # type: BuildEnvironment
|
||||
self.events = app.events # type: EventManager
|
||||
self.config = app.config # type: Config
|
||||
self.tags = app.tags # type: Tags
|
||||
self.tags.add(self.format)
|
||||
@ -111,20 +112,17 @@ class Builder:
|
||||
self.parallel_ok = False
|
||||
self.finish_tasks = None # type: Any
|
||||
|
||||
def set_environment(self, env):
|
||||
# type: (BuildEnvironment) -> None
|
||||
def set_environment(self, env: BuildEnvironment) -> None:
|
||||
"""Store BuildEnvironment object."""
|
||||
self.env = env
|
||||
self.env.set_versioning_method(self.versioning_method,
|
||||
self.versioning_compare)
|
||||
|
||||
def get_translator_class(self, *args):
|
||||
# type: (Any) -> Type[nodes.NodeVisitor]
|
||||
def get_translator_class(self, *args: Any) -> "Type[nodes.NodeVisitor]":
|
||||
"""Return a class of translator."""
|
||||
return self.app.registry.get_translator_class(self)
|
||||
|
||||
def create_translator(self, *args):
|
||||
# type: (Any) -> nodes.NodeVisitor
|
||||
def create_translator(self, *args: Any) -> nodes.NodeVisitor:
|
||||
"""Return an instance of translator.
|
||||
|
||||
This method returns an instance of ``default_translator_class`` by default.
|
||||
@ -133,15 +131,13 @@ class Builder:
|
||||
return self.app.registry.create_translator(self, *args)
|
||||
|
||||
# helper methods
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
def init(self) -> None:
|
||||
"""Load necessary templates and perform initialization. The default
|
||||
implementation does nothing.
|
||||
"""
|
||||
pass
|
||||
|
||||
def create_template_bridge(self):
|
||||
# type: () -> None
|
||||
def create_template_bridge(self) -> None:
|
||||
"""Return the template bridge configured."""
|
||||
if self.config.template_bridge:
|
||||
self.templates = import_object(self.config.template_bridge,
|
||||
@ -150,8 +146,7 @@ class Builder:
|
||||
from sphinx.jinja2glue import BuiltinTemplateLoader
|
||||
self.templates = BuiltinTemplateLoader()
|
||||
|
||||
def get_target_uri(self, docname, typ=None):
|
||||
# type: (str, str) -> str
|
||||
def get_target_uri(self, docname: str, typ: str = None) -> str:
|
||||
"""Return the target URI for a document name.
|
||||
|
||||
*typ* can be used to qualify the link characteristic for individual
|
||||
@ -159,8 +154,7 @@ class Builder:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_relative_uri(self, from_, to, typ=None):
|
||||
# type: (str, str, str) -> str
|
||||
def get_relative_uri(self, from_: str, to: str, typ: str = None) -> str:
|
||||
"""Return a relative URI between two source filenames.
|
||||
|
||||
May raise environment.NoUri if there's no way to return a sensible URI.
|
||||
@ -168,8 +162,7 @@ class Builder:
|
||||
return relative_uri(self.get_target_uri(from_),
|
||||
self.get_target_uri(to, typ))
|
||||
|
||||
def get_outdated_docs(self):
|
||||
# type: () -> Union[str, Iterable[str]]
|
||||
def get_outdated_docs(self) -> Union[str, Iterable[str]]:
|
||||
"""Return an iterable of output files that are outdated, or a string
|
||||
describing what an update build will build.
|
||||
|
||||
@ -179,13 +172,11 @@ class Builder:
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def get_asset_paths(self):
|
||||
# type: () -> List[str]
|
||||
def get_asset_paths(self) -> List[str]:
|
||||
"""Return list of paths for assets (ex. templates, CSS, etc.)."""
|
||||
return []
|
||||
|
||||
def post_process_images(self, doctree):
|
||||
# type: (nodes.Node) -> None
|
||||
def post_process_images(self, doctree: Node) -> None:
|
||||
"""Pick the best candidate for all image URIs."""
|
||||
images = ImageAdapter(self.env)
|
||||
for node in doctree.traverse(nodes.image):
|
||||
@ -218,13 +209,11 @@ class Builder:
|
||||
|
||||
# compile po methods
|
||||
|
||||
def compile_catalogs(self, catalogs, message):
|
||||
# type: (Set[CatalogInfo], str) -> None
|
||||
def compile_catalogs(self, catalogs: Set[CatalogInfo], message: str) -> None:
|
||||
if not self.config.gettext_auto_build:
|
||||
return
|
||||
|
||||
def cat2relpath(cat):
|
||||
# type: (CatalogInfo) -> str
|
||||
def cat2relpath(cat: CatalogInfo) -> str:
|
||||
return relpath(cat.mo_path, self.env.srcdir).replace(path.sep, SEP)
|
||||
|
||||
logger.info(bold(__('building [mo]: ')) + message)
|
||||
@ -233,17 +222,14 @@ class Builder:
|
||||
stringify_func=cat2relpath):
|
||||
catalog.write_mo(self.config.language)
|
||||
|
||||
def compile_all_catalogs(self):
|
||||
# type: () -> None
|
||||
def compile_all_catalogs(self) -> None:
|
||||
repo = CatalogRepository(self.srcdir, self.config.locale_dirs,
|
||||
self.config.language, self.config.source_encoding)
|
||||
message = __('all of %d po files') % len(list(repo.catalogs))
|
||||
self.compile_catalogs(set(repo.catalogs), message)
|
||||
|
||||
def compile_specific_catalogs(self, specified_files):
|
||||
# type: (List[str]) -> None
|
||||
def to_domain(fpath):
|
||||
# type: (str) -> str
|
||||
def compile_specific_catalogs(self, specified_files: List[str]) -> None:
|
||||
def to_domain(fpath: str) -> str:
|
||||
docname = self.env.path2doc(path.abspath(fpath))
|
||||
if docname:
|
||||
return docname_to_domain(docname, self.config.gettext_compact)
|
||||
@ -260,8 +246,7 @@ class Builder:
|
||||
message = __('targets for %d po files that are specified') % len(catalogs)
|
||||
self.compile_catalogs(catalogs, message)
|
||||
|
||||
def compile_update_catalogs(self):
|
||||
# type: () -> None
|
||||
def compile_update_catalogs(self) -> None:
|
||||
repo = CatalogRepository(self.srcdir, self.config.locale_dirs,
|
||||
self.config.language, self.config.source_encoding)
|
||||
catalogs = {c for c in repo.catalogs if c.is_outdated()}
|
||||
@ -270,13 +255,11 @@ class Builder:
|
||||
|
||||
# build methods
|
||||
|
||||
def build_all(self):
|
||||
# type: () -> None
|
||||
def build_all(self) -> None:
|
||||
"""Build all source files."""
|
||||
self.build(None, summary=__('all source files'), method='all')
|
||||
|
||||
def build_specific(self, filenames):
|
||||
# type: (List[str]) -> None
|
||||
def build_specific(self, filenames: List[str]) -> None:
|
||||
"""Only rebuild as much as needed for changes in the *filenames*."""
|
||||
# bring the filenames to the canonical format, that is,
|
||||
# relative to the source directory and without source_suffix.
|
||||
@ -304,8 +287,7 @@ class Builder:
|
||||
self.build(to_write, method='specific',
|
||||
summary=__('%d source files given on command line') % len(to_write))
|
||||
|
||||
def build_update(self):
|
||||
# type: () -> None
|
||||
def build_update(self) -> None:
|
||||
"""Only rebuild what was changed or added since last build."""
|
||||
to_build = self.get_outdated_docs()
|
||||
if isinstance(to_build, str):
|
||||
@ -316,14 +298,13 @@ class Builder:
|
||||
summary=__('targets for %d source files that are out of date') %
|
||||
len(to_build))
|
||||
|
||||
def build(self, docnames, summary=None, method='update'):
|
||||
# type: (Iterable[str], str, str) -> None
|
||||
def build(self, docnames: Iterable[str], summary: str = None, method: str = 'update') -> None: # NOQA
|
||||
"""Main build method.
|
||||
|
||||
First updates the environment, and then calls :meth:`write`.
|
||||
"""
|
||||
if summary:
|
||||
logger.info(bold(__('building [%s]') % self.name) + ': ' + summary)
|
||||
logger.info(bold(__('building [%s]: ') % self.name) + summary)
|
||||
|
||||
# while reading, collect all warnings from docutils
|
||||
with logging.pending_warnings():
|
||||
@ -385,8 +366,7 @@ class Builder:
|
||||
# wait for all tasks
|
||||
self.finish_tasks.join()
|
||||
|
||||
def read(self):
|
||||
# type: () -> List[str]
|
||||
def read(self) -> List[str]:
|
||||
"""(Re-)read all files new or changed since last update.
|
||||
|
||||
Store all environment docnames in the canonical format (ie using SEP as
|
||||
@ -399,7 +379,7 @@ class Builder:
|
||||
added, changed, removed = self.env.get_outdated_files(updated)
|
||||
|
||||
# allow user intervention as well
|
||||
for docs in self.app.emit('env-get-outdated', self, added, changed, removed):
|
||||
for docs in self.events.emit('env-get-outdated', self, added, changed, removed):
|
||||
changed.update(set(docs) & self.env.found_docs)
|
||||
|
||||
# if files were added or removed, all documents with globbed toctrees
|
||||
@ -408,21 +388,23 @@ class Builder:
|
||||
# ... but not those that already were removed
|
||||
changed.update(self.env.glob_toctrees & self.env.found_docs)
|
||||
|
||||
if changed:
|
||||
reason = CONFIG_CHANGED_REASON.get(self.env.config_status, '')
|
||||
if updated: # explain the change iff build config status was not ok
|
||||
reason = (CONFIG_CHANGED_REASON.get(self.env.config_status, '') +
|
||||
(self.env.config_status_extra or ''))
|
||||
logger.info('[%s] ', reason, nonl=True)
|
||||
|
||||
logger.info(__('%s added, %s changed, %s removed'),
|
||||
len(added), len(changed), len(removed))
|
||||
|
||||
# clear all files no longer present
|
||||
for docname in removed:
|
||||
self.app.emit('env-purge-doc', self.env, docname)
|
||||
self.events.emit('env-purge-doc', self.env, docname)
|
||||
self.env.clear_doc(docname)
|
||||
|
||||
# read all new and changed files
|
||||
docnames = sorted(added | changed)
|
||||
# allow changing and reordering the list of docs to read
|
||||
self.app.emit('env-before-read-docs', self.env, docnames)
|
||||
self.events.emit('env-before-read-docs', self.env, docnames)
|
||||
|
||||
# check if we should do parallel or serial read
|
||||
if parallel_available and len(docnames) > 5 and self.app.parallel > 1:
|
||||
@ -439,7 +421,7 @@ class Builder:
|
||||
raise SphinxError('master file %s not found' %
|
||||
self.env.doc2path(self.config.master_doc))
|
||||
|
||||
for retval in self.app.emit('env-updated', self.env):
|
||||
for retval in self.events.emit('env-updated', self.env):
|
||||
if retval is not None:
|
||||
docnames.extend(retval)
|
||||
|
||||
@ -448,32 +430,28 @@ class Builder:
|
||||
|
||||
return sorted(docnames)
|
||||
|
||||
def _read_serial(self, docnames):
|
||||
# type: (List[str]) -> None
|
||||
def _read_serial(self, docnames: List[str]) -> None:
|
||||
for docname in status_iterator(docnames, __('reading sources... '), "purple",
|
||||
len(docnames), self.app.verbosity):
|
||||
# remove all inventory entries for that file
|
||||
self.app.emit('env-purge-doc', self.env, docname)
|
||||
self.events.emit('env-purge-doc', self.env, docname)
|
||||
self.env.clear_doc(docname)
|
||||
self.read_doc(docname)
|
||||
|
||||
def _read_parallel(self, docnames, nproc):
|
||||
# type: (List[str], int) -> None
|
||||
def _read_parallel(self, docnames: List[str], nproc: int) -> None:
|
||||
# clear all outdated docs at once
|
||||
for docname in docnames:
|
||||
self.app.emit('env-purge-doc', self.env, docname)
|
||||
self.events.emit('env-purge-doc', self.env, docname)
|
||||
self.env.clear_doc(docname)
|
||||
|
||||
def read_process(docs):
|
||||
# type: (List[str]) -> bytes
|
||||
def read_process(docs: List[str]) -> bytes:
|
||||
self.env.app = self.app
|
||||
for docname in docs:
|
||||
self.read_doc(docname)
|
||||
# allow pickling self to send it back
|
||||
return pickle.dumps(self.env, pickle.HIGHEST_PROTOCOL)
|
||||
|
||||
def merge(docs, otherenv):
|
||||
# type: (List[str], bytes) -> None
|
||||
def merge(docs: List[str], otherenv: bytes) -> None:
|
||||
env = pickle.loads(otherenv)
|
||||
self.env.merge_info_from(docs, env, self.app)
|
||||
|
||||
@ -488,8 +466,7 @@ class Builder:
|
||||
logger.info(bold(__('waiting for workers...')))
|
||||
tasks.join()
|
||||
|
||||
def read_doc(self, docname):
|
||||
# type: (str) -> None
|
||||
def read_doc(self, docname: str) -> None:
|
||||
"""Parse a file and add/update inventory entries for the doctree."""
|
||||
self.env.prepare_settings(docname)
|
||||
|
||||
@ -514,8 +491,7 @@ class Builder:
|
||||
|
||||
self.write_doctree(docname, doctree)
|
||||
|
||||
def write_doctree(self, docname, doctree):
|
||||
# type: (str, nodes.document) -> None
|
||||
def write_doctree(self, docname: str, doctree: nodes.document) -> None:
|
||||
"""Write the doctree to a file."""
|
||||
# make it picklable
|
||||
doctree.reporter = None
|
||||
@ -529,8 +505,7 @@ class Builder:
|
||||
with open(doctree_filename, 'wb') as f:
|
||||
pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
|
||||
|
||||
def write(self, build_docnames, updated_docnames, method='update'):
|
||||
# type: (Iterable[str], Sequence[str], str) -> None
|
||||
def write(self, build_docnames: Iterable[str], updated_docnames: Sequence[str], method: str = 'update') -> None: # NOQA
|
||||
if build_docnames is None or build_docnames == ['__all__']:
|
||||
# build_all
|
||||
build_docnames = self.env.found_docs
|
||||
@ -559,8 +534,7 @@ class Builder:
|
||||
else:
|
||||
self._write_serial(sorted(docnames))
|
||||
|
||||
def _write_serial(self, docnames):
|
||||
# type: (Sequence[str]) -> None
|
||||
def _write_serial(self, docnames: Sequence[str]) -> None:
|
||||
with logging.pending_warnings():
|
||||
for docname in status_iterator(docnames, __('writing output... '), "darkgreen",
|
||||
len(docnames), self.app.verbosity):
|
||||
@ -570,10 +544,8 @@ class Builder:
|
||||
self.write_doc_serialized(docname, doctree)
|
||||
self.write_doc(docname, doctree)
|
||||
|
||||
def _write_parallel(self, docnames, nproc):
|
||||
# type: (Sequence[str], int) -> None
|
||||
def write_process(docs):
|
||||
# type: (List[Tuple[str, nodes.document]]) -> None
|
||||
def _write_parallel(self, docnames: Sequence[str], nproc: int) -> None:
|
||||
def write_process(docs: List[Tuple[str, nodes.document]]) -> None:
|
||||
self.app.phase = BuildPhase.WRITING
|
||||
for docname, doctree in docs:
|
||||
self.write_doc(docname, doctree)
|
||||
@ -603,41 +575,35 @@ class Builder:
|
||||
logger.info(bold(__('waiting for workers...')))
|
||||
tasks.join()
|
||||
|
||||
def prepare_writing(self, docnames):
|
||||
# type: (Set[str]) -> None
|
||||
def prepare_writing(self, docnames: Set[str]) -> None:
|
||||
"""A place where you can add logic before :meth:`write_doc` is run"""
|
||||
raise NotImplementedError
|
||||
|
||||
def write_doc(self, docname, doctree):
|
||||
# type: (str, nodes.document) -> None
|
||||
def write_doc(self, docname: str, doctree: nodes.document) -> None:
|
||||
"""Where you actually write something to the filesystem."""
|
||||
raise NotImplementedError
|
||||
|
||||
def write_doc_serialized(self, docname, doctree):
|
||||
# type: (str, nodes.document) -> None
|
||||
def write_doc_serialized(self, docname: str, doctree: nodes.document) -> None:
|
||||
"""Handle parts of write_doc that must be called in the main process
|
||||
if parallel build is active.
|
||||
"""
|
||||
pass
|
||||
|
||||
def finish(self):
|
||||
# type: () -> None
|
||||
def finish(self) -> None:
|
||||
"""Finish the building process.
|
||||
|
||||
The default implementation does nothing.
|
||||
"""
|
||||
pass
|
||||
|
||||
def cleanup(self):
|
||||
# type: () -> None
|
||||
def cleanup(self) -> None:
|
||||
"""Cleanup any resources.
|
||||
|
||||
The default implementation does nothing.
|
||||
"""
|
||||
pass
|
||||
|
||||
def get_builder_config(self, option, default):
|
||||
# type: (str, str) -> Any
|
||||
def get_builder_config(self, option: str, default: str) -> Any:
|
||||
"""Return a builder specific option.
|
||||
|
||||
This method allows customization of common builder settings by
|
||||
|
@ -4,18 +4,21 @@
|
||||
|
||||
Base class of epub2/epub3 builders.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import html
|
||||
import os
|
||||
import re
|
||||
import warnings
|
||||
from collections import namedtuple
|
||||
from os import path
|
||||
from typing import Any, Dict, List, Set, Tuple
|
||||
from zipfile import ZIP_DEFLATED, ZIP_STORED, ZipFile
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.nodes import Element, Node
|
||||
from docutils.utils import smartquotes
|
||||
|
||||
from sphinx import addnodes
|
||||
@ -33,11 +36,6 @@ try:
|
||||
except ImportError:
|
||||
Image = None
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, List, Set, Tuple # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -93,8 +91,7 @@ Guide = namedtuple('Guide', ['type', 'title', 'uri'])
|
||||
NavPoint = namedtuple('NavPoint', ['navpoint', 'playorder', 'text', 'refuri', 'children'])
|
||||
|
||||
|
||||
def sphinx_smarty_pants(t, language='en'):
|
||||
# type: (str, str) -> str
|
||||
def sphinx_smarty_pants(t: str, language: str = 'en') -> str:
|
||||
t = t.replace('"', '"')
|
||||
t = smartquotes.educateDashesOldSchool(t)
|
||||
t = smartquotes.educateQuotes(t, language)
|
||||
@ -145,8 +142,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
template_dir = ""
|
||||
doctype = ""
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
def init(self) -> None:
|
||||
super().init()
|
||||
# the output files for epub must be .html only
|
||||
self.out_suffix = '.xhtml'
|
||||
@ -157,17 +153,14 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
self.use_index = self.get_builder_config('use_index', 'epub')
|
||||
self.refnodes = [] # type: List[Dict[str, Any]]
|
||||
|
||||
def create_build_info(self):
|
||||
# type: () -> BuildInfo
|
||||
def create_build_info(self) -> BuildInfo:
|
||||
return BuildInfo(self.config, self.tags, ['html', 'epub'])
|
||||
|
||||
def get_theme_config(self):
|
||||
# type: () -> Tuple[str, Dict]
|
||||
def get_theme_config(self) -> Tuple[str, Dict]:
|
||||
return self.config.epub_theme, self.config.epub_theme_options
|
||||
|
||||
# generic support functions
|
||||
def make_id(self, name):
|
||||
# type: (str) -> str
|
||||
def make_id(self, name: str) -> str:
|
||||
# id_cache is intentionally mutable
|
||||
"""Return a unique id for name."""
|
||||
id = self.id_cache.get(name)
|
||||
@ -176,10 +169,11 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
self.id_cache[name] = id
|
||||
return id
|
||||
|
||||
def esc(self, name):
|
||||
# type: (str) -> str
|
||||
def esc(self, name: str) -> str:
|
||||
"""Replace all characters not allowed in text an attribute values."""
|
||||
# Like cgi.escape, but also replace apostrophe
|
||||
warnings.warn(
|
||||
'%s.esc() is deprecated. Use html.escape() instead.' % self.__class__.__name__,
|
||||
RemovedInSphinx40Warning)
|
||||
name = name.replace('&', '&')
|
||||
name = name.replace('<', '<')
|
||||
name = name.replace('>', '>')
|
||||
@ -187,8 +181,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
name = name.replace('\'', ''')
|
||||
return name
|
||||
|
||||
def get_refnodes(self, doctree, result):
|
||||
# type: (nodes.Node, List[Dict[str, Any]]) -> List[Dict[str, Any]]
|
||||
def get_refnodes(self, doctree: Node, result: List[Dict[str, Any]]) -> List[Dict[str, Any]]: # NOQA
|
||||
"""Collect section titles, their depth in the toc and the refuri."""
|
||||
# XXX: is there a better way than checking the attribute
|
||||
# toctree-l[1-8] on the parent node?
|
||||
@ -202,8 +195,8 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
if (self.toctree_template % level) in classes:
|
||||
result.append({
|
||||
'level': level,
|
||||
'refuri': self.esc(refuri),
|
||||
'text': ssp(self.esc(doctree.astext()))
|
||||
'refuri': html.escape(refuri),
|
||||
'text': ssp(html.escape(doctree.astext()))
|
||||
})
|
||||
break
|
||||
elif isinstance(doctree, nodes.Element):
|
||||
@ -211,8 +204,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
result = self.get_refnodes(elem, result)
|
||||
return result
|
||||
|
||||
def check_refnodes(self, nodes):
|
||||
# type: (List[Dict[str, Any]]) -> None
|
||||
def check_refnodes(self, nodes: List[Dict[str, Any]]) -> None:
|
||||
appeared = set() # type: Set[str]
|
||||
for node in nodes:
|
||||
if node['refuri'] in appeared:
|
||||
@ -220,8 +212,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
else:
|
||||
appeared.add(node['refuri'])
|
||||
|
||||
def get_toc(self):
|
||||
# type: () -> None
|
||||
def get_toc(self) -> None:
|
||||
"""Get the total table of contents, containing the master_doc
|
||||
and pre and post files not managed by sphinx.
|
||||
"""
|
||||
@ -236,36 +227,33 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
item['refuri'] = master_dir + item['refuri']
|
||||
self.toc_add_files(self.refnodes)
|
||||
|
||||
def toc_add_files(self, refnodes):
|
||||
# type: (List[Dict[str, Any]]) -> None
|
||||
def toc_add_files(self, refnodes: List[Dict[str, Any]]) -> None:
|
||||
"""Add the master_doc, pre and post files to a list of refnodes.
|
||||
"""
|
||||
refnodes.insert(0, {
|
||||
'level': 1,
|
||||
'refuri': self.esc(self.config.master_doc + self.out_suffix),
|
||||
'text': ssp(self.esc(
|
||||
'refuri': html.escape(self.config.master_doc + self.out_suffix),
|
||||
'text': ssp(html.escape(
|
||||
self.env.titles[self.config.master_doc].astext()))
|
||||
})
|
||||
for file, text in reversed(self.config.epub_pre_files):
|
||||
refnodes.insert(0, {
|
||||
'level': 1,
|
||||
'refuri': self.esc(file),
|
||||
'text': ssp(self.esc(text))
|
||||
'refuri': html.escape(file),
|
||||
'text': ssp(html.escape(text))
|
||||
})
|
||||
for file, text in self.config.epub_post_files:
|
||||
refnodes.append({
|
||||
'level': 1,
|
||||
'refuri': self.esc(file),
|
||||
'text': ssp(self.esc(text))
|
||||
'refuri': html.escape(file),
|
||||
'text': ssp(html.escape(text))
|
||||
})
|
||||
|
||||
def fix_fragment(self, prefix, fragment):
|
||||
# type: (str, str) -> str
|
||||
def fix_fragment(self, prefix: str, fragment: str) -> str:
|
||||
"""Return a href/id attribute with colons replaced by hyphens."""
|
||||
return prefix + fragment.replace(':', '-')
|
||||
|
||||
def fix_ids(self, tree):
|
||||
# type: (nodes.document) -> None
|
||||
def fix_ids(self, tree: nodes.document) -> None:
|
||||
"""Replace colons with hyphens in href and id attributes.
|
||||
|
||||
Some readers crash because they interpret the part as a
|
||||
@ -284,7 +272,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
if ':' in node_id:
|
||||
target['ids'][i] = self.fix_fragment('', node_id)
|
||||
|
||||
next_node = target.next_node(siblings=True) # type: nodes.Node
|
||||
next_node = target.next_node(ascend=True) # type: Node
|
||||
if isinstance(next_node, nodes.Element):
|
||||
for i, node_id in enumerate(next_node['ids']):
|
||||
if ':' in node_id:
|
||||
@ -297,20 +285,17 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
newids.append(self.fix_fragment('', id))
|
||||
desc_signature.attributes['ids'] = newids
|
||||
|
||||
def add_visible_links(self, tree, show_urls='inline'):
|
||||
# type: (nodes.document, str) -> None
|
||||
def add_visible_links(self, tree: nodes.document, show_urls: str = 'inline') -> None:
|
||||
"""Add visible link targets for external links"""
|
||||
|
||||
def make_footnote_ref(doc, label):
|
||||
# type: (nodes.document, str) -> nodes.footnote_reference
|
||||
def make_footnote_ref(doc: nodes.document, label: str) -> nodes.footnote_reference:
|
||||
"""Create a footnote_reference node with children"""
|
||||
footnote_ref = nodes.footnote_reference('[#]_')
|
||||
footnote_ref.append(nodes.Text(label))
|
||||
doc.note_autofootnote_ref(footnote_ref)
|
||||
return footnote_ref
|
||||
|
||||
def make_footnote(doc, label, uri):
|
||||
# type: (nodes.document, str, str) -> nodes.footnote
|
||||
def make_footnote(doc: nodes.document, label: str, uri: str) -> nodes.footnote:
|
||||
"""Create a footnote node with children"""
|
||||
footnote = nodes.footnote(uri)
|
||||
para = nodes.paragraph()
|
||||
@ -320,8 +305,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
doc.note_autofootnote(footnote)
|
||||
return footnote
|
||||
|
||||
def footnote_spot(tree):
|
||||
# type: (nodes.document) -> Tuple[nodes.Element, int]
|
||||
def footnote_spot(tree: nodes.document) -> Tuple[Element, int]:
|
||||
"""Find or create a spot to place footnotes.
|
||||
|
||||
The function returns the tuple (parent, index)."""
|
||||
@ -369,8 +353,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
footnote.add_backref(footnote_ref['ids'][0])
|
||||
fn_idx += 1
|
||||
|
||||
def write_doc(self, docname, doctree):
|
||||
# type: (str, nodes.document) -> None
|
||||
def write_doc(self, docname: str, doctree: nodes.document) -> None:
|
||||
"""Write one document file.
|
||||
|
||||
This method is overwritten in order to fix fragment identifiers
|
||||
@ -380,8 +363,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
self.add_visible_links(doctree, self.config.epub_show_urls)
|
||||
super().write_doc(docname, doctree)
|
||||
|
||||
def fix_genindex(self, tree):
|
||||
# type: (List[Tuple[str, List[Tuple[str, Any]]]]) -> None
|
||||
def fix_genindex(self, tree: List[Tuple[str, List[Tuple[str, Any]]]]) -> None:
|
||||
"""Fix href attributes for genindex pages."""
|
||||
# XXX: modifies tree inline
|
||||
# Logic modeled from themes/basic/genindex.html
|
||||
@ -399,14 +381,12 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
subentrylinks[i] = (ismain,
|
||||
self.fix_fragment(m.group(1), m.group(2)))
|
||||
|
||||
def is_vector_graphics(self, filename):
|
||||
# type: (str) -> bool
|
||||
def is_vector_graphics(self, filename: str) -> bool:
|
||||
"""Does the filename extension indicate a vector graphic format?"""
|
||||
ext = path.splitext(filename)[-1]
|
||||
return ext in VECTOR_GRAPHICS_EXTENSIONS
|
||||
|
||||
def copy_image_files_pil(self):
|
||||
# type: () -> None
|
||||
def copy_image_files_pil(self) -> None:
|
||||
"""Copy images using Pillow, the Python Imaging Libary.
|
||||
The method tries to read and write the files with Pillow, converting
|
||||
the format and resizing the image if necessary/possible.
|
||||
@ -445,8 +425,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
logger.warning(__('cannot write image file %r: %s'),
|
||||
path.join(self.srcdir, src), err)
|
||||
|
||||
def copy_image_files(self):
|
||||
# type: () -> None
|
||||
def copy_image_files(self) -> None:
|
||||
"""Copy image files to destination directory.
|
||||
This overwritten method can use Pillow to convert image files.
|
||||
"""
|
||||
@ -460,13 +439,11 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
else:
|
||||
super().copy_image_files()
|
||||
|
||||
def copy_download_files(self):
|
||||
# type: () -> None
|
||||
def copy_download_files(self) -> None:
|
||||
pass
|
||||
|
||||
def handle_page(self, pagename, addctx, templatename='page.html',
|
||||
outfilename=None, event_arg=None):
|
||||
# type: (str, Dict, str, str, Any) -> None
|
||||
def handle_page(self, pagename: str, addctx: Dict, templatename: str = 'page.html',
|
||||
outfilename: str = None, event_arg: Any = None) -> None:
|
||||
"""Create a rendered page.
|
||||
|
||||
This method is overwritten for genindex pages in order to fix href link
|
||||
@ -479,8 +456,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
addctx['doctype'] = self.doctype
|
||||
super().handle_page(pagename, addctx, templatename, outfilename, event_arg)
|
||||
|
||||
def build_mimetype(self, outdir=None, outname='mimetype'):
|
||||
# type: (str, str) -> None
|
||||
def build_mimetype(self, outdir: str = None, outname: str = 'mimetype') -> None:
|
||||
"""Write the metainfo file mimetype."""
|
||||
if outdir:
|
||||
warnings.warn('The arguments of EpubBuilder.build_mimetype() is deprecated.',
|
||||
@ -492,8 +468,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
copy_asset_file(path.join(self.template_dir, 'mimetype'),
|
||||
path.join(outdir, outname))
|
||||
|
||||
def build_container(self, outdir=None, outname='META-INF/container.xml'):
|
||||
# type: (str, str) -> None
|
||||
def build_container(self, outdir: str = None, outname: str = 'META-INF/container.xml') -> None: # NOQA
|
||||
"""Write the metainfo file META-INF/container.xml."""
|
||||
if outdir:
|
||||
warnings.warn('The arguments of EpubBuilder.build_container() is deprecated.',
|
||||
@ -506,28 +481,26 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
ensuredir(path.dirname(filename))
|
||||
copy_asset_file(path.join(self.template_dir, 'container.xml'), filename)
|
||||
|
||||
def content_metadata(self):
|
||||
# type: () -> Dict[str, Any]
|
||||
def content_metadata(self) -> Dict[str, Any]:
|
||||
"""Create a dictionary with all metadata for the content.opf
|
||||
file properly escaped.
|
||||
"""
|
||||
metadata = {} # type: Dict[str, Any]
|
||||
metadata['title'] = self.esc(self.config.epub_title)
|
||||
metadata['author'] = self.esc(self.config.epub_author)
|
||||
metadata['uid'] = self.esc(self.config.epub_uid)
|
||||
metadata['lang'] = self.esc(self.config.epub_language)
|
||||
metadata['publisher'] = self.esc(self.config.epub_publisher)
|
||||
metadata['copyright'] = self.esc(self.config.epub_copyright)
|
||||
metadata['scheme'] = self.esc(self.config.epub_scheme)
|
||||
metadata['id'] = self.esc(self.config.epub_identifier)
|
||||
metadata['date'] = self.esc(format_date("%Y-%m-%d"))
|
||||
metadata['title'] = html.escape(self.config.epub_title)
|
||||
metadata['author'] = html.escape(self.config.epub_author)
|
||||
metadata['uid'] = html.escape(self.config.epub_uid)
|
||||
metadata['lang'] = html.escape(self.config.epub_language)
|
||||
metadata['publisher'] = html.escape(self.config.epub_publisher)
|
||||
metadata['copyright'] = html.escape(self.config.epub_copyright)
|
||||
metadata['scheme'] = html.escape(self.config.epub_scheme)
|
||||
metadata['id'] = html.escape(self.config.epub_identifier)
|
||||
metadata['date'] = html.escape(format_date("%Y-%m-%d"))
|
||||
metadata['manifest_items'] = []
|
||||
metadata['spines'] = []
|
||||
metadata['guides'] = []
|
||||
return metadata
|
||||
|
||||
def build_content(self, outdir=None, outname='content.opf'):
|
||||
# type: (str, str) -> None
|
||||
def build_content(self, outdir: str = None, outname: str = 'content.opf') -> None:
|
||||
"""Write the metainfo file content.opf It contains bibliographic data,
|
||||
a file list and the spine (the reading order).
|
||||
"""
|
||||
@ -567,9 +540,9 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
type='epub', subtype='unknown_project_files')
|
||||
continue
|
||||
filename = filename.replace(os.sep, '/')
|
||||
item = ManifestItem(self.esc(filename),
|
||||
self.esc(self.make_id(filename)),
|
||||
self.esc(self.media_types[ext]))
|
||||
item = ManifestItem(html.escape(filename),
|
||||
html.escape(self.make_id(filename)),
|
||||
html.escape(self.media_types[ext]))
|
||||
metadata['manifest_items'].append(item)
|
||||
self.files.append(filename)
|
||||
|
||||
@ -580,21 +553,21 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
continue
|
||||
if refnode['refuri'] in self.ignored_files:
|
||||
continue
|
||||
spine = Spine(self.esc(self.make_id(refnode['refuri'])), True)
|
||||
spine = Spine(html.escape(self.make_id(refnode['refuri'])), True)
|
||||
metadata['spines'].append(spine)
|
||||
spinefiles.add(refnode['refuri'])
|
||||
for info in self.domain_indices:
|
||||
spine = Spine(self.esc(self.make_id(info[0] + self.out_suffix)), True)
|
||||
spine = Spine(html.escape(self.make_id(info[0] + self.out_suffix)), True)
|
||||
metadata['spines'].append(spine)
|
||||
spinefiles.add(info[0] + self.out_suffix)
|
||||
if self.use_index:
|
||||
spine = Spine(self.esc(self.make_id('genindex' + self.out_suffix)), True)
|
||||
spine = Spine(html.escape(self.make_id('genindex' + self.out_suffix)), True)
|
||||
metadata['spines'].append(spine)
|
||||
spinefiles.add('genindex' + self.out_suffix)
|
||||
# add auto generated files
|
||||
for name in self.files:
|
||||
if name not in spinefiles and name.endswith(self.out_suffix):
|
||||
spine = Spine(self.esc(self.make_id(name)), False)
|
||||
spine = Spine(html.escape(self.make_id(name)), False)
|
||||
metadata['spines'].append(spine)
|
||||
|
||||
# add the optional cover
|
||||
@ -602,18 +575,18 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
if self.config.epub_cover:
|
||||
image, html_tmpl = self.config.epub_cover
|
||||
image = image.replace(os.sep, '/')
|
||||
metadata['cover'] = self.esc(self.make_id(image))
|
||||
metadata['cover'] = html.escape(self.make_id(image))
|
||||
if html_tmpl:
|
||||
spine = Spine(self.esc(self.make_id(self.coverpage_name)), True)
|
||||
spine = Spine(html.escape(self.make_id(self.coverpage_name)), True)
|
||||
metadata['spines'].insert(0, spine)
|
||||
if self.coverpage_name not in self.files:
|
||||
ext = path.splitext(self.coverpage_name)[-1]
|
||||
self.files.append(self.coverpage_name)
|
||||
item = ManifestItem(self.esc(self.coverpage_name),
|
||||
self.esc(self.make_id(self.coverpage_name)),
|
||||
self.esc(self.media_types[ext]))
|
||||
item = ManifestItem(html.escape(self.coverpage_name),
|
||||
html.escape(self.make_id(self.coverpage_name)),
|
||||
html.escape(self.media_types[ext]))
|
||||
metadata['manifest_items'].append(item)
|
||||
ctx = {'image': self.esc(image), 'title': self.config.project}
|
||||
ctx = {'image': html.escape(image), 'title': self.config.project}
|
||||
self.handle_page(
|
||||
path.splitext(self.coverpage_name)[0], ctx, html_tmpl)
|
||||
spinefiles.add(self.coverpage_name)
|
||||
@ -629,25 +602,24 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
auto_add_cover = False
|
||||
if type == 'toc':
|
||||
auto_add_toc = False
|
||||
metadata['guides'].append(Guide(self.esc(type),
|
||||
self.esc(title),
|
||||
self.esc(uri)))
|
||||
metadata['guides'].append(Guide(html.escape(type),
|
||||
html.escape(title),
|
||||
html.escape(uri)))
|
||||
if auto_add_cover and html_tmpl:
|
||||
metadata['guides'].append(Guide('cover',
|
||||
self.guide_titles['cover'],
|
||||
self.esc(self.coverpage_name)))
|
||||
html.escape(self.coverpage_name)))
|
||||
if auto_add_toc and self.refnodes:
|
||||
metadata['guides'].append(Guide('toc',
|
||||
self.guide_titles['toc'],
|
||||
self.esc(self.refnodes[0]['refuri'])))
|
||||
html.escape(self.refnodes[0]['refuri'])))
|
||||
|
||||
# write the project file
|
||||
copy_asset_file(path.join(self.template_dir, 'content.opf_t'),
|
||||
path.join(outdir, outname),
|
||||
metadata)
|
||||
|
||||
def new_navpoint(self, node, level, incr=True):
|
||||
# type: (Dict[str, Any], int, bool) -> NavPoint
|
||||
def new_navpoint(self, node: Dict[str, Any], level: int, incr: bool = True) -> NavPoint:
|
||||
"""Create a new entry in the toc from the node at given level."""
|
||||
# XXX Modifies the node
|
||||
if incr:
|
||||
@ -656,8 +628,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
return NavPoint('navPoint%d' % self.tocid, self.playorder,
|
||||
node['text'], node['refuri'], [])
|
||||
|
||||
def build_navpoints(self, nodes):
|
||||
# type: (List[Dict[str, Any]]) -> List[NavPoint]
|
||||
def build_navpoints(self, nodes: List[Dict[str, Any]]) -> List[NavPoint]:
|
||||
"""Create the toc navigation structure.
|
||||
|
||||
Subelements of a node are nested inside the navpoint. For nested nodes
|
||||
@ -701,20 +672,18 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
|
||||
return navstack[0].children
|
||||
|
||||
def toc_metadata(self, level, navpoints):
|
||||
# type: (int, List[NavPoint]) -> Dict[str, Any]
|
||||
def toc_metadata(self, level: int, navpoints: List[NavPoint]) -> Dict[str, Any]:
|
||||
"""Create a dictionary with all metadata for the toc.ncx file
|
||||
properly escaped.
|
||||
"""
|
||||
metadata = {} # type: Dict[str, Any]
|
||||
metadata['uid'] = self.config.epub_uid
|
||||
metadata['title'] = self.esc(self.config.epub_title)
|
||||
metadata['title'] = html.escape(self.config.epub_title)
|
||||
metadata['level'] = level
|
||||
metadata['navpoints'] = navpoints
|
||||
return metadata
|
||||
|
||||
def build_toc(self, outdir=None, outname='toc.ncx'):
|
||||
# type: (str, str) -> None
|
||||
def build_toc(self, outdir: str = None, outname: str = 'toc.ncx') -> None:
|
||||
"""Write the metainfo file toc.ncx."""
|
||||
if outdir:
|
||||
warnings.warn('The arguments of EpubBuilder.build_toc() is deprecated.',
|
||||
@ -741,8 +710,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
||||
path.join(outdir, outname),
|
||||
self.toc_metadata(level, navpoints))
|
||||
|
||||
def build_epub(self, outdir=None, outname=None):
|
||||
# type: (str, str) -> None
|
||||
def build_epub(self, outdir: str = None, outname: str = None) -> None:
|
||||
"""Write the epub file.
|
||||
|
||||
It is a zip file with the mimetype file stored uncompressed as the first
|
||||
|
@ -4,11 +4,12 @@
|
||||
|
||||
Build Apple help books.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import warnings
|
||||
from typing import Any, Dict
|
||||
|
||||
from sphinxcontrib.applehelp import (
|
||||
AppleHelpCodeSigningFailed,
|
||||
@ -16,13 +17,9 @@ from sphinxcontrib.applehelp import (
|
||||
AppleHelpBuilder,
|
||||
)
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
|
||||
deprecated_alias('sphinx.builders.applehelp',
|
||||
{
|
||||
@ -33,8 +30,7 @@ deprecated_alias('sphinx.builders.applehelp',
|
||||
RemovedInSphinx40Warning)
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
warnings.warn('sphinx.builders.applehelp has been moved to sphinxcontrib-applehelp.',
|
||||
RemovedInSphinx40Warning)
|
||||
app.setup_extension('sphinxcontrib.applehelp')
|
||||
|
@ -4,15 +4,17 @@
|
||||
|
||||
Changelog builder.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import html
|
||||
from os import path
|
||||
from typing import Any, Dict, List, Tuple
|
||||
from typing import cast
|
||||
|
||||
from sphinx import package_dir
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.domains.changeset import ChangeSetDomain
|
||||
from sphinx.locale import _, __
|
||||
@ -22,11 +24,6 @@ from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.fileutil import copy_asset_file
|
||||
from sphinx.util.osutil import ensuredir, os_path
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, List, Tuple # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -38,15 +35,13 @@ class ChangesBuilder(Builder):
|
||||
name = 'changes'
|
||||
epilog = __('The overview file is in %(outdir)s.')
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
def init(self) -> None:
|
||||
self.create_template_bridge()
|
||||
theme_factory = HTMLThemeFactory(self.app)
|
||||
self.theme = theme_factory.create('default')
|
||||
self.templates.init(self, self.theme)
|
||||
|
||||
def get_outdated_docs(self):
|
||||
# type: () -> str
|
||||
def get_outdated_docs(self) -> str:
|
||||
return self.outdir
|
||||
|
||||
typemap = {
|
||||
@ -55,8 +50,7 @@ class ChangesBuilder(Builder):
|
||||
'deprecated': 'deprecated',
|
||||
}
|
||||
|
||||
def write(self, *ignored):
|
||||
# type: (Any) -> None
|
||||
def write(self, *ignored: Any) -> None:
|
||||
version = self.config.version
|
||||
domain = cast(ChangeSetDomain, self.env.get_domain('changeset'))
|
||||
libchanges = {} # type: Dict[str, List[Tuple[str, str, int]]]
|
||||
@ -83,8 +77,7 @@ class ChangesBuilder(Builder):
|
||||
entry = '<b>%s</b>: <i>%s</i>.' % (descname, ttext)
|
||||
apichanges.append((entry, changeset.docname, changeset.lineno))
|
||||
elif descname or changeset.module:
|
||||
if not changeset.module:
|
||||
module = _('Builtins')
|
||||
module = changeset.module or _('Builtins')
|
||||
if not descname:
|
||||
descname = _('Module level')
|
||||
if context:
|
||||
@ -122,8 +115,7 @@ class ChangesBuilder(Builder):
|
||||
'.. versionchanged:: %s' % version,
|
||||
'.. deprecated:: %s' % version]
|
||||
|
||||
def hl(no, line):
|
||||
# type: (int, str) -> str
|
||||
def hl(no: int, line: str) -> str:
|
||||
line = '<a name="L%s"> </a>' % no + html.escape(line)
|
||||
for x in hltext:
|
||||
if x in line:
|
||||
@ -149,28 +141,25 @@ class ChangesBuilder(Builder):
|
||||
'text': text
|
||||
}
|
||||
f.write(self.templates.render('changes/rstsource.html', ctx))
|
||||
themectx = dict(('theme_' + key, val) for (key, val) in
|
||||
self.theme.get_options({}).items())
|
||||
themectx = {'theme_' + key: val for (key, val) in
|
||||
self.theme.get_options({}).items()}
|
||||
copy_asset_file(path.join(package_dir, 'themes', 'default', 'static', 'default.css_t'),
|
||||
self.outdir, context=themectx, renderer=self.templates)
|
||||
copy_asset_file(path.join(package_dir, 'themes', 'basic', 'static', 'basic.css'),
|
||||
self.outdir)
|
||||
|
||||
def hl(self, text, version):
|
||||
# type: (str, str) -> str
|
||||
def hl(self, text: str, version: str) -> str:
|
||||
text = html.escape(text)
|
||||
for directive in ['versionchanged', 'versionadded', 'deprecated']:
|
||||
text = text.replace('.. %s:: %s' % (directive, version),
|
||||
'<b>.. %s:: %s</b>' % (directive, version))
|
||||
return text
|
||||
|
||||
def finish(self):
|
||||
# type: () -> None
|
||||
def finish(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.add_builder(ChangesBuilder)
|
||||
|
||||
return {
|
||||
|
@ -6,23 +6,19 @@
|
||||
|
||||
.. _Devhelp: https://wiki.gnome.org/Apps/Devhelp
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import warnings
|
||||
from typing import Any, Dict
|
||||
|
||||
from sphinxcontrib.devhelp import DevhelpBuilder
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
|
||||
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
|
||||
deprecated_alias('sphinx.builders.devhelp',
|
||||
{
|
||||
'DevhelpBuilder': DevhelpBuilder,
|
||||
@ -30,8 +26,7 @@ deprecated_alias('sphinx.builders.devhelp',
|
||||
RemovedInSphinx40Warning)
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
warnings.warn('sphinx.builders.devhelp has been moved to sphinxcontrib-devhelp.',
|
||||
RemovedInSphinx40Warning)
|
||||
app.setup_extension('sphinxcontrib.devhelp')
|
||||
|
@ -4,21 +4,19 @@
|
||||
|
||||
Directory HTML builders.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from os import path
|
||||
from typing import Any, Dict
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders.html import StandaloneHTMLBuilder
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.osutil import SEP, os_path
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, Set # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -30,16 +28,14 @@ class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
|
||||
"""
|
||||
name = 'dirhtml'
|
||||
|
||||
def get_target_uri(self, docname, typ=None):
|
||||
# type: (str, str) -> str
|
||||
def get_target_uri(self, docname: str, typ: str = None) -> str:
|
||||
if docname == 'index':
|
||||
return ''
|
||||
if docname.endswith(SEP + 'index'):
|
||||
return docname[:-5] # up to sep
|
||||
return docname + SEP
|
||||
|
||||
def get_outfilename(self, pagename):
|
||||
# type: (str) -> str
|
||||
def get_outfilename(self, pagename: str) -> str:
|
||||
if pagename == 'index' or pagename.endswith(SEP + 'index'):
|
||||
outfilename = path.join(self.outdir, os_path(pagename) +
|
||||
self.out_suffix)
|
||||
@ -49,14 +45,16 @@ class DirectoryHTMLBuilder(StandaloneHTMLBuilder):
|
||||
|
||||
return outfilename
|
||||
|
||||
def prepare_writing(self, docnames):
|
||||
# type: (Set[str]) -> None
|
||||
super().prepare_writing(docnames)
|
||||
self.globalcontext['no_search_suffix'] = True
|
||||
|
||||
# for compatibility
|
||||
deprecated_alias('sphinx.builders.html',
|
||||
{
|
||||
'DirectoryHTMLBuilder': DirectoryHTMLBuilder,
|
||||
},
|
||||
RemovedInSphinx40Warning)
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.setup_extension('sphinx.builders.html')
|
||||
|
||||
app.add_builder(DirectoryHTMLBuilder)
|
||||
|
@ -8,16 +8,14 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from typing import Any, Dict, Set
|
||||
|
||||
from docutils.nodes import Node
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.locale import __
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, Set # NOQA
|
||||
from docutils import nodes # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
|
||||
class DummyBuilder(Builder):
|
||||
name = 'dummy'
|
||||
@ -25,33 +23,26 @@ class DummyBuilder(Builder):
|
||||
|
||||
allow_parallel = True
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
def init(self) -> None:
|
||||
pass
|
||||
|
||||
def get_outdated_docs(self):
|
||||
# type: () -> Set[str]
|
||||
def get_outdated_docs(self) -> Set[str]:
|
||||
return self.env.found_docs
|
||||
|
||||
def get_target_uri(self, docname, typ=None):
|
||||
# type: (str, str) -> str
|
||||
def get_target_uri(self, docname: str, typ: str = None) -> str:
|
||||
return ''
|
||||
|
||||
def prepare_writing(self, docnames):
|
||||
# type: (Set[str]) -> None
|
||||
def prepare_writing(self, docnames: Set[str]) -> None:
|
||||
pass
|
||||
|
||||
def write_doc(self, docname, doctree):
|
||||
# type: (str, nodes.Node) -> None
|
||||
def write_doc(self, docname: str, doctree: Node) -> None:
|
||||
pass
|
||||
|
||||
def finish(self):
|
||||
# type: () -> None
|
||||
def finish(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.add_builder(DummyBuilder)
|
||||
|
||||
return {
|
||||
|
@ -9,13 +9,16 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import html
|
||||
import warnings
|
||||
from collections import namedtuple
|
||||
from os import path
|
||||
from typing import Any, Dict, List, Set, Tuple
|
||||
|
||||
from sphinx import package_dir
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import _epub_base
|
||||
from sphinx.config import ENUM
|
||||
from sphinx.config import Config, ENUM
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import logging, xmlname_checker
|
||||
@ -23,13 +26,6 @@ from sphinx.util.fileutil import copy_asset_file
|
||||
from sphinx.util.i18n import format_date
|
||||
from sphinx.util.osutil import make_filename
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, Iterable, List, Set, Tuple # NOQA
|
||||
from docutils import nodes # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -75,8 +71,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
|
||||
use_meta_charset = True
|
||||
|
||||
# Finish by building the epub file
|
||||
def handle_finish(self):
|
||||
# type: () -> None
|
||||
def handle_finish(self) -> None:
|
||||
"""Create the metainfo files and finally the epub."""
|
||||
self.get_toc()
|
||||
self.build_mimetype()
|
||||
@ -86,30 +81,27 @@ class Epub3Builder(_epub_base.EpubBuilder):
|
||||
self.build_toc()
|
||||
self.build_epub()
|
||||
|
||||
def validate_config_value(self):
|
||||
# type: () -> None
|
||||
def validate_config_value(self) -> None:
|
||||
warnings.warn('Epub3Builder.validate_config_value() is deprecated.',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
|
||||
def content_metadata(self):
|
||||
# type: () -> Dict
|
||||
def content_metadata(self) -> Dict:
|
||||
"""Create a dictionary with all metadata for the content.opf
|
||||
file properly escaped.
|
||||
"""
|
||||
writing_mode = self.config.epub_writing_mode
|
||||
|
||||
metadata = super().content_metadata()
|
||||
metadata['description'] = self.esc(self.config.epub_description)
|
||||
metadata['contributor'] = self.esc(self.config.epub_contributor)
|
||||
metadata['description'] = html.escape(self.config.epub_description)
|
||||
metadata['contributor'] = html.escape(self.config.epub_contributor)
|
||||
metadata['page_progression_direction'] = PAGE_PROGRESSION_DIRECTIONS.get(writing_mode)
|
||||
metadata['ibook_scroll_axis'] = IBOOK_SCROLL_AXIS.get(writing_mode)
|
||||
metadata['date'] = self.esc(format_date("%Y-%m-%dT%H:%M:%SZ"))
|
||||
metadata['version'] = self.esc(self.config.version)
|
||||
metadata['date'] = html.escape(format_date("%Y-%m-%dT%H:%M:%SZ"))
|
||||
metadata['version'] = html.escape(self.config.version)
|
||||
metadata['epub_version'] = self.config.epub_version
|
||||
return metadata
|
||||
|
||||
def prepare_writing(self, docnames):
|
||||
# type: (Set[str]) -> None
|
||||
def prepare_writing(self, docnames: Set[str]) -> None:
|
||||
super().prepare_writing(docnames)
|
||||
|
||||
writing_mode = self.config.epub_writing_mode
|
||||
@ -118,8 +110,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
|
||||
self.globalcontext['use_meta_charset'] = self.use_meta_charset
|
||||
self.globalcontext['skip_ua_compatible'] = True
|
||||
|
||||
def build_navlist(self, navnodes):
|
||||
# type: (List[Dict[str, Any]]) -> List[NavPoint]
|
||||
def build_navlist(self, navnodes: List[Dict[str, Any]]) -> List[NavPoint]:
|
||||
"""Create the toc navigation structure.
|
||||
|
||||
This method is almost same as build_navpoints method in epub.py.
|
||||
@ -161,19 +152,17 @@ class Epub3Builder(_epub_base.EpubBuilder):
|
||||
|
||||
return navstack[0].children
|
||||
|
||||
def navigation_doc_metadata(self, navlist):
|
||||
# type: (List[NavPoint]) -> Dict
|
||||
def navigation_doc_metadata(self, navlist: List[NavPoint]) -> Dict:
|
||||
"""Create a dictionary with all metadata for the nav.xhtml file
|
||||
properly escaped.
|
||||
"""
|
||||
metadata = {} # type: Dict
|
||||
metadata['lang'] = self.esc(self.config.epub_language)
|
||||
metadata['toc_locale'] = self.esc(self.guide_titles['toc'])
|
||||
metadata['lang'] = html.escape(self.config.epub_language)
|
||||
metadata['toc_locale'] = html.escape(self.guide_titles['toc'])
|
||||
metadata['navlist'] = navlist
|
||||
return metadata
|
||||
|
||||
def build_navigation_doc(self, outdir=None, outname='nav.xhtml'):
|
||||
# type: (str, str) -> None
|
||||
def build_navigation_doc(self, outdir: str = None, outname: str = 'nav.xhtml') -> None:
|
||||
"""Write the metainfo file nav.xhtml."""
|
||||
if outdir:
|
||||
warnings.warn('The arguments of Epub3Builder.build_navigation_doc() '
|
||||
@ -202,8 +191,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
|
||||
self.files.append(outname)
|
||||
|
||||
|
||||
def validate_config_values(app):
|
||||
# type: (Sphinx) -> None
|
||||
def validate_config_values(app: Sphinx) -> None:
|
||||
if app.builder.name != 'epub':
|
||||
return
|
||||
|
||||
@ -242,8 +230,7 @@ def validate_config_values(app):
|
||||
logger.warning(__('conf value "version" should not be empty for EPUB3'))
|
||||
|
||||
|
||||
def convert_epub_css_files(app, config):
|
||||
# type: (Sphinx, Config) -> None
|
||||
def convert_epub_css_files(app: Sphinx, config: Config) -> None:
|
||||
"""This converts string styled epub_css_files to tuple styled one."""
|
||||
epub_css_files = [] # type: List[Tuple[str, Dict]]
|
||||
for entry in config.epub_css_files:
|
||||
@ -260,8 +247,7 @@ def convert_epub_css_files(app, config):
|
||||
config.epub_css_files = epub_css_files # type: ignore
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.add_builder(Epub3Builder)
|
||||
|
||||
# config values
|
||||
|
@ -4,36 +4,39 @@
|
||||
|
||||
The MessageCatalogBuilder class.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from codecs import open
|
||||
from collections import defaultdict, OrderedDict
|
||||
from datetime import datetime, tzinfo, timedelta
|
||||
from io import StringIO
|
||||
from os import path, walk, getenv
|
||||
from time import time
|
||||
from typing import Any, Dict, Iterable, Generator, List, Set, Tuple, Union
|
||||
from uuid import uuid4
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.nodes import Element
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx import package_dir
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.domains.python import pairindextypes
|
||||
from sphinx.errors import ThemeError
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import split_index_msg, logging, status_iterator
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.i18n import docname_to_domain
|
||||
from sphinx.util.i18n import CatalogInfo, docname_to_domain
|
||||
from sphinx.util.nodes import extract_messages, traverse_translatable_index
|
||||
from sphinx.util.osutil import relpath, ensuredir, canon_path
|
||||
from sphinx.util.osutil import ensuredir, canon_path, relpath
|
||||
from sphinx.util.tags import Tags
|
||||
from sphinx.util.template import SphinxRenderer
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, DefaultDict, Dict, Iterable, List, Set, Tuple, Union # NOQA
|
||||
from docutils import nodes # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.util.i18n import CatalogInfo # NOQA
|
||||
|
||||
from typing import DefaultDict # for python3.5.1
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -56,21 +59,27 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
"""[1:]
|
||||
"""[1:] # RemovedInSphinx40Warning
|
||||
|
||||
|
||||
class Message:
|
||||
"""An entry of translatable message."""
|
||||
def __init__(self, text: str, locations: List[Tuple[str, int]], uuids: List[str]):
|
||||
self.text = text
|
||||
self.locations = locations
|
||||
self.uuids = uuids
|
||||
|
||||
|
||||
class Catalog:
|
||||
"""Catalog of translatable messages."""
|
||||
|
||||
def __init__(self):
|
||||
# type: () -> None
|
||||
def __init__(self) -> None:
|
||||
self.messages = [] # type: List[str]
|
||||
# retain insertion order, a la OrderedDict
|
||||
self.metadata = OrderedDict() # type: Dict[str, List[Tuple[str, int, str]]]
|
||||
# msgid -> file, line, uid
|
||||
|
||||
def add(self, msg, origin):
|
||||
# type: (str, Union[nodes.Element, MsgOrigin]) -> None
|
||||
def add(self, msg: str, origin: Union[Element, "MsgOrigin"]) -> None:
|
||||
if not hasattr(origin, 'uid'):
|
||||
# Nodes that are replicated like todo don't have a uid,
|
||||
# however i18n is also unnecessary.
|
||||
@ -80,27 +89,55 @@ class Catalog:
|
||||
self.metadata[msg] = []
|
||||
self.metadata[msg].append((origin.source, origin.line, origin.uid)) # type: ignore
|
||||
|
||||
def __iter__(self) -> Generator[Message, None, None]:
|
||||
for message in self.messages:
|
||||
positions = [(source, line) for source, line, uuid in self.metadata[message]]
|
||||
uuids = [uuid for source, line, uuid in self.metadata[message]]
|
||||
yield Message(message, positions, uuids)
|
||||
|
||||
|
||||
class MsgOrigin:
|
||||
"""
|
||||
Origin holder for Catalog message origin.
|
||||
"""
|
||||
|
||||
def __init__(self, source, line):
|
||||
# type: (str, int) -> None
|
||||
def __init__(self, source: str, line: int) -> None:
|
||||
self.source = source
|
||||
self.line = line
|
||||
self.uid = uuid4().hex
|
||||
|
||||
|
||||
class GettextRenderer(SphinxRenderer):
|
||||
def __init__(self, template_path: str = None, outdir: str = None) -> None:
|
||||
self.outdir = outdir
|
||||
if template_path is None:
|
||||
template_path = path.join(package_dir, 'templates', 'gettext')
|
||||
super().__init__(template_path)
|
||||
|
||||
def escape(s: str) -> str:
|
||||
s = s.replace('\\', r'\\')
|
||||
s = s.replace('"', r'\"')
|
||||
return s.replace('\n', '\\n"\n"')
|
||||
|
||||
# use texescape as escape filter
|
||||
self.env.filters['e'] = escape
|
||||
self.env.filters['escape'] = escape
|
||||
|
||||
def render(self, filename: str, context: Dict) -> str:
|
||||
def _relpath(s: str) -> str:
|
||||
return canon_path(relpath(s, self.outdir))
|
||||
|
||||
context['relpath'] = _relpath
|
||||
return super().render(filename, context)
|
||||
|
||||
|
||||
class I18nTags(Tags):
|
||||
"""Dummy tags module for I18nBuilder.
|
||||
|
||||
To translate all text inside of only nodes, this class
|
||||
always returns True value even if no tags are defined.
|
||||
"""
|
||||
def eval_condition(self, condition):
|
||||
# type: (Any) -> bool
|
||||
def eval_condition(self, condition: Any) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
@ -114,34 +151,33 @@ class I18nBuilder(Builder):
|
||||
# be set by `gettext_uuid`
|
||||
use_message_catalog = False
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
def init(self) -> None:
|
||||
super().init()
|
||||
self.env.set_versioning_method(self.versioning_method,
|
||||
self.env.config.gettext_uuid)
|
||||
self.tags = I18nTags()
|
||||
self.catalogs = defaultdict(Catalog) # type: DefaultDict[str, Catalog]
|
||||
|
||||
def get_target_uri(self, docname, typ=None):
|
||||
# type: (str, str) -> str
|
||||
def get_target_uri(self, docname: str, typ: str = None) -> str:
|
||||
return ''
|
||||
|
||||
def get_outdated_docs(self):
|
||||
# type: () -> Set[str]
|
||||
def get_outdated_docs(self) -> Set[str]:
|
||||
return self.env.found_docs
|
||||
|
||||
def prepare_writing(self, docnames):
|
||||
# type: (Set[str]) -> None
|
||||
def prepare_writing(self, docnames: Set[str]) -> None:
|
||||
return
|
||||
|
||||
def compile_catalogs(self, catalogs, message):
|
||||
# type: (Set[CatalogInfo], str) -> None
|
||||
def compile_catalogs(self, catalogs: Set[CatalogInfo], message: str) -> None:
|
||||
return
|
||||
|
||||
def write_doc(self, docname, doctree):
|
||||
# type: (str, nodes.document) -> None
|
||||
def write_doc(self, docname: str, doctree: nodes.document) -> None:
|
||||
catalog = self.catalogs[docname_to_domain(docname, self.config.gettext_compact)]
|
||||
|
||||
for toctree in self.env.tocs[docname].traverse(addnodes.toctree):
|
||||
for node, msg in extract_messages(toctree):
|
||||
node.uid = '' # type: ignore # Hack UUID model
|
||||
catalog.add(msg, node)
|
||||
|
||||
for node, msg in extract_messages(doctree):
|
||||
catalog.add(msg, node)
|
||||
|
||||
@ -170,26 +206,21 @@ if source_date_epoch is not None:
|
||||
|
||||
|
||||
class LocalTimeZone(tzinfo):
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
# type: (Any, Any) -> None
|
||||
super().__init__(*args, **kw) # type: ignore
|
||||
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
||||
super().__init__(*args, **kwargs) # type: ignore
|
||||
self.tzdelta = tzdelta
|
||||
|
||||
def utcoffset(self, dt):
|
||||
# type: (datetime) -> timedelta
|
||||
def utcoffset(self, dt: datetime) -> timedelta:
|
||||
return self.tzdelta
|
||||
|
||||
def dst(self, dt):
|
||||
# type: (datetime) -> timedelta
|
||||
def dst(self, dt: datetime) -> timedelta:
|
||||
return timedelta(0)
|
||||
|
||||
|
||||
ltz = LocalTimeZone()
|
||||
|
||||
|
||||
def should_write(filepath, new_content):
|
||||
# type: (str, str) -> bool
|
||||
def should_write(filepath: str, new_content: str) -> bool:
|
||||
if not path.exists(filepath):
|
||||
return True
|
||||
try:
|
||||
@ -214,14 +245,12 @@ class MessageCatalogBuilder(I18nBuilder):
|
||||
name = 'gettext'
|
||||
epilog = __('The message catalogs are in %(outdir)s.')
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
def init(self) -> None:
|
||||
super().init()
|
||||
self.create_template_bridge()
|
||||
self.templates.init(self)
|
||||
|
||||
def _collect_templates(self):
|
||||
# type: () -> Set[str]
|
||||
def _collect_templates(self) -> Set[str]:
|
||||
template_files = set()
|
||||
for template_path in self.config.templates_path:
|
||||
tmpl_abs_path = path.join(self.app.srcdir, template_path)
|
||||
@ -232,8 +261,7 @@ class MessageCatalogBuilder(I18nBuilder):
|
||||
template_files.add(filename)
|
||||
return template_files
|
||||
|
||||
def _extract_from_template(self):
|
||||
# type: () -> None
|
||||
def _extract_from_template(self) -> None:
|
||||
files = list(self._collect_templates())
|
||||
files.sort()
|
||||
logger.info(bold(__('building [%s]: ') % self.name), nonl=True)
|
||||
@ -252,20 +280,21 @@ class MessageCatalogBuilder(I18nBuilder):
|
||||
except Exception as exc:
|
||||
raise ThemeError('%s: %r' % (template, exc))
|
||||
|
||||
def build(self, docnames, summary=None, method='update'):
|
||||
# type: (Iterable[str], str, str) -> None
|
||||
def build(self, docnames: Iterable[str], summary: str = None, method: str = 'update') -> None: # NOQA
|
||||
self._extract_from_template()
|
||||
super().build(docnames, summary, method)
|
||||
|
||||
def finish(self):
|
||||
# type: () -> None
|
||||
def finish(self) -> None:
|
||||
super().finish()
|
||||
data = {
|
||||
context = {
|
||||
'version': self.config.version,
|
||||
'copyright': self.config.copyright,
|
||||
'project': self.config.project,
|
||||
'ctime': datetime.fromtimestamp(
|
||||
timestamp, ltz).strftime('%Y-%m-%d %H:%M%z'),
|
||||
'last_translator': self.config.gettext_last_translator,
|
||||
'language_team': self.config.gettext_language_team,
|
||||
'ctime': datetime.fromtimestamp(timestamp, ltz).strftime('%Y-%m-%d %H:%M%z'),
|
||||
'display_location': self.config.gettext_location,
|
||||
'display_uuid': self.config.gettext_uuid,
|
||||
}
|
||||
for textdomain, catalog in status_iterator(self.catalogs.items(),
|
||||
__("writing message catalogs... "),
|
||||
@ -275,37 +304,16 @@ class MessageCatalogBuilder(I18nBuilder):
|
||||
# noop if config.gettext_compact is set
|
||||
ensuredir(path.join(self.outdir, path.dirname(textdomain)))
|
||||
|
||||
context['messages'] = list(catalog)
|
||||
content = GettextRenderer(outdir=self.outdir).render('message.pot_t', context)
|
||||
|
||||
pofn = path.join(self.outdir, textdomain + '.pot')
|
||||
output = StringIO()
|
||||
output.write(POHEADER % data)
|
||||
|
||||
for message in catalog.messages:
|
||||
positions = catalog.metadata[message]
|
||||
|
||||
if self.config.gettext_location:
|
||||
# generate "#: file1:line1\n#: file2:line2 ..."
|
||||
output.write("#: %s\n" % "\n#: ".join(
|
||||
"%s:%s" % (canon_path(relpath(source, self.outdir)), line)
|
||||
for source, line, _ in positions))
|
||||
if self.config.gettext_uuid:
|
||||
# generate "# uuid1\n# uuid2\n ..."
|
||||
output.write("# %s\n" % "\n# ".join(uid for _, _, uid in positions))
|
||||
|
||||
# message contains *one* line of text ready for translation
|
||||
message = message.replace('\\', r'\\'). \
|
||||
replace('"', r'\"'). \
|
||||
replace('\n', '\\n"\n"')
|
||||
output.write('msgid "%s"\nmsgstr ""\n\n' % message)
|
||||
|
||||
content = output.getvalue()
|
||||
|
||||
if should_write(pofn, content):
|
||||
with open(pofn, 'w', encoding='utf-8') as pofile:
|
||||
pofile.write(content)
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.add_builder(MessageCatalogBuilder)
|
||||
|
||||
app.add_config_value('gettext_compact', True, 'gettext')
|
||||
@ -313,6 +321,8 @@ def setup(app):
|
||||
app.add_config_value('gettext_uuid', False, 'gettext')
|
||||
app.add_config_value('gettext_auto_build', True, 'env')
|
||||
app.add_config_value('gettext_additional_targets', [], 'env')
|
||||
app.add_config_value('gettext_last_translator', 'FULL NAME <EMAIL@ADDRESS>', 'gettext')
|
||||
app.add_config_value('gettext_language_team', 'LANGUAGE <LL@li.org>', 'gettext')
|
||||
|
||||
return {
|
||||
'version': 'builtin',
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
Several HTML builders.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -15,18 +15,21 @@ import sys
|
||||
import warnings
|
||||
from hashlib import md5
|
||||
from os import path
|
||||
from typing import Any, Dict, IO, Iterable, Iterator, List, Set, Tuple
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.core import publish_parts
|
||||
from docutils.frontend import OptionParser
|
||||
from docutils.io import DocTreeInput, StringOutput
|
||||
from docutils.nodes import Node
|
||||
from docutils.utils import relative_path
|
||||
|
||||
from sphinx import package_dir, __display_version__
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.deprecation import (
|
||||
RemovedInSphinx30Warning, RemovedInSphinx40Warning, deprecated_alias
|
||||
)
|
||||
from sphinx.config import Config
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning
|
||||
from sphinx.domains import Domain, Index, IndexEntry
|
||||
from sphinx.environment.adapters.asset import ImageAdapter
|
||||
from sphinx.environment.adapters.indexentries import IndexEntries
|
||||
from sphinx.environment.adapters.toctree import TocTree
|
||||
@ -35,25 +38,22 @@ from sphinx.highlighting import PygmentsBridge
|
||||
from sphinx.locale import _, __
|
||||
from sphinx.search import js_index
|
||||
from sphinx.theming import HTMLThemeFactory
|
||||
from sphinx.util import logging, status_iterator
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util import logging, progress_message, status_iterator
|
||||
from sphinx.util.docutils import is_html5_writer_available, new_document
|
||||
from sphinx.util.fileutil import copy_asset
|
||||
from sphinx.util.i18n import format_date
|
||||
from sphinx.util.inventory import InventoryFile
|
||||
from sphinx.util.matching import patmatch, Matcher, DOTFILES
|
||||
from sphinx.util.osutil import os_path, relative_uri, ensuredir, movefile, copyfile
|
||||
from sphinx.util.tags import Tags
|
||||
from sphinx.writers.html import HTMLWriter, HTMLTranslator
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, IO, Iterable, Iterator, List, Set, Type, Tuple # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
from sphinx.domains import Domain, Index, IndexEntry # NOQA
|
||||
from sphinx.util.tags import Tags # NOQA
|
||||
from typing import Type # for python3.5.1
|
||||
|
||||
# HTML5 Writer is avialable or not
|
||||
|
||||
# HTML5 Writer is available or not
|
||||
if is_html5_writer_available():
|
||||
from sphinx.writers.html5 import HTML5Translator
|
||||
html5_ready = True
|
||||
@ -67,8 +67,7 @@ logger = logging.getLogger(__name__)
|
||||
return_codes_re = re.compile('[\r\n]+')
|
||||
|
||||
|
||||
def get_stable_hash(obj):
|
||||
# type: (Any) -> str
|
||||
def get_stable_hash(obj: Any) -> str:
|
||||
"""
|
||||
Return a stable hash for a Python data structure. We can't just use
|
||||
the md5 of str(obj) since for example dictionary items are enumerated
|
||||
@ -91,8 +90,7 @@ class Stylesheet(str):
|
||||
attributes = None # type: Dict[str, str]
|
||||
filename = None # type: str
|
||||
|
||||
def __new__(cls, filename, *args, **attributes):
|
||||
# type: (str, str, str) -> None
|
||||
def __new__(cls, filename: str, *args: str, **attributes: str) -> "Stylesheet":
|
||||
self = str.__new__(cls, filename) # type: ignore
|
||||
self.filename = filename
|
||||
self.attributes = attributes
|
||||
@ -105,39 +103,6 @@ class Stylesheet(str):
|
||||
return self
|
||||
|
||||
|
||||
class JSContainer(list):
|
||||
"""The container for JavaScript scripts."""
|
||||
def insert(self, index, obj):
|
||||
# type: (int, str) -> None
|
||||
warnings.warn('To modify script_files in the theme is deprecated. '
|
||||
'Please insert a <script> tag directly in your theme instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=3)
|
||||
super().insert(index, obj)
|
||||
|
||||
def extend(self, other): # type: ignore
|
||||
# type: (List[str]) -> None
|
||||
warnings.warn('To modify script_files in the theme is deprecated. '
|
||||
'Please insert a <script> tag directly in your theme instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=3)
|
||||
for item in other:
|
||||
self.append(item)
|
||||
|
||||
def __iadd__(self, other): # type: ignore
|
||||
# type: (List[str]) -> JSContainer
|
||||
warnings.warn('To modify script_files in the theme is deprecated. '
|
||||
'Please insert a <script> tag directly in your theme instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=3)
|
||||
for item in other:
|
||||
self.append(item)
|
||||
return self
|
||||
|
||||
def __add__(self, other):
|
||||
# type: (List[str]) -> JSContainer
|
||||
ret = JSContainer(self)
|
||||
ret += other
|
||||
return ret
|
||||
|
||||
|
||||
class JavaScript(str):
|
||||
"""A metadata of javascript file.
|
||||
|
||||
@ -148,12 +113,10 @@ class JavaScript(str):
|
||||
attributes = None # type: Dict[str, str]
|
||||
filename = None # type: str
|
||||
|
||||
def __new__(cls, filename, **attributes):
|
||||
# type: (str, **str) -> None
|
||||
def __new__(cls, filename: str, **attributes: str) -> "JavaScript":
|
||||
self = str.__new__(cls, filename) # type: ignore
|
||||
self.filename = filename
|
||||
self.attributes = attributes
|
||||
self.attributes.setdefault('type', 'text/javascript')
|
||||
|
||||
return self
|
||||
|
||||
@ -166,8 +129,7 @@ class BuildInfo:
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def load(cls, f):
|
||||
# type: (IO) -> BuildInfo
|
||||
def load(cls, f: IO) -> "BuildInfo":
|
||||
try:
|
||||
lines = f.readlines()
|
||||
assert lines[0].rstrip() == '# Sphinx build info version 1'
|
||||
@ -181,25 +143,22 @@ class BuildInfo:
|
||||
except Exception as exc:
|
||||
raise ValueError(__('build info file is broken: %r') % exc)
|
||||
|
||||
def __init__(self, config=None, tags=None, config_categories=[]):
|
||||
# type: (Config, Tags, List[str]) -> None
|
||||
def __init__(self, config: Config = None, tags: Tags = None, config_categories: List[str] = []) -> None: # NOQA
|
||||
self.config_hash = ''
|
||||
self.tags_hash = ''
|
||||
|
||||
if config:
|
||||
values = dict((c.name, c.value) for c in config.filter(config_categories))
|
||||
values = {c.name: c.value for c in config.filter(config_categories)}
|
||||
self.config_hash = get_stable_hash(values)
|
||||
|
||||
if tags:
|
||||
self.tags_hash = get_stable_hash(sorted(tags))
|
||||
|
||||
def __eq__(self, other): # type: ignore
|
||||
# type: (BuildInfo) -> bool
|
||||
def __eq__(self, other: "BuildInfo") -> bool: # type: ignore
|
||||
return (self.config_hash == other.config_hash and
|
||||
self.tags_hash == other.tags_hash)
|
||||
|
||||
def dump(self, f):
|
||||
# type: (IO) -> None
|
||||
def dump(self, f: IO) -> None:
|
||||
f.write('# Sphinx build info version 1\n'
|
||||
'# This file hashes the configuration used when building these files.'
|
||||
' When it is not found, a full rebuild will be done.\n'
|
||||
@ -239,18 +198,16 @@ class StandaloneHTMLBuilder(Builder):
|
||||
imgpath = None # type: str
|
||||
domain_indices = [] # type: List[Tuple[str, Type[Index], List[Tuple[str, List[IndexEntry]]], bool]] # NOQA
|
||||
|
||||
def __init__(self, app):
|
||||
# type: (Sphinx) -> None
|
||||
def __init__(self, app: Sphinx) -> None:
|
||||
super().__init__(app)
|
||||
|
||||
# CSS files
|
||||
self.css_files = [] # type: List[Dict[str, str]]
|
||||
|
||||
# JS files
|
||||
self.script_files = JSContainer() # type: List[JavaScript]
|
||||
self.script_files = [] # type: List[JavaScript]
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
def init(self) -> None:
|
||||
self.build_info = self.create_build_info()
|
||||
# basename of images directory
|
||||
self.imagedir = '_images'
|
||||
@ -276,12 +233,10 @@ class StandaloneHTMLBuilder(Builder):
|
||||
|
||||
self.use_index = self.get_builder_config('use_index', 'html')
|
||||
|
||||
def create_build_info(self):
|
||||
# type: () -> BuildInfo
|
||||
def create_build_info(self) -> BuildInfo:
|
||||
return BuildInfo(self.config, self.tags, ['html'])
|
||||
|
||||
def _get_translations_js(self):
|
||||
# type: () -> str
|
||||
def _get_translations_js(self) -> str:
|
||||
candidates = [path.join(dir, self.config.language,
|
||||
'LC_MESSAGES', 'sphinx.js')
|
||||
for dir in self.config.locale_dirs] + \
|
||||
@ -295,12 +250,10 @@ class StandaloneHTMLBuilder(Builder):
|
||||
return jsfile
|
||||
return None
|
||||
|
||||
def get_theme_config(self):
|
||||
# type: () -> Tuple[str, Dict]
|
||||
def get_theme_config(self) -> Tuple[str, Dict]:
|
||||
return self.config.html_theme, self.config.html_theme_options
|
||||
|
||||
def init_templates(self):
|
||||
# type: () -> None
|
||||
def init_templates(self) -> None:
|
||||
theme_factory = HTMLThemeFactory(self.app)
|
||||
themename, themeoptions = self.get_theme_config()
|
||||
self.theme = theme_factory.create(themename)
|
||||
@ -308,8 +261,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
self.create_template_bridge()
|
||||
self.templates.init(self, self.theme)
|
||||
|
||||
def init_highlighter(self):
|
||||
# type: () -> None
|
||||
def init_highlighter(self) -> None:
|
||||
# determine Pygments style and create the highlighter
|
||||
if self.config.pygments_style is not None:
|
||||
style = self.config.pygments_style
|
||||
@ -319,23 +271,20 @@ class StandaloneHTMLBuilder(Builder):
|
||||
style = 'sphinx'
|
||||
self.highlighter = PygmentsBridge('html', style)
|
||||
|
||||
def init_css_files(self):
|
||||
# type: () -> None
|
||||
def init_css_files(self) -> None:
|
||||
for filename, attrs in self.app.registry.css_files:
|
||||
self.add_css_file(filename, **attrs)
|
||||
|
||||
for filename, attrs in self.get_builder_config('css_files', 'html'):
|
||||
self.add_css_file(filename, **attrs)
|
||||
|
||||
def add_css_file(self, filename, **kwargs):
|
||||
# type: (str, **str) -> None
|
||||
def add_css_file(self, filename: str, **kwargs: str) -> None:
|
||||
if '://' not in filename:
|
||||
filename = posixpath.join('_static', filename)
|
||||
|
||||
self.css_files.append(Stylesheet(filename, **kwargs)) # type: ignore
|
||||
|
||||
def init_js_files(self):
|
||||
# type: () -> None
|
||||
def init_js_files(self) -> None:
|
||||
self.add_js_file('jquery.js')
|
||||
self.add_js_file('underscore.js')
|
||||
self.add_js_file('doctools.js')
|
||||
@ -350,24 +299,21 @@ class StandaloneHTMLBuilder(Builder):
|
||||
if self.config.language and self._get_translations_js():
|
||||
self.add_js_file('translations.js')
|
||||
|
||||
def add_js_file(self, filename, **kwargs):
|
||||
# type: (str, **str) -> None
|
||||
def add_js_file(self, filename: str, **kwargs: str) -> None:
|
||||
if filename and '://' not in filename:
|
||||
filename = posixpath.join('_static', filename)
|
||||
|
||||
self.script_files.append(JavaScript(filename, **kwargs))
|
||||
|
||||
@property
|
||||
def default_translator_class(self): # type: ignore
|
||||
# type: () -> Type[nodes.NodeVisitor]
|
||||
def default_translator_class(self) -> "Type[nodes.NodeVisitor]": # type: ignore
|
||||
if not html5_ready or self.config.html4_writer:
|
||||
return HTMLTranslator
|
||||
else:
|
||||
return HTML5Translator
|
||||
|
||||
@property
|
||||
def math_renderer_name(self):
|
||||
# type: () -> str
|
||||
def math_renderer_name(self) -> str:
|
||||
name = self.get_builder_config('math_renderer', 'html')
|
||||
if name is not None:
|
||||
# use given name
|
||||
@ -386,8 +332,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
# many math_renderers are registered. can't choose automatically!
|
||||
return None
|
||||
|
||||
def get_outdated_docs(self):
|
||||
# type: () -> Iterator[str]
|
||||
def get_outdated_docs(self) -> Iterator[str]:
|
||||
try:
|
||||
with open(path.join(self.outdir, '.buildinfo')) as fp:
|
||||
buildinfo = BuildInfo.load(fp)
|
||||
@ -423,12 +368,10 @@ class StandaloneHTMLBuilder(Builder):
|
||||
# source doesn't exist anymore
|
||||
pass
|
||||
|
||||
def get_asset_paths(self):
|
||||
# type: () -> List[str]
|
||||
def get_asset_paths(self) -> List[str]:
|
||||
return self.config.html_extra_path + self.config.html_static_path
|
||||
|
||||
def render_partial(self, node):
|
||||
# type: (nodes.Node) -> Dict[str, str]
|
||||
def render_partial(self, node: Node) -> Dict[str, str]:
|
||||
"""Utility: Render a lone doctree node."""
|
||||
if node is None:
|
||||
return {'fragment': ''}
|
||||
@ -442,8 +385,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
settings_overrides={'output_encoding': 'unicode'},
|
||||
source=doc)
|
||||
|
||||
def prepare_writing(self, docnames):
|
||||
# type: (Set[str]) -> None
|
||||
def prepare_writing(self, docnames: Set[str]) -> None:
|
||||
# create the search indexer
|
||||
self.indexer = None
|
||||
if self.search:
|
||||
@ -490,11 +432,8 @@ class StandaloneHTMLBuilder(Builder):
|
||||
else:
|
||||
self.last_updated = None
|
||||
|
||||
logo = self.config.html_logo and \
|
||||
path.basename(self.config.html_logo) or ''
|
||||
|
||||
favicon = self.config.html_favicon and \
|
||||
path.basename(self.config.html_favicon) or ''
|
||||
logo = path.basename(self.config.html_logo) if self.config.html_logo else ''
|
||||
favicon = path.basename(self.config.html_favicon) if self.config.html_favicon else ''
|
||||
|
||||
if not isinstance(self.config.html_use_opensearch, str):
|
||||
logger.warning(__('html_use_opensearch config value must now be a string'))
|
||||
@ -552,8 +491,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
self.theme.get_options(self.theme_options).items())
|
||||
self.globalcontext.update(self.config.html_context)
|
||||
|
||||
def get_doc_context(self, docname, body, metatags):
|
||||
# type: (str, str, str) -> Dict[str, Any]
|
||||
def get_doc_context(self, docname: str, body: str, metatags: str) -> Dict[str, Any]:
|
||||
"""Collect items for the template context of a page."""
|
||||
# find out relations
|
||||
prev = next = None
|
||||
@ -597,7 +535,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
|
||||
# title rendered as HTML
|
||||
title_node = self.env.longtitles.get(docname)
|
||||
title = title_node and self.render_partial(title_node)['title'] or ''
|
||||
title = self.render_partial(title_node)['title'] if title_node else ''
|
||||
|
||||
# Suffix for the document
|
||||
source_suffix = path.splitext(self.env.doc2path(docname))[1]
|
||||
@ -633,8 +571,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
'page_source_suffix': source_suffix,
|
||||
}
|
||||
|
||||
def write_doc(self, docname, doctree):
|
||||
# type: (str, nodes.document) -> None
|
||||
def write_doc(self, docname: str, doctree: nodes.document) -> None:
|
||||
destination = StringOutput(encoding='utf-8')
|
||||
doctree.settings = self.docsettings
|
||||
|
||||
@ -651,17 +588,16 @@ class StandaloneHTMLBuilder(Builder):
|
||||
ctx = self.get_doc_context(docname, body, metatags)
|
||||
self.handle_page(docname, ctx, event_arg=doctree)
|
||||
|
||||
def write_doc_serialized(self, docname, doctree):
|
||||
# type: (str, nodes.document) -> None
|
||||
def write_doc_serialized(self, docname: str, doctree: nodes.document) -> None:
|
||||
self.imgpath = relative_uri(self.get_target_uri(docname), self.imagedir)
|
||||
self.post_process_images(doctree)
|
||||
title_node = self.env.longtitles.get(docname)
|
||||
title = title_node and self.render_partial(title_node)['title'] or ''
|
||||
title = self.render_partial(title_node)['title'] if title_node else ''
|
||||
self.index_page(docname, doctree, title)
|
||||
|
||||
def finish(self):
|
||||
# type: () -> None
|
||||
def finish(self) -> None:
|
||||
self.finish_tasks.add_task(self.gen_indices)
|
||||
self.finish_tasks.add_task(self.gen_pages_from_extensions)
|
||||
self.finish_tasks.add_task(self.gen_additional_pages)
|
||||
self.finish_tasks.add_task(self.copy_image_files)
|
||||
self.finish_tasks.add_task(self.copy_download_files)
|
||||
@ -672,10 +608,8 @@ class StandaloneHTMLBuilder(Builder):
|
||||
# dump the search index
|
||||
self.handle_finish()
|
||||
|
||||
def gen_indices(self):
|
||||
# type: () -> None
|
||||
logger.info(bold(__('generating indices...')), nonl=True)
|
||||
|
||||
@progress_message(__('generating indices'))
|
||||
def gen_indices(self) -> None:
|
||||
# the global general index
|
||||
if self.use_index:
|
||||
self.write_genindex()
|
||||
@ -683,17 +617,14 @@ class StandaloneHTMLBuilder(Builder):
|
||||
# the global domain-specific indices
|
||||
self.write_domain_indices()
|
||||
|
||||
logger.info('')
|
||||
|
||||
def gen_additional_pages(self):
|
||||
# type: () -> None
|
||||
def gen_pages_from_extensions(self) -> None:
|
||||
# pages from extensions
|
||||
for pagelist in self.app.emit('html-collect-pages'):
|
||||
for pagelist in self.events.emit('html-collect-pages'):
|
||||
for pagename, context, template in pagelist:
|
||||
self.handle_page(pagename, context, template)
|
||||
|
||||
logger.info(bold(__('writing additional pages...')), nonl=True)
|
||||
|
||||
@progress_message(__('writing additional pages'))
|
||||
def gen_additional_pages(self) -> None:
|
||||
# additional pages from conf.py
|
||||
for pagename, template in self.config.html_additional_pages.items():
|
||||
logger.info(' ' + pagename, nonl=True)
|
||||
@ -710,10 +641,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
fn = path.join(self.outdir, '_static', 'opensearch.xml')
|
||||
self.handle_page('opensearch', {}, 'opensearch.xml', outfilename=fn)
|
||||
|
||||
logger.info('')
|
||||
|
||||
def write_genindex(self):
|
||||
# type: () -> None
|
||||
def write_genindex(self) -> None:
|
||||
# the total count of lines for each index letter, used to distribute
|
||||
# the entries into two columns
|
||||
genindex = IndexEntries(self.env).create_index(self)
|
||||
@ -742,8 +670,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
else:
|
||||
self.handle_page('genindex', genindexcontext, 'genindex.html')
|
||||
|
||||
def write_domain_indices(self):
|
||||
# type: () -> None
|
||||
def write_domain_indices(self) -> None:
|
||||
for indexname, indexcls, content, collapse in self.domain_indices:
|
||||
indexcontext = {
|
||||
'indextitle': indexcls.localname,
|
||||
@ -753,8 +680,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
logger.info(' ' + indexname, nonl=True)
|
||||
self.handle_page(indexname, indexcontext, 'domainindex.html')
|
||||
|
||||
def copy_image_files(self):
|
||||
# type: () -> None
|
||||
def copy_image_files(self) -> None:
|
||||
if self.images:
|
||||
stringify_func = ImageAdapter(self.app.env).get_original_image_uri
|
||||
ensuredir(path.join(self.outdir, self.imagedir))
|
||||
@ -769,11 +695,10 @@ class StandaloneHTMLBuilder(Builder):
|
||||
logger.warning(__('cannot copy image file %r: %s'),
|
||||
path.join(self.srcdir, src), err)
|
||||
|
||||
def copy_download_files(self):
|
||||
# type: () -> None
|
||||
def to_relpath(f):
|
||||
# type: (str) -> str
|
||||
def copy_download_files(self) -> None:
|
||||
def to_relpath(f: str) -> str:
|
||||
return relative_path(self.srcdir, f)
|
||||
|
||||
# copy downloadable files
|
||||
if self.env.dlfiles:
|
||||
ensuredir(path.join(self.outdir, '_downloads'))
|
||||
@ -788,105 +713,93 @@ class StandaloneHTMLBuilder(Builder):
|
||||
logger.warning(__('cannot copy downloadable file %r: %s'),
|
||||
path.join(self.srcdir, src), err)
|
||||
|
||||
def copy_static_files(self):
|
||||
# type: () -> None
|
||||
def create_pygments_style_file(self) -> None:
|
||||
"""create a style file for pygments."""
|
||||
with open(path.join(self.outdir, '_static', 'pygments.css'), 'w') as f:
|
||||
f.write(self.highlighter.get_stylesheet())
|
||||
|
||||
def copy_translation_js(self) -> None:
|
||||
"""Copy a JavaScript file for translations."""
|
||||
if self.config.language is not None:
|
||||
jsfile = self._get_translations_js()
|
||||
if jsfile:
|
||||
copyfile(jsfile, path.join(self.outdir, '_static', 'translations.js'))
|
||||
|
||||
def copy_stemmer_js(self) -> None:
|
||||
"""Copy a JavaScript file for stemmer."""
|
||||
if self.indexer is not None:
|
||||
jsfile = self.indexer.get_js_stemmer_rawcode()
|
||||
if jsfile:
|
||||
copyfile(jsfile, path.join(self.outdir, '_static', '_stemmer.js'))
|
||||
|
||||
def copy_theme_static_files(self, context: Dict) -> None:
|
||||
if self.theme:
|
||||
for entry in self.theme.get_theme_dirs()[::-1]:
|
||||
copy_asset(path.join(entry, 'static'),
|
||||
path.join(self.outdir, '_static'),
|
||||
excluded=DOTFILES, context=context, renderer=self.templates)
|
||||
|
||||
def copy_html_static_files(self, context: Dict) -> None:
|
||||
excluded = Matcher(self.config.exclude_patterns + ["**/.*"])
|
||||
for entry in self.config.html_static_path:
|
||||
copy_asset(path.join(self.confdir, entry),
|
||||
path.join(self.outdir, '_static'),
|
||||
excluded, context=context, renderer=self.templates)
|
||||
|
||||
def copy_html_logo(self) -> None:
|
||||
if self.config.html_logo:
|
||||
copy_asset(path.join(self.confdir, self.config.html_logo),
|
||||
path.join(self.outdir, '_static'))
|
||||
|
||||
def copy_html_favicon(self) -> None:
|
||||
if self.config.html_favicon:
|
||||
copy_asset(path.join(self.confdir, self.config.html_favicon),
|
||||
path.join(self.outdir, '_static'))
|
||||
|
||||
def copy_static_files(self) -> None:
|
||||
try:
|
||||
# copy static files
|
||||
logger.info(bold(__('copying static files... ')), nonl=True)
|
||||
ensuredir(path.join(self.outdir, '_static'))
|
||||
# first, create pygments style file
|
||||
with open(path.join(self.outdir, '_static', 'pygments.css'), 'w') as f:
|
||||
f.write(self.highlighter.get_stylesheet())
|
||||
# then, copy translations JavaScript file
|
||||
if self.config.language is not None:
|
||||
jsfile = self._get_translations_js()
|
||||
if jsfile:
|
||||
copyfile(jsfile, path.join(self.outdir, '_static',
|
||||
'translations.js'))
|
||||
with progress_message(__('copying static files... ')):
|
||||
ensuredir(path.join(self.outdir, '_static'))
|
||||
|
||||
# copy non-minified stemmer JavaScript file
|
||||
if self.indexer is not None:
|
||||
jsfile = self.indexer.get_js_stemmer_rawcode()
|
||||
if jsfile:
|
||||
copyfile(jsfile, path.join(self.outdir, '_static', '_stemmer.js'))
|
||||
# prepare context for templates
|
||||
context = self.globalcontext.copy()
|
||||
if self.indexer is not None:
|
||||
context.update(self.indexer.context_for_searchtool())
|
||||
|
||||
ctx = self.globalcontext.copy()
|
||||
|
||||
# add context items for search function used in searchtools.js_t
|
||||
if self.indexer is not None:
|
||||
ctx.update(self.indexer.context_for_searchtool())
|
||||
|
||||
# then, copy over theme-supplied static files
|
||||
if self.theme:
|
||||
for theme_path in self.theme.get_theme_dirs()[::-1]:
|
||||
entry = path.join(theme_path, 'static')
|
||||
copy_asset(entry, path.join(self.outdir, '_static'), excluded=DOTFILES,
|
||||
context=ctx, renderer=self.templates)
|
||||
# then, copy over all user-supplied static files
|
||||
excluded = Matcher(self.config.exclude_patterns + ["**/.*"])
|
||||
for static_path in self.config.html_static_path:
|
||||
entry = path.join(self.confdir, static_path)
|
||||
if not path.exists(entry):
|
||||
logger.warning(__('html_static_path entry %r does not exist'), entry)
|
||||
continue
|
||||
copy_asset(entry, path.join(self.outdir, '_static'), excluded,
|
||||
context=ctx, renderer=self.templates)
|
||||
# copy logo and favicon files if not already in static path
|
||||
if self.config.html_logo:
|
||||
logobase = path.basename(self.config.html_logo)
|
||||
logotarget = path.join(self.outdir, '_static', logobase)
|
||||
if not path.isfile(path.join(self.confdir, self.config.html_logo)):
|
||||
logger.warning(__('logo file %r does not exist'), self.config.html_logo)
|
||||
elif not path.isfile(logotarget):
|
||||
copyfile(path.join(self.confdir, self.config.html_logo),
|
||||
logotarget)
|
||||
if self.config.html_favicon:
|
||||
iconbase = path.basename(self.config.html_favicon)
|
||||
icontarget = path.join(self.outdir, '_static', iconbase)
|
||||
if not path.isfile(path.join(self.confdir, self.config.html_favicon)):
|
||||
logger.warning(__('favicon file %r does not exist'),
|
||||
self.config.html_favicon)
|
||||
elif not path.isfile(icontarget):
|
||||
copyfile(path.join(self.confdir, self.config.html_favicon),
|
||||
icontarget)
|
||||
logger.info(__('done'))
|
||||
self.create_pygments_style_file()
|
||||
self.copy_translation_js()
|
||||
self.copy_stemmer_js()
|
||||
self.copy_theme_static_files(context)
|
||||
self.copy_html_static_files(context)
|
||||
self.copy_html_logo()
|
||||
self.copy_html_favicon()
|
||||
except OSError as err:
|
||||
logger.warning(__('cannot copy static file %r'), err)
|
||||
|
||||
def copy_extra_files(self):
|
||||
# type: () -> None
|
||||
def copy_extra_files(self) -> None:
|
||||
"""copy html_extra_path files."""
|
||||
try:
|
||||
# copy html_extra_path files
|
||||
logger.info(bold(__('copying extra files... ')), nonl=True)
|
||||
excluded = Matcher(self.config.exclude_patterns)
|
||||
|
||||
for extra_path in self.config.html_extra_path:
|
||||
entry = path.join(self.confdir, extra_path)
|
||||
if not path.exists(entry):
|
||||
logger.warning(__('html_extra_path entry %r does not exist'), entry)
|
||||
continue
|
||||
|
||||
copy_asset(entry, self.outdir, excluded)
|
||||
logger.info(__('done'))
|
||||
with progress_message(__('copying extra files')):
|
||||
excluded = Matcher(self.config.exclude_patterns)
|
||||
for extra_path in self.config.html_extra_path:
|
||||
entry = path.join(self.confdir, extra_path)
|
||||
copy_asset(entry, self.outdir, excluded)
|
||||
except OSError as err:
|
||||
logger.warning(__('cannot copy extra file %r'), err)
|
||||
|
||||
def write_buildinfo(self):
|
||||
# type: () -> None
|
||||
def write_buildinfo(self) -> None:
|
||||
try:
|
||||
with open(path.join(self.outdir, '.buildinfo'), 'w') as fp:
|
||||
self.build_info.dump(fp)
|
||||
except OSError as exc:
|
||||
logger.warning(__('Failed to write build info file: %r'), exc)
|
||||
|
||||
def cleanup(self):
|
||||
# type: () -> None
|
||||
def cleanup(self) -> None:
|
||||
# clean up theme stuff
|
||||
if self.theme:
|
||||
self.theme.cleanup()
|
||||
|
||||
def post_process_images(self, doctree):
|
||||
# type: (nodes.Node) -> None
|
||||
def post_process_images(self, doctree: Node) -> None:
|
||||
"""Pick the best candidate for an image and link down-scaled images to
|
||||
their high res version.
|
||||
"""
|
||||
@ -911,8 +824,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
node.replace_self(reference)
|
||||
reference.append(node)
|
||||
|
||||
def load_indexer(self, docnames):
|
||||
# type: (Iterable[str]) -> None
|
||||
def load_indexer(self, docnames: Iterable[str]) -> None:
|
||||
keep = set(self.env.all_docs) - set(docnames)
|
||||
try:
|
||||
searchindexfn = path.join(self.outdir, self.searchindex_filename)
|
||||
@ -930,8 +842,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
# delete all entries for files that will be rebuilt
|
||||
self.indexer.prune(keep)
|
||||
|
||||
def index_page(self, pagename, doctree, title):
|
||||
# type: (str, nodes.document, str) -> None
|
||||
def index_page(self, pagename: str, doctree: nodes.document, title: str) -> None:
|
||||
# only index pages with title
|
||||
if self.indexer is not None and title:
|
||||
filename = self.env.doc2path(pagename, base=None)
|
||||
@ -947,22 +858,19 @@ class StandaloneHTMLBuilder(Builder):
|
||||
indexer_name, indexer_name),
|
||||
RemovedInSphinx40Warning)
|
||||
|
||||
def _get_local_toctree(self, docname, collapse=True, **kwds):
|
||||
# type: (str, bool, Any) -> str
|
||||
if 'includehidden' not in kwds:
|
||||
kwds['includehidden'] = False
|
||||
def _get_local_toctree(self, docname: str, collapse: bool = True, **kwargs: Any) -> str:
|
||||
if 'includehidden' not in kwargs:
|
||||
kwargs['includehidden'] = False
|
||||
return self.render_partial(TocTree(self.env).get_toctree_for(
|
||||
docname, self, collapse, **kwds))['fragment']
|
||||
docname, self, collapse, **kwargs))['fragment']
|
||||
|
||||
def get_outfilename(self, pagename):
|
||||
# type: (str) -> str
|
||||
def get_outfilename(self, pagename: str) -> str:
|
||||
return path.join(self.outdir, os_path(pagename) + self.out_suffix)
|
||||
|
||||
def add_sidebars(self, pagename, ctx):
|
||||
# type: (str, Dict) -> None
|
||||
def has_wildcard(pattern):
|
||||
# type: (str) -> bool
|
||||
def add_sidebars(self, pagename: str, ctx: Dict) -> None:
|
||||
def has_wildcard(pattern: str) -> bool:
|
||||
return any(char in pattern for char in '*?[')
|
||||
|
||||
sidebars = None
|
||||
matched = None
|
||||
customsidebar = None
|
||||
@ -1011,13 +919,11 @@ class StandaloneHTMLBuilder(Builder):
|
||||
|
||||
# --------- these are overwritten by the serialization builder
|
||||
|
||||
def get_target_uri(self, docname, typ=None):
|
||||
# type: (str, str) -> str
|
||||
def get_target_uri(self, docname: str, typ: str = None) -> str:
|
||||
return docname + self.link_suffix
|
||||
|
||||
def handle_page(self, pagename, addctx, templatename='page.html',
|
||||
outfilename=None, event_arg=None):
|
||||
# type: (str, Dict, str, str, Any) -> None
|
||||
def handle_page(self, pagename: str, addctx: Dict, templatename: str = 'page.html',
|
||||
outfilename: str = None, event_arg: Any = None) -> None:
|
||||
ctx = self.globalcontext.copy()
|
||||
# current_page_name is backwards compatibility
|
||||
ctx['pagename'] = ctx['current_page_name'] = pagename
|
||||
@ -1033,8 +939,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
else:
|
||||
ctx['pageurl'] = None
|
||||
|
||||
def pathto(otheruri, resource=False, baseuri=default_baseuri):
|
||||
# type: (str, bool, str) -> str
|
||||
def pathto(otheruri: str, resource: bool = False, baseuri: str = default_baseuri) -> str: # NOQA
|
||||
if resource and '://' in otheruri:
|
||||
# allow non-local resources given by scheme
|
||||
return otheruri
|
||||
@ -1046,8 +951,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
return uri
|
||||
ctx['pathto'] = pathto
|
||||
|
||||
def css_tag(css):
|
||||
# type: (Stylesheet) -> str
|
||||
def css_tag(css: Stylesheet) -> str:
|
||||
attrs = []
|
||||
for key in sorted(css.attributes):
|
||||
value = css.attributes[key]
|
||||
@ -1057,8 +961,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
return '<link %s />' % ' '.join(attrs)
|
||||
ctx['css_tag'] = css_tag
|
||||
|
||||
def hasdoc(name):
|
||||
# type: (str) -> bool
|
||||
def hasdoc(name: str) -> bool:
|
||||
if name in self.env.all_docs:
|
||||
return True
|
||||
elif name == 'search' and self.search:
|
||||
@ -1068,17 +971,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
return False
|
||||
ctx['hasdoc'] = hasdoc
|
||||
|
||||
def warn(*args, **kwargs):
|
||||
# type: (Any, Any) -> str
|
||||
"""Simple warn() wrapper for themes."""
|
||||
warnings.warn('The template function warn() was deprecated. '
|
||||
'Use warning() instead.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
logger.warning(*args, **kwargs)
|
||||
return '' # return empty string
|
||||
ctx['warn'] = warn
|
||||
|
||||
ctx['toctree'] = lambda **kw: self._get_local_toctree(pagename, **kw)
|
||||
ctx['toctree'] = lambda **kwargs: self._get_local_toctree(pagename, **kwargs)
|
||||
self.add_sidebars(pagename, ctx)
|
||||
ctx.update(addctx)
|
||||
|
||||
@ -1116,43 +1009,35 @@ class StandaloneHTMLBuilder(Builder):
|
||||
ensuredir(path.dirname(source_name))
|
||||
copyfile(self.env.doc2path(pagename), source_name)
|
||||
|
||||
def update_page_context(self, pagename, templatename, ctx, event_arg):
|
||||
# type: (str, str, Dict, Any) -> None
|
||||
def update_page_context(self, pagename: str, templatename: str,
|
||||
ctx: Dict, event_arg: Any) -> None:
|
||||
pass
|
||||
|
||||
def handle_finish(self):
|
||||
# type: () -> None
|
||||
def handle_finish(self) -> None:
|
||||
if self.indexer:
|
||||
self.finish_tasks.add_task(self.dump_search_index)
|
||||
self.finish_tasks.add_task(self.dump_inventory)
|
||||
|
||||
def dump_inventory(self):
|
||||
# type: () -> None
|
||||
logger.info(bold(__('dumping object inventory... ')), nonl=True)
|
||||
@progress_message(__('dumping object inventory'))
|
||||
def dump_inventory(self) -> None:
|
||||
InventoryFile.dump(path.join(self.outdir, INVENTORY_FILENAME), self.env, self)
|
||||
logger.info(__('done'))
|
||||
|
||||
def dump_search_index(self):
|
||||
# type: () -> None
|
||||
logger.info(
|
||||
bold(__('dumping search index in %s ... ') % self.indexer.label()),
|
||||
nonl=True)
|
||||
self.indexer.prune(self.env.all_docs)
|
||||
searchindexfn = path.join(self.outdir, self.searchindex_filename)
|
||||
# first write to a temporary file, so that if dumping fails,
|
||||
# the existing index won't be overwritten
|
||||
if self.indexer_dumps_unicode:
|
||||
with open(searchindexfn + '.tmp', 'w', encoding='utf-8') as ft:
|
||||
self.indexer.dump(ft, self.indexer_format)
|
||||
else:
|
||||
with open(searchindexfn + '.tmp', 'wb') as fb:
|
||||
self.indexer.dump(fb, self.indexer_format)
|
||||
movefile(searchindexfn + '.tmp', searchindexfn)
|
||||
logger.info(__('done'))
|
||||
def dump_search_index(self) -> None:
|
||||
with progress_message(__('dumping search index in %s') % self.indexer.label()):
|
||||
self.indexer.prune(self.env.all_docs)
|
||||
searchindexfn = path.join(self.outdir, self.searchindex_filename)
|
||||
# first write to a temporary file, so that if dumping fails,
|
||||
# the existing index won't be overwritten
|
||||
if self.indexer_dumps_unicode:
|
||||
with open(searchindexfn + '.tmp', 'w', encoding='utf-8') as ft:
|
||||
self.indexer.dump(ft, self.indexer_format)
|
||||
else:
|
||||
with open(searchindexfn + '.tmp', 'wb') as fb:
|
||||
self.indexer.dump(fb, self.indexer_format)
|
||||
movefile(searchindexfn + '.tmp', searchindexfn)
|
||||
|
||||
|
||||
def convert_html_css_files(app, config):
|
||||
# type: (Sphinx, Config) -> None
|
||||
def convert_html_css_files(app: Sphinx, config: Config) -> None:
|
||||
"""This converts string styled html_css_files to tuple styled one."""
|
||||
html_css_files = [] # type: List[Tuple[str, Dict]]
|
||||
for entry in config.html_css_files:
|
||||
@ -1169,8 +1054,7 @@ def convert_html_css_files(app, config):
|
||||
config.html_css_files = html_css_files # type: ignore
|
||||
|
||||
|
||||
def convert_html_js_files(app, config):
|
||||
# type: (Sphinx, Config) -> None
|
||||
def convert_html_js_files(app: Sphinx, config: Config) -> None:
|
||||
"""This converts string styled html_js_files to tuple styled one."""
|
||||
html_js_files = [] # type: List[Tuple[str, Dict]]
|
||||
for entry in config.html_js_files:
|
||||
@ -1187,16 +1071,15 @@ def convert_html_js_files(app, config):
|
||||
config.html_js_files = html_js_files # type: ignore
|
||||
|
||||
|
||||
def setup_js_tag_helper(app, pagename, templatexname, context, doctree):
|
||||
# type: (Sphinx, str, str, Dict, nodes.Node) -> None
|
||||
def setup_js_tag_helper(app: Sphinx, pagename: str, templatexname: str,
|
||||
context: Dict, doctree: Node) -> None:
|
||||
"""Set up js_tag() template helper.
|
||||
|
||||
.. note:: This set up function is added to keep compatibility with webhelper.
|
||||
"""
|
||||
pathto = context.get('pathto')
|
||||
|
||||
def js_tag(js):
|
||||
# type: (JavaScript) -> str
|
||||
def js_tag(js: JavaScript) -> str:
|
||||
attrs = []
|
||||
body = ''
|
||||
if isinstance(js, JavaScript):
|
||||
@ -1211,15 +1094,13 @@ def setup_js_tag_helper(app, pagename, templatexname, context, doctree):
|
||||
attrs.append('src="%s"' % pathto(js.filename, resource=True))
|
||||
else:
|
||||
# str value (old styled)
|
||||
attrs.append('type="text/javascript"')
|
||||
attrs.append('src="%s"' % pathto(js, resource=True))
|
||||
return '<script %s>%s</script>' % (' '.join(attrs), body)
|
||||
|
||||
context['js_tag'] = js_tag
|
||||
|
||||
|
||||
def validate_math_renderer(app):
|
||||
# type: (Sphinx) -> None
|
||||
def validate_math_renderer(app: Sphinx) -> None:
|
||||
if app.builder.format != 'html':
|
||||
return
|
||||
|
||||
@ -1231,28 +1112,53 @@ def validate_math_renderer(app):
|
||||
raise ConfigError(__('Unknown math_renderer %r is given.') % name)
|
||||
|
||||
|
||||
def validate_html_extra_path(app: Sphinx, config: Config) -> None:
|
||||
"""Check html_extra_paths setting."""
|
||||
for entry in config.html_extra_path[:]:
|
||||
extra_path = path.normpath(path.join(app.confdir, entry))
|
||||
if not path.exists(extra_path):
|
||||
logger.warning(__('html_extra_path entry %r does not exist'), entry)
|
||||
config.html_extra_path.remove(entry)
|
||||
elif (path.splitdrive(app.outdir)[0] == path.splitdrive(extra_path)[0] and
|
||||
path.commonpath([app.outdir, extra_path]) == app.outdir):
|
||||
logger.warning(__('html_extra_path entry %r is placed inside outdir'), entry)
|
||||
config.html_extra_path.remove(entry)
|
||||
|
||||
|
||||
def validate_html_static_path(app: Sphinx, config: Config) -> None:
|
||||
"""Check html_static_paths setting."""
|
||||
for entry in config.html_static_path[:]:
|
||||
static_path = path.normpath(path.join(app.confdir, entry))
|
||||
if not path.exists(static_path):
|
||||
logger.warning(__('html_static_path entry %r does not exist'), entry)
|
||||
config.html_static_path.remove(entry)
|
||||
elif (path.splitdrive(app.outdir)[0] == path.splitdrive(static_path)[0] and
|
||||
path.commonpath([app.outdir, static_path]) == app.outdir):
|
||||
logger.warning(__('html_static_path entry %r is placed inside outdir'), entry)
|
||||
config.html_static_path.remove(entry)
|
||||
|
||||
|
||||
def validate_html_logo(app: Sphinx, config: Config) -> None:
|
||||
"""Check html_logo setting."""
|
||||
if config.html_logo and not path.isfile(path.join(app.confdir, config.html_logo)):
|
||||
logger.warning(__('logo file %r does not exist'), config.html_logo)
|
||||
config.html_logo = None # type: ignore
|
||||
|
||||
|
||||
def validate_html_favicon(app: Sphinx, config: Config) -> None:
|
||||
"""Check html_favicon setting."""
|
||||
if config.html_favicon and not path.isfile(path.join(app.confdir, config.html_favicon)):
|
||||
logger.warning(__('favicon file %r does not exist'), config.html_favicon)
|
||||
config.html_favicon = None # type: ignore
|
||||
|
||||
|
||||
# for compatibility
|
||||
from sphinx.builders.dirhtml import DirectoryHTMLBuilder # NOQA
|
||||
from sphinx.builders.singlehtml import SingleFileHTMLBuilder # NOQA
|
||||
from sphinxcontrib.serializinghtml import ( # NOQA
|
||||
LAST_BUILD_FILENAME, JSONHTMLBuilder, PickleHTMLBuilder, SerializingHTMLBuilder
|
||||
)
|
||||
|
||||
deprecated_alias('sphinx.builders.html',
|
||||
{
|
||||
'LAST_BUILD_FILENAME': LAST_BUILD_FILENAME,
|
||||
'DirectoryHTMLBuilder': DirectoryHTMLBuilder,
|
||||
'JSONHTMLBuilder': JSONHTMLBuilder,
|
||||
'PickleHTMLBuilder': PickleHTMLBuilder,
|
||||
'SerializingHTMLBuilder': SerializingHTMLBuilder,
|
||||
'SingleFileHTMLBuilder': SingleFileHTMLBuilder,
|
||||
'WebHTMLBuilder': PickleHTMLBuilder,
|
||||
},
|
||||
RemovedInSphinx40Warning)
|
||||
import sphinx.builders.dirhtml # NOQA
|
||||
import sphinx.builders.singlehtml # NOQA
|
||||
import sphinxcontrib.serializinghtml # NOQA
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
# builders
|
||||
app.add_builder(StandaloneHTMLBuilder)
|
||||
|
||||
@ -1301,6 +1207,10 @@ def setup(app):
|
||||
# event handlers
|
||||
app.connect('config-inited', convert_html_css_files)
|
||||
app.connect('config-inited', convert_html_js_files)
|
||||
app.connect('config-inited', validate_html_extra_path)
|
||||
app.connect('config-inited', validate_html_static_path)
|
||||
app.connect('config-inited', validate_html_logo)
|
||||
app.connect('config-inited', validate_html_favicon)
|
||||
app.connect('builder-inited', validate_math_renderer)
|
||||
app.connect('html-page-context', setup_js_tag_helper)
|
||||
|
||||
|
@ -5,26 +5,22 @@
|
||||
Build HTML help support files.
|
||||
Parts adapted from Python's Doc/tools/prechm.py.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import warnings
|
||||
from typing import Any, Dict
|
||||
|
||||
from sphinxcontrib.htmlhelp import (
|
||||
chm_locales, chm_htmlescape, HTMLHelpBuilder, default_htmlhelp_basename
|
||||
)
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
|
||||
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
|
||||
deprecated_alias('sphinx.builders.devhelp',
|
||||
deprecated_alias('sphinx.builders.htmlhelp',
|
||||
{
|
||||
'chm_locales': chm_locales,
|
||||
'chm_htmlescape': chm_htmlescape,
|
||||
@ -34,8 +30,7 @@ deprecated_alias('sphinx.builders.devhelp',
|
||||
RemovedInSphinx40Warning)
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
warnings.warn('sphinx.builders.htmlhelp has been moved to sphinxcontrib-htmlhelp.',
|
||||
RemovedInSphinx40Warning)
|
||||
app.setup_extension('sphinxcontrib.htmlhelp')
|
||||
|
@ -4,30 +4,29 @@
|
||||
|
||||
LaTeX builder.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import os
|
||||
import warnings
|
||||
from os import path
|
||||
from typing import Any, Dict, Iterable, List, Tuple, Union
|
||||
|
||||
from docutils.frontend import OptionParser
|
||||
from docutils.nodes import Node
|
||||
|
||||
import sphinx.builders.latex.nodes # NOQA # Workaround: import this before writer to avoid ImportError
|
||||
from sphinx import package_dir, addnodes, highlighting
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.builders.latex.transforms import (
|
||||
BibliographyTransform, CitationReferenceTransform, MathReferenceTransform,
|
||||
FootnoteDocnameUpdater, LaTeXFootnoteTransform, LiteralBlockTransform,
|
||||
ShowUrlsTransform, DocumentTargetTransform,
|
||||
)
|
||||
from sphinx.builders.latex.constants import ADDITIONAL_SETTINGS, DEFAULT_SETTINGS
|
||||
from sphinx.builders.latex.util import ExtBabel
|
||||
from sphinx.config import ENUM
|
||||
from sphinx.environment import NoUri
|
||||
from sphinx.config import Config, ENUM
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning
|
||||
from sphinx.environment.adapters.asset import ImageAdapter
|
||||
from sphinx.errors import SphinxError
|
||||
from sphinx.errors import NoUri, SphinxError
|
||||
from sphinx.locale import _, __
|
||||
from sphinx.transforms import SphinxTransformer
|
||||
from sphinx.util import texescape, logging, progress_message, status_iterator
|
||||
from sphinx.util.console import bold, darkgreen # type: ignore
|
||||
from sphinx.util.docutils import SphinxFileOutput, new_document
|
||||
@ -36,16 +35,10 @@ from sphinx.util.i18n import format_date
|
||||
from sphinx.util.nodes import inline_all_toctrees
|
||||
from sphinx.util.osutil import SEP, make_filename_from_project
|
||||
from sphinx.util.template import LaTeXRenderer
|
||||
from sphinx.writers.latex import (
|
||||
ADDITIONAL_SETTINGS, DEFAULT_SETTINGS, LaTeXWriter, LaTeXTranslator
|
||||
)
|
||||
from sphinx.writers.latex import LaTeXWriter, LaTeXTranslator
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from docutils import nodes # NOQA
|
||||
from typing import Any, Dict, Iterable, List, Tuple, Union # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
# load docutils.nodes after loading sphinx.builders.latex.nodes
|
||||
from docutils import nodes # NOQA
|
||||
|
||||
|
||||
XINDY_LANG_OPTIONS = {
|
||||
@ -128,8 +121,7 @@ class LaTeXBuilder(Builder):
|
||||
supported_remote_images = False
|
||||
default_translator_class = LaTeXTranslator
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
def init(self) -> None:
|
||||
self.babel = None # type: ExtBabel
|
||||
self.context = {} # type: Dict[str, Any]
|
||||
self.docnames = [] # type: Iterable[str]
|
||||
@ -140,24 +132,20 @@ class LaTeXBuilder(Builder):
|
||||
self.init_context()
|
||||
self.init_babel()
|
||||
|
||||
def get_outdated_docs(self):
|
||||
# type: () -> Union[str, List[str]]
|
||||
def get_outdated_docs(self) -> Union[str, List[str]]:
|
||||
return 'all documents' # for now
|
||||
|
||||
def get_target_uri(self, docname, typ=None):
|
||||
# type: (str, str) -> str
|
||||
def get_target_uri(self, docname: str, typ: str = None) -> str:
|
||||
if docname not in self.docnames:
|
||||
raise NoUri
|
||||
raise NoUri(docname, typ)
|
||||
else:
|
||||
return '%' + docname
|
||||
|
||||
def get_relative_uri(self, from_, to, typ=None):
|
||||
# type: (str, str, str) -> str
|
||||
def get_relative_uri(self, from_: str, to: str, typ: str = None) -> str:
|
||||
# ignore source path
|
||||
return self.get_target_uri(to, typ)
|
||||
|
||||
def init_document_data(self):
|
||||
# type: () -> None
|
||||
def init_document_data(self) -> None:
|
||||
preliminary_document_data = [list(x) for x in self.config.latex_documents]
|
||||
if not preliminary_document_data:
|
||||
logger.warning(__('no "latex_documents" config value found; no documents '
|
||||
@ -176,19 +164,16 @@ class LaTeXBuilder(Builder):
|
||||
docname = docname[:-5]
|
||||
self.titles.append((docname, entry[2]))
|
||||
|
||||
def init_context(self):
|
||||
# type: () -> None
|
||||
def init_context(self) -> None:
|
||||
self.context = DEFAULT_SETTINGS.copy()
|
||||
|
||||
# Add special settings for latex_engine
|
||||
self.context.update(ADDITIONAL_SETTINGS.get(self.config.latex_engine, {}))
|
||||
|
||||
# for xelatex+French, don't use polyglossia by default
|
||||
if self.config.latex_engine == 'xelatex':
|
||||
if self.config.language:
|
||||
if self.config.language[:2] == 'fr':
|
||||
self.context['polyglossia'] = ''
|
||||
self.context['babel'] = r'\usepackage{babel}'
|
||||
# Add special settings for (latex_engine, language_code)
|
||||
if self.config.language:
|
||||
key = (self.config.latex_engine, self.config.language[:2])
|
||||
self.context.update(ADDITIONAL_SETTINGS.get(key, {}))
|
||||
|
||||
# Apply extension settings to context
|
||||
self.context['packages'] = self.usepackages
|
||||
@ -211,10 +196,9 @@ class LaTeXBuilder(Builder):
|
||||
self.context['indexname'] = _('Index')
|
||||
if self.config.release:
|
||||
# Show the release label only if release value exists
|
||||
self.context['releasename'] = _('Release')
|
||||
self.context.setdefault('releasename', _('Release'))
|
||||
|
||||
def init_babel(self):
|
||||
# type: () -> None
|
||||
def init_babel(self) -> None:
|
||||
self.babel = ExtBabel(self.config.language, not self.context['babel'])
|
||||
if self.config.language and not self.babel.is_supported_language():
|
||||
# emit warning if specified language is invalid
|
||||
@ -222,8 +206,7 @@ class LaTeXBuilder(Builder):
|
||||
logger.warning(__('no Babel option known for language %r'),
|
||||
self.config.language)
|
||||
|
||||
def write_stylesheet(self):
|
||||
# type: () -> None
|
||||
def write_stylesheet(self) -> None:
|
||||
highlighter = highlighting.PygmentsBridge('latex', self.config.pygments_style)
|
||||
stylesheet = path.join(self.outdir, 'sphinxhighlight.sty')
|
||||
with open(stylesheet, 'w') as f:
|
||||
@ -232,13 +215,13 @@ class LaTeXBuilder(Builder):
|
||||
'[2016/05/29 stylesheet for highlighting with pygments]\n\n')
|
||||
f.write(highlighter.get_stylesheet())
|
||||
|
||||
def write(self, *ignored):
|
||||
# type: (Any) -> None
|
||||
def write(self, *ignored: Any) -> None:
|
||||
docwriter = LaTeXWriter(self)
|
||||
docsettings = OptionParser(
|
||||
defaults=self.env.settings,
|
||||
components=(docwriter,),
|
||||
read_config_files=True).get_default_values() # type: Any
|
||||
patch_settings(docsettings)
|
||||
|
||||
self.init_document_data()
|
||||
self.write_stylesheet()
|
||||
@ -251,34 +234,33 @@ class LaTeXBuilder(Builder):
|
||||
destination = SphinxFileOutput(destination_path=path.join(self.outdir, targetname),
|
||||
encoding='utf-8', overwrite_if_changed=True)
|
||||
with progress_message(__("processing %s") % targetname):
|
||||
toctrees = self.env.get_doctree(docname).traverse(addnodes.toctree)
|
||||
if toctrees:
|
||||
if toctrees[0].get('maxdepth') > 0:
|
||||
tocdepth = toctrees[0].get('maxdepth')
|
||||
else:
|
||||
tocdepth = None
|
||||
doctree = self.env.get_doctree(docname)
|
||||
toctree = next(iter(doctree.traverse(addnodes.toctree)), None)
|
||||
if toctree and toctree.get('maxdepth') > 0:
|
||||
tocdepth = toctree.get('maxdepth')
|
||||
else:
|
||||
tocdepth = None
|
||||
|
||||
doctree = self.assemble_doctree(
|
||||
docname, toctree_only,
|
||||
appendices=((docclass != 'howto') and self.config.latex_appendices or []))
|
||||
appendices=(self.config.latex_appendices if docclass != 'howto' else []))
|
||||
doctree['docclass'] = docclass
|
||||
doctree['contentsname'] = self.get_contentsname(docname)
|
||||
doctree['tocdepth'] = tocdepth
|
||||
self.apply_transforms(doctree)
|
||||
self.post_process_images(doctree)
|
||||
self.update_doc_context(title, author)
|
||||
|
||||
with progress_message(__("writing")):
|
||||
docsettings.author = author
|
||||
docsettings.title = title
|
||||
docsettings.contentsname = self.get_contentsname(docname)
|
||||
docsettings.docname = docname
|
||||
docsettings.docclass = docclass
|
||||
docsettings._author = author
|
||||
docsettings._title = title
|
||||
docsettings._contentsname = doctree['contentsname']
|
||||
docsettings._docname = docname
|
||||
docsettings._docclass = docclass
|
||||
|
||||
doctree.settings = docsettings
|
||||
docwriter.write(doctree, destination)
|
||||
|
||||
def get_contentsname(self, indexfile):
|
||||
# type: (str) -> str
|
||||
def get_contentsname(self, indexfile: str) -> str:
|
||||
tree = self.env.get_doctree(indexfile)
|
||||
contentsname = None
|
||||
for toctree in tree.traverse(addnodes.toctree):
|
||||
@ -288,14 +270,11 @@ class LaTeXBuilder(Builder):
|
||||
|
||||
return contentsname
|
||||
|
||||
def update_doc_context(self, title, author):
|
||||
# type: (str, str) -> None
|
||||
def update_doc_context(self, title: str, author: str) -> None:
|
||||
self.context['title'] = title
|
||||
self.context['author'] = author
|
||||
|
||||
def assemble_doctree(self, indexfile, toctree_only, appendices):
|
||||
# type: (str, bool, List[str]) -> nodes.document
|
||||
from docutils import nodes # NOQA
|
||||
def assemble_doctree(self, indexfile: str, toctree_only: bool, appendices: List[str]) -> nodes.document: # NOQA
|
||||
self.docnames = set([indexfile] + appendices)
|
||||
logger.info(darkgreen(indexfile) + " ", nonl=True)
|
||||
tree = self.env.get_doctree(indexfile)
|
||||
@ -326,7 +305,7 @@ class LaTeXBuilder(Builder):
|
||||
for pendingnode in largetree.traverse(addnodes.pending_xref):
|
||||
docname = pendingnode['refdocname']
|
||||
sectname = pendingnode['refsectname']
|
||||
newnodes = [nodes.emphasis(sectname, sectname)] # type: List[nodes.Node]
|
||||
newnodes = [nodes.emphasis(sectname, sectname)] # type: List[Node]
|
||||
for subdir, title in self.titles:
|
||||
if docname.startswith(subdir):
|
||||
newnodes.append(nodes.Text(_(' (in '), _(' (in ')))
|
||||
@ -338,19 +317,11 @@ class LaTeXBuilder(Builder):
|
||||
pendingnode.replace_self(newnodes)
|
||||
return largetree
|
||||
|
||||
def apply_transforms(self, doctree):
|
||||
# type: (nodes.document) -> None
|
||||
transformer = SphinxTransformer(doctree)
|
||||
transformer.set_environment(self.env)
|
||||
transformer.add_transforms([BibliographyTransform,
|
||||
ShowUrlsTransform,
|
||||
LaTeXFootnoteTransform,
|
||||
LiteralBlockTransform,
|
||||
DocumentTargetTransform])
|
||||
transformer.apply_transforms()
|
||||
def apply_transforms(self, doctree: nodes.document) -> None:
|
||||
warnings.warn('LaTeXBuilder.apply_transforms() is deprecated.',
|
||||
RemovedInSphinx40Warning)
|
||||
|
||||
def finish(self):
|
||||
# type: () -> None
|
||||
def finish(self) -> None:
|
||||
self.copy_image_files()
|
||||
self.write_message_catalog()
|
||||
self.copy_support_files()
|
||||
@ -359,8 +330,7 @@ class LaTeXBuilder(Builder):
|
||||
self.copy_latex_additional_files()
|
||||
|
||||
@progress_message(__('copying TeX support files'))
|
||||
def copy_support_files(self):
|
||||
# type: () -> None
|
||||
def copy_support_files(self) -> None:
|
||||
"""copy TeX support files from texinputs."""
|
||||
# configure usage of xindy (impacts Makefile and latexmkrc)
|
||||
# FIXME: convert this rather to a confval with suitable default
|
||||
@ -392,22 +362,13 @@ class LaTeXBuilder(Builder):
|
||||
copy_asset_file(path.join(staticdirname, 'Makefile_t'),
|
||||
self.outdir, context=context)
|
||||
|
||||
# the logo is handled differently
|
||||
if self.config.latex_logo:
|
||||
if not path.isfile(path.join(self.confdir, self.config.latex_logo)):
|
||||
raise SphinxError(__('logo file %r does not exist') % self.config.latex_logo)
|
||||
else:
|
||||
copy_asset_file(path.join(self.confdir, self.config.latex_logo), self.outdir)
|
||||
|
||||
@progress_message(__('copying additional files'))
|
||||
def copy_latex_additional_files(self):
|
||||
# type: () -> None
|
||||
def copy_latex_additional_files(self) -> None:
|
||||
for filename in self.config.latex_additional_files:
|
||||
logger.info(' ' + filename, nonl=True)
|
||||
copy_asset_file(path.join(self.confdir, filename), self.outdir)
|
||||
|
||||
def copy_image_files(self):
|
||||
# type: () -> None
|
||||
def copy_image_files(self) -> None:
|
||||
if self.images:
|
||||
stringify_func = ImageAdapter(self.app.env).get_original_image_uri
|
||||
for src in status_iterator(self.images, __('copying images... '), "brown",
|
||||
@ -420,9 +381,13 @@ class LaTeXBuilder(Builder):
|
||||
except Exception as err:
|
||||
logger.warning(__('cannot copy image file %r: %s'),
|
||||
path.join(self.srcdir, src), err)
|
||||
if self.config.latex_logo:
|
||||
if not path.isfile(path.join(self.confdir, self.config.latex_logo)):
|
||||
raise SphinxError(__('logo file %r does not exist') % self.config.latex_logo)
|
||||
else:
|
||||
copy_asset_file(path.join(self.confdir, self.config.latex_logo), self.outdir)
|
||||
|
||||
def write_message_catalog(self):
|
||||
# type: () -> None
|
||||
def write_message_catalog(self) -> None:
|
||||
formats = self.config.numfig_format
|
||||
context = {
|
||||
'addtocaptions': r'\@iden',
|
||||
@ -438,8 +403,45 @@ class LaTeXBuilder(Builder):
|
||||
copy_asset_file(filename, self.outdir, context=context, renderer=LaTeXRenderer())
|
||||
|
||||
|
||||
def validate_config_values(app, config):
|
||||
# type: (Sphinx, Config) -> None
|
||||
def patch_settings(settings: Any) -> Any:
|
||||
"""Make settings object to show deprecation messages."""
|
||||
|
||||
class Values(type(settings)): # type: ignore
|
||||
@property
|
||||
def author(self):
|
||||
warnings.warn('settings.author is deprecated',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
return self._author
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
warnings.warn('settings.title is deprecated',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
return self._title
|
||||
|
||||
@property
|
||||
def contentsname(self):
|
||||
warnings.warn('settings.contentsname is deprecated',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
return self._contentsname
|
||||
|
||||
@property
|
||||
def docname(self):
|
||||
warnings.warn('settings.docname is deprecated',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
return self._docname
|
||||
|
||||
@property
|
||||
def docclass(self):
|
||||
warnings.warn('settings.docclass is deprecated',
|
||||
RemovedInSphinx40Warning, stacklevel=2)
|
||||
return self._docclass
|
||||
|
||||
# dynamic subclassing
|
||||
settings.__class__ = Values
|
||||
|
||||
|
||||
def validate_config_values(app: Sphinx, config: Config) -> None:
|
||||
for key in list(config.latex_elements):
|
||||
if key not in DEFAULT_SETTINGS:
|
||||
msg = __("Unknown configure key: latex_elements[%r]. ignored.")
|
||||
@ -447,56 +449,60 @@ def validate_config_values(app, config):
|
||||
config.latex_elements.pop(key)
|
||||
|
||||
|
||||
def default_latex_engine(config):
|
||||
# type: (Config) -> str
|
||||
def default_latex_engine(config: Config) -> str:
|
||||
""" Better default latex_engine settings for specific languages. """
|
||||
if config.language == 'ja':
|
||||
return 'platex'
|
||||
elif (config.language or '').startswith('zh'):
|
||||
return 'xelatex'
|
||||
elif config.language == 'el':
|
||||
return 'xelatex'
|
||||
else:
|
||||
return 'pdflatex'
|
||||
|
||||
|
||||
def default_latex_docclass(config):
|
||||
# type: (Config) -> Dict[str, str]
|
||||
def default_latex_docclass(config: Config) -> Dict[str, str]:
|
||||
""" Better default latex_docclass settings for specific languages. """
|
||||
if config.language == 'ja':
|
||||
return {'manual': 'jsbook',
|
||||
'howto': 'jreport'}
|
||||
if config.latex_engine == 'uplatex':
|
||||
return {'manual': 'ujbook',
|
||||
'howto': 'ujreport'}
|
||||
else:
|
||||
return {'manual': 'jsbook',
|
||||
'howto': 'jreport'}
|
||||
else:
|
||||
return {}
|
||||
|
||||
|
||||
def default_latex_use_xindy(config):
|
||||
# type: (Config) -> bool
|
||||
def default_latex_use_xindy(config: Config) -> bool:
|
||||
""" Better default latex_use_xindy settings for specific engines. """
|
||||
return config.latex_engine in {'xelatex', 'lualatex'}
|
||||
|
||||
|
||||
def default_latex_documents(config):
|
||||
# type: (Config) -> List[Tuple[str, str, str, str, str]]
|
||||
def default_latex_documents(config: Config) -> List[Tuple[str, str, str, str, str]]:
|
||||
""" Better default latex_documents settings. """
|
||||
project = texescape.escape(config.project, config.latex_engine)
|
||||
author = texescape.escape(config.author, config.latex_engine)
|
||||
return [(config.master_doc,
|
||||
make_filename_from_project(config.project) + '.tex',
|
||||
texescape.escape_abbr(texescape.escape(config.project)),
|
||||
texescape.escape_abbr(texescape.escape(config.author)),
|
||||
texescape.escape_abbr(project),
|
||||
texescape.escape_abbr(author),
|
||||
'manual')]
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.setup_extension('sphinx.builders.latex.transforms')
|
||||
|
||||
app.add_builder(LaTeXBuilder)
|
||||
app.add_post_transform(CitationReferenceTransform)
|
||||
app.add_post_transform(MathReferenceTransform)
|
||||
app.connect('config-inited', validate_config_values)
|
||||
app.add_transform(FootnoteDocnameUpdater)
|
||||
|
||||
app.add_config_value('latex_engine', default_latex_engine, None,
|
||||
ENUM('pdflatex', 'xelatex', 'lualatex', 'platex'))
|
||||
ENUM('pdflatex', 'xelatex', 'lualatex', 'platex', 'uplatex'))
|
||||
app.add_config_value('latex_documents', default_latex_documents, None)
|
||||
app.add_config_value('latex_logo', None, None, [str])
|
||||
app.add_config_value('latex_appendices', [], None)
|
||||
app.add_config_value('latex_use_latex_multicolumn', False, None)
|
||||
app.add_config_value('latex_use_xindy', default_latex_use_xindy, None)
|
||||
app.add_config_value('latex_use_xindy', default_latex_use_xindy, None, [bool])
|
||||
app.add_config_value('latex_toplevel_sectioning', None, None,
|
||||
ENUM(None, 'part', 'chapter', 'section'))
|
||||
app.add_config_value('latex_domain_indices', True, None, [list])
|
||||
|
192
sphinx/builders/latex/constants.py
Normal file
192
sphinx/builders/latex/constants.py
Normal file
@ -0,0 +1,192 @@
|
||||
"""
|
||||
sphinx.builders.latex.constants
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
consntants for LaTeX builder.
|
||||
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from typing import Any, Dict
|
||||
|
||||
|
||||
PDFLATEX_DEFAULT_FONTPKG = r'''
|
||||
\usepackage{times}
|
||||
\expandafter\ifx\csname T@LGR\endcsname\relax
|
||||
\else
|
||||
% LGR was declared as font encoding
|
||||
\substitutefont{LGR}{\rmdefault}{cmr}
|
||||
\substitutefont{LGR}{\sfdefault}{cmss}
|
||||
\substitutefont{LGR}{\ttdefault}{cmtt}
|
||||
\fi
|
||||
\expandafter\ifx\csname T@X2\endcsname\relax
|
||||
\expandafter\ifx\csname T@T2A\endcsname\relax
|
||||
\else
|
||||
% T2A was declared as font encoding
|
||||
\substitutefont{T2A}{\rmdefault}{cmr}
|
||||
\substitutefont{T2A}{\sfdefault}{cmss}
|
||||
\substitutefont{T2A}{\ttdefault}{cmtt}
|
||||
\fi
|
||||
\else
|
||||
% X2 was declared as font encoding
|
||||
\substitutefont{X2}{\rmdefault}{cmr}
|
||||
\substitutefont{X2}{\sfdefault}{cmss}
|
||||
\substitutefont{X2}{\ttdefault}{cmtt}
|
||||
\fi
|
||||
'''
|
||||
|
||||
XELATEX_DEFAULT_FONTPKG = r'''
|
||||
\setmainfont{FreeSerif}[
|
||||
Extension = .otf,
|
||||
UprightFont = *,
|
||||
ItalicFont = *Italic,
|
||||
BoldFont = *Bold,
|
||||
BoldItalicFont = *BoldItalic
|
||||
]
|
||||
\setsansfont{FreeSans}[
|
||||
Extension = .otf,
|
||||
UprightFont = *,
|
||||
ItalicFont = *Oblique,
|
||||
BoldFont = *Bold,
|
||||
BoldItalicFont = *BoldOblique,
|
||||
]
|
||||
\setmonofont{FreeMono}[
|
||||
Extension = .otf,
|
||||
UprightFont = *,
|
||||
ItalicFont = *Oblique,
|
||||
BoldFont = *Bold,
|
||||
BoldItalicFont = *BoldOblique,
|
||||
]
|
||||
'''
|
||||
|
||||
XELATEX_GREEK_DEFAULT_FONTPKG = (XELATEX_DEFAULT_FONTPKG +
|
||||
'\n\\newfontfamily\\greekfont{FreeSerif}' +
|
||||
'\n\\newfontfamily\\greekfontsf{FreeSans}' +
|
||||
'\n\\newfontfamily\\greekfonttt{FreeMono}')
|
||||
|
||||
LUALATEX_DEFAULT_FONTPKG = XELATEX_DEFAULT_FONTPKG
|
||||
|
||||
DEFAULT_SETTINGS = {
|
||||
'latex_engine': 'pdflatex',
|
||||
'papersize': 'letterpaper',
|
||||
'pointsize': '10pt',
|
||||
'pxunit': '.75bp',
|
||||
'classoptions': '',
|
||||
'extraclassoptions': '',
|
||||
'maxlistdepth': '',
|
||||
'sphinxpkgoptions': '',
|
||||
'sphinxsetup': '',
|
||||
'fvset': '\\fvset{fontsize=\\small}',
|
||||
'passoptionstopackages': '',
|
||||
'geometry': '\\usepackage{geometry}',
|
||||
'inputenc': '',
|
||||
'utf8extra': '',
|
||||
'cmappkg': '\\usepackage{cmap}',
|
||||
'fontenc': '\\usepackage[T1]{fontenc}',
|
||||
'amsmath': '\\usepackage{amsmath,amssymb,amstext}',
|
||||
'multilingual': '',
|
||||
'babel': '\\usepackage{babel}',
|
||||
'polyglossia': '',
|
||||
'fontpkg': PDFLATEX_DEFAULT_FONTPKG,
|
||||
'substitutefont': '',
|
||||
'textcyrillic': '',
|
||||
'textgreek': '\\usepackage{textalpha}',
|
||||
'fncychap': '\\usepackage[Bjarne]{fncychap}',
|
||||
'hyperref': ('% Include hyperref last.\n'
|
||||
'\\usepackage{hyperref}\n'
|
||||
'% Fix anchor placement for figures with captions.\n'
|
||||
'\\usepackage{hypcap}% it must be loaded after hyperref.\n'
|
||||
'% Set up styles of URL: it should be placed after hyperref.\n'
|
||||
'\\urlstyle{same}'),
|
||||
'contentsname': '',
|
||||
'extrapackages': '',
|
||||
'preamble': '',
|
||||
'title': '',
|
||||
'release': '',
|
||||
'author': '',
|
||||
'releasename': '',
|
||||
'makeindex': '\\makeindex',
|
||||
'shorthandoff': '',
|
||||
'maketitle': '\\sphinxmaketitle',
|
||||
'tableofcontents': '\\sphinxtableofcontents',
|
||||
'atendofbody': '',
|
||||
'printindex': '\\printindex',
|
||||
'transition': '\n\n\\bigskip\\hrule\\bigskip\n\n',
|
||||
'figure_align': 'htbp',
|
||||
'tocdepth': '',
|
||||
'secnumdepth': '',
|
||||
} # type: Dict[str, Any]
|
||||
|
||||
ADDITIONAL_SETTINGS = {
|
||||
'pdflatex': {
|
||||
'inputenc': '\\usepackage[utf8]{inputenc}',
|
||||
'utf8extra': ('\\ifdefined\\DeclareUnicodeCharacter\n'
|
||||
'% support both utf8 and utf8x syntaxes\n'
|
||||
' \\ifdefined\\DeclareUnicodeCharacterAsOptional\n'
|
||||
' \\def\\sphinxDUC#1{\\DeclareUnicodeCharacter{"#1}}\n'
|
||||
' \\else\n'
|
||||
' \\let\\sphinxDUC\\DeclareUnicodeCharacter\n'
|
||||
' \\fi\n'
|
||||
' \\sphinxDUC{00A0}{\\nobreakspace}\n'
|
||||
' \\sphinxDUC{2500}{\\sphinxunichar{2500}}\n'
|
||||
' \\sphinxDUC{2502}{\\sphinxunichar{2502}}\n'
|
||||
' \\sphinxDUC{2514}{\\sphinxunichar{2514}}\n'
|
||||
' \\sphinxDUC{251C}{\\sphinxunichar{251C}}\n'
|
||||
' \\sphinxDUC{2572}{\\textbackslash}\n'
|
||||
'\\fi'),
|
||||
},
|
||||
'xelatex': {
|
||||
'latex_engine': 'xelatex',
|
||||
'polyglossia': '\\usepackage{polyglossia}',
|
||||
'babel': '',
|
||||
'fontenc': ('\\usepackage{fontspec}\n'
|
||||
'\\defaultfontfeatures[\\rmfamily,\\sffamily,\\ttfamily]{}'),
|
||||
'fontpkg': XELATEX_DEFAULT_FONTPKG,
|
||||
'textgreek': '',
|
||||
'utf8extra': ('\\catcode`^^^^00a0\\active\\protected\\def^^^^00a0'
|
||||
'{\\leavevmode\\nobreak\\ }'),
|
||||
},
|
||||
'lualatex': {
|
||||
'latex_engine': 'lualatex',
|
||||
'polyglossia': '\\usepackage{polyglossia}',
|
||||
'babel': '',
|
||||
'fontenc': ('\\usepackage{fontspec}\n'
|
||||
'\\defaultfontfeatures[\\rmfamily,\\sffamily,\\ttfamily]{}'),
|
||||
'fontpkg': LUALATEX_DEFAULT_FONTPKG,
|
||||
'textgreek': '',
|
||||
'utf8extra': ('\\catcode`^^^^00a0\\active\\protected\\def^^^^00a0'
|
||||
'{\\leavevmode\\nobreak\\ }'),
|
||||
},
|
||||
'platex': {
|
||||
'latex_engine': 'platex',
|
||||
'babel': '',
|
||||
'classoptions': ',dvipdfmx',
|
||||
'fontpkg': '\\usepackage{times}',
|
||||
'textgreek': '',
|
||||
'fncychap': '',
|
||||
'geometry': '\\usepackage[dvipdfm]{geometry}',
|
||||
},
|
||||
'uplatex': {
|
||||
'latex_engine': 'uplatex',
|
||||
'babel': '',
|
||||
'classoptions': ',dvipdfmx',
|
||||
'fontpkg': '\\usepackage{times}',
|
||||
'textgreek': '',
|
||||
'fncychap': '',
|
||||
'geometry': '\\usepackage[dvipdfm]{geometry}',
|
||||
},
|
||||
|
||||
# special settings for latex_engine + language_code
|
||||
('xelatex', 'fr'): {
|
||||
# use babel instead of polyglossia by default
|
||||
'polyglossia': '',
|
||||
'babel': '\\usepackage{babel}',
|
||||
},
|
||||
('xelatex', 'zh'): {
|
||||
'fontenc': '\\usepackage{xeCJK}',
|
||||
},
|
||||
('xelatex', 'el'): {
|
||||
'fontpkg': XELATEX_GREEK_DEFAULT_FONTPKG,
|
||||
},
|
||||
} # type: Dict[Any, Dict[str, Any]]
|
@ -4,7 +4,7 @@
|
||||
|
||||
Additional nodes for LaTeX writer.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -4,25 +4,26 @@
|
||||
|
||||
Transforms for LaTeX builder.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from typing import Any, Dict, List, Set, Tuple
|
||||
from typing import cast
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.nodes import Element, Node
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders.latex.nodes import (
|
||||
captioned_literal_block, footnotemark, footnotetext, math_reference, thebibliography
|
||||
)
|
||||
from sphinx.domains.citation import CitationDomain
|
||||
from sphinx.transforms import SphinxTransform
|
||||
from sphinx.transforms.post_transforms import SphinxPostTransform
|
||||
from sphinx.util.nodes import NodeMatcher
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, List, Set, Tuple, Union # NOQA
|
||||
|
||||
URI_SCHEMES = ('mailto:', 'http:', 'https:', 'ftp:')
|
||||
|
||||
|
||||
@ -31,14 +32,13 @@ class FootnoteDocnameUpdater(SphinxTransform):
|
||||
default_priority = 700
|
||||
TARGET_NODES = (nodes.footnote, nodes.footnote_reference)
|
||||
|
||||
def apply(self, **kwargs):
|
||||
# type: (Any) -> None
|
||||
def apply(self, **kwargs: Any) -> None:
|
||||
matcher = NodeMatcher(*self.TARGET_NODES)
|
||||
for node in self.document.traverse(matcher): # type: nodes.Element
|
||||
node['docname'] = self.env.docname
|
||||
|
||||
|
||||
class ShowUrlsTransform(SphinxTransform):
|
||||
class ShowUrlsTransform(SphinxPostTransform):
|
||||
"""Expand references to inline text or footnotes.
|
||||
|
||||
For more information, see :confval:`latex_show_urls`.
|
||||
@ -46,12 +46,12 @@ class ShowUrlsTransform(SphinxTransform):
|
||||
.. note:: This transform is used for integrated doctree
|
||||
"""
|
||||
default_priority = 400
|
||||
builders = ('latex',)
|
||||
|
||||
# references are expanded to footnotes (or not)
|
||||
expanded = False
|
||||
|
||||
def apply(self, **kwargs):
|
||||
# type: (Any) -> None
|
||||
def run(self, **kwargs: Any) -> None:
|
||||
try:
|
||||
# replace id_prefix temporarily
|
||||
settings = self.document.settings # type: Any
|
||||
@ -65,8 +65,7 @@ class ShowUrlsTransform(SphinxTransform):
|
||||
# restore id_prefix
|
||||
settings.id_prefix = id_prefix
|
||||
|
||||
def expand_show_urls(self):
|
||||
# type: () -> None
|
||||
def expand_show_urls(self) -> None:
|
||||
show_urls = self.config.latex_show_urls
|
||||
if show_urls is False or show_urls == 'no':
|
||||
return
|
||||
@ -89,8 +88,7 @@ class ShowUrlsTransform(SphinxTransform):
|
||||
textnode = nodes.Text(" (%s)" % uri)
|
||||
node.parent.insert(index + 1, textnode)
|
||||
|
||||
def get_docname_for_node(self, node):
|
||||
# type: (nodes.Node) -> str
|
||||
def get_docname_for_node(self, node: Node) -> str:
|
||||
while node:
|
||||
if isinstance(node, nodes.document):
|
||||
return self.env.path2doc(node['source'])
|
||||
@ -101,8 +99,7 @@ class ShowUrlsTransform(SphinxTransform):
|
||||
|
||||
return None # never reached here. only for type hinting
|
||||
|
||||
def create_footnote(self, uri, docname):
|
||||
# type: (str, str) -> Tuple[nodes.footnote, nodes.footnote_reference]
|
||||
def create_footnote(self, uri: str, docname: str) -> Tuple[nodes.footnote, nodes.footnote_reference]: # NOQA
|
||||
reference = nodes.reference('', nodes.Text(uri), refuri=uri, nolinkurl=True)
|
||||
footnote = nodes.footnote(uri, auto=1, docname=docname)
|
||||
footnote['names'].append('#')
|
||||
@ -118,8 +115,7 @@ class ShowUrlsTransform(SphinxTransform):
|
||||
|
||||
return footnote, footnote_ref
|
||||
|
||||
def renumber_footnotes(self):
|
||||
# type: () -> None
|
||||
def renumber_footnotes(self) -> None:
|
||||
collector = FootnoteCollector(self.document)
|
||||
self.document.walkabout(collector)
|
||||
|
||||
@ -149,35 +145,30 @@ class ShowUrlsTransform(SphinxTransform):
|
||||
class FootnoteCollector(nodes.NodeVisitor):
|
||||
"""Collect footnotes and footnote references on the document"""
|
||||
|
||||
def __init__(self, document):
|
||||
# type: (nodes.document) -> None
|
||||
def __init__(self, document: nodes.document) -> None:
|
||||
self.auto_footnotes = [] # type: List[nodes.footnote]
|
||||
self.used_footnote_numbers = set() # type: Set[str]
|
||||
self.footnote_refs = [] # type: List[nodes.footnote_reference]
|
||||
super().__init__(document)
|
||||
|
||||
def unknown_visit(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
def unknown_visit(self, node: Node) -> None:
|
||||
pass
|
||||
|
||||
def unknown_departure(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
def unknown_departure(self, node: Node) -> None:
|
||||
pass
|
||||
|
||||
def visit_footnote(self, node):
|
||||
# type: (nodes.footnote) -> None
|
||||
def visit_footnote(self, node: nodes.footnote) -> None:
|
||||
if node.get('auto'):
|
||||
self.auto_footnotes.append(node)
|
||||
else:
|
||||
for name in node['names']:
|
||||
self.used_footnote_numbers.add(name)
|
||||
|
||||
def visit_footnote_reference(self, node):
|
||||
# type: (nodes.footnote_reference) -> None
|
||||
def visit_footnote_reference(self, node: nodes.footnote_reference) -> None:
|
||||
self.footnote_refs.append(node)
|
||||
|
||||
|
||||
class LaTeXFootnoteTransform(SphinxTransform):
|
||||
class LaTeXFootnoteTransform(SphinxPostTransform):
|
||||
"""Convert footnote definitions and references to appropriate form to LaTeX.
|
||||
|
||||
* Replace footnotes on restricted zone (e.g. headings) by footnotemark node.
|
||||
@ -345,9 +336,9 @@ class LaTeXFootnoteTransform(SphinxTransform):
|
||||
"""
|
||||
|
||||
default_priority = 600
|
||||
builders = ('latex',)
|
||||
|
||||
def apply(self, **kwargs):
|
||||
# type: (Any) -> None
|
||||
def run(self, **kwargs: Any) -> None:
|
||||
footnotes = list(self.document.traverse(nodes.footnote))
|
||||
for node in footnotes:
|
||||
node.parent.remove(node)
|
||||
@ -357,8 +348,7 @@ class LaTeXFootnoteTransform(SphinxTransform):
|
||||
|
||||
|
||||
class LaTeXFootnoteVisitor(nodes.NodeVisitor):
|
||||
def __init__(self, document, footnotes):
|
||||
# type: (nodes.document, List[nodes.footnote]) -> None
|
||||
def __init__(self, document: nodes.document, footnotes: List[nodes.footnote]) -> None:
|
||||
self.appeared = set() # type: Set[Tuple[str, str]]
|
||||
self.footnotes = footnotes # type: List[nodes.footnote]
|
||||
self.pendings = [] # type: List[nodes.footnote]
|
||||
@ -366,21 +356,17 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
|
||||
self.restricted = None # type: nodes.Element
|
||||
super().__init__(document)
|
||||
|
||||
def unknown_visit(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
def unknown_visit(self, node: Node) -> None:
|
||||
pass
|
||||
|
||||
def unknown_departure(self, node):
|
||||
# type: (nodes.Node) -> None
|
||||
def unknown_departure(self, node: Node) -> None:
|
||||
pass
|
||||
|
||||
def restrict(self, node):
|
||||
# type: (nodes.Element) -> None
|
||||
def restrict(self, node: Element) -> None:
|
||||
if self.restricted is None:
|
||||
self.restricted = node
|
||||
|
||||
def unrestrict(self, node):
|
||||
# type: (nodes.Element) -> None
|
||||
def unrestrict(self, node: Element) -> None:
|
||||
if self.restricted == node:
|
||||
self.restricted = None
|
||||
pos = node.parent.index(node)
|
||||
@ -389,37 +375,29 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
|
||||
node.parent.insert(pos + i + 1, fntext)
|
||||
self.pendings = []
|
||||
|
||||
def visit_figure(self, node):
|
||||
# type: (nodes.figure) -> None
|
||||
def visit_figure(self, node: nodes.figure) -> None:
|
||||
self.restrict(node)
|
||||
|
||||
def depart_figure(self, node):
|
||||
# type: (nodes.figure) -> None
|
||||
def depart_figure(self, node: nodes.figure) -> None:
|
||||
self.unrestrict(node)
|
||||
|
||||
def visit_term(self, node):
|
||||
# type: (nodes.term) -> None
|
||||
def visit_term(self, node: nodes.term) -> None:
|
||||
self.restrict(node)
|
||||
|
||||
def depart_term(self, node):
|
||||
# type: (nodes.term) -> None
|
||||
def depart_term(self, node: nodes.term) -> None:
|
||||
self.unrestrict(node)
|
||||
|
||||
def visit_caption(self, node):
|
||||
# type: (nodes.caption) -> None
|
||||
def visit_caption(self, node: nodes.caption) -> None:
|
||||
self.restrict(node)
|
||||
|
||||
def depart_caption(self, node):
|
||||
# type: (nodes.caption) -> None
|
||||
def depart_caption(self, node: nodes.caption) -> None:
|
||||
self.unrestrict(node)
|
||||
|
||||
def visit_title(self, node):
|
||||
# type: (nodes.title) -> None
|
||||
def visit_title(self, node: nodes.title) -> None:
|
||||
if isinstance(node.parent, (nodes.section, nodes.table)):
|
||||
self.restrict(node)
|
||||
|
||||
def depart_title(self, node):
|
||||
# type: (nodes.title) -> None
|
||||
def depart_title(self, node: nodes.title) -> None:
|
||||
if isinstance(node.parent, nodes.section):
|
||||
self.unrestrict(node)
|
||||
elif isinstance(node.parent, nodes.table):
|
||||
@ -427,18 +405,15 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
|
||||
self.pendings = []
|
||||
self.unrestrict(node)
|
||||
|
||||
def visit_thead(self, node):
|
||||
# type: (nodes.thead) -> None
|
||||
def visit_thead(self, node: nodes.thead) -> None:
|
||||
self.restrict(node)
|
||||
|
||||
def depart_thead(self, node):
|
||||
# type: (nodes.thead) -> None
|
||||
def depart_thead(self, node: nodes.thead) -> None:
|
||||
self.table_footnotes += self.pendings
|
||||
self.pendings = []
|
||||
self.unrestrict(node)
|
||||
|
||||
def depart_table(self, node):
|
||||
# type: (nodes.table) -> None
|
||||
def depart_table(self, node: nodes.table) -> None:
|
||||
tbody = list(node.traverse(nodes.tbody))[0]
|
||||
for footnote in reversed(self.table_footnotes):
|
||||
fntext = footnotetext('', *footnote.children)
|
||||
@ -446,16 +421,13 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
|
||||
|
||||
self.table_footnotes = []
|
||||
|
||||
def visit_footnote(self, node):
|
||||
# type: (nodes.footnote) -> None
|
||||
def visit_footnote(self, node: nodes.footnote) -> None:
|
||||
self.restrict(node)
|
||||
|
||||
def depart_footnote(self, node):
|
||||
# type: (nodes.footnote) -> None
|
||||
def depart_footnote(self, node: nodes.footnote) -> None:
|
||||
self.unrestrict(node)
|
||||
|
||||
def visit_footnote_reference(self, node):
|
||||
# type: (nodes.footnote_reference) -> None
|
||||
def visit_footnote_reference(self, node: nodes.footnote_reference) -> None:
|
||||
number = node.astext().strip()
|
||||
docname = node['docname']
|
||||
if self.restricted:
|
||||
@ -476,8 +448,7 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
|
||||
self.appeared.add((docname, number))
|
||||
raise nodes.SkipNode
|
||||
|
||||
def get_footnote_by_reference(self, node):
|
||||
# type: (nodes.footnote_reference) -> nodes.footnote
|
||||
def get_footnote_by_reference(self, node: nodes.footnote_reference) -> nodes.footnote:
|
||||
docname = node['docname']
|
||||
for footnote in self.footnotes:
|
||||
if docname == footnote['docname'] and footnote['ids'][0] == node['refid']:
|
||||
@ -486,7 +457,7 @@ class LaTeXFootnoteVisitor(nodes.NodeVisitor):
|
||||
return None
|
||||
|
||||
|
||||
class BibliographyTransform(SphinxTransform):
|
||||
class BibliographyTransform(SphinxPostTransform):
|
||||
"""Gather bibliography entries to tail of document.
|
||||
|
||||
Before::
|
||||
@ -517,9 +488,9 @@ class BibliographyTransform(SphinxTransform):
|
||||
...
|
||||
"""
|
||||
default_priority = 750
|
||||
builders = ('latex',)
|
||||
|
||||
def apply(self, **kwargs):
|
||||
# type: (Any) -> None
|
||||
def run(self, **kwargs: Any) -> None:
|
||||
citations = thebibliography()
|
||||
for node in self.document.traverse(nodes.citation):
|
||||
node.parent.remove(node)
|
||||
@ -529,42 +500,36 @@ class BibliographyTransform(SphinxTransform):
|
||||
self.document += citations
|
||||
|
||||
|
||||
class CitationReferenceTransform(SphinxTransform):
|
||||
class CitationReferenceTransform(SphinxPostTransform):
|
||||
"""Replace pending_xref nodes for citation by citation_reference.
|
||||
|
||||
To handle citation reference easily on LaTeX writer, this converts
|
||||
pending_xref nodes to citation_reference.
|
||||
"""
|
||||
default_priority = 5 # before ReferencesResolver
|
||||
builders = ('latex',)
|
||||
|
||||
def apply(self, **kwargs):
|
||||
# type: (Any) -> None
|
||||
if self.app.builder.name != 'latex':
|
||||
return
|
||||
|
||||
matcher = NodeMatcher(addnodes.pending_xref, refdomain='std', reftype='citation')
|
||||
citations = self.env.get_domain('std').data['citations']
|
||||
def run(self, **kwargs: Any) -> None:
|
||||
domain = cast(CitationDomain, self.env.get_domain('citation'))
|
||||
matcher = NodeMatcher(addnodes.pending_xref, refdomain='citation', reftype='ref')
|
||||
for node in self.document.traverse(matcher): # type: addnodes.pending_xref
|
||||
docname, labelid, _ = citations.get(node['reftarget'], ('', '', 0))
|
||||
docname, labelid, _ = domain.citations.get(node['reftarget'], ('', '', 0))
|
||||
if docname:
|
||||
citation_ref = nodes.citation_reference('', '', *node.children,
|
||||
docname=docname, refname=labelid)
|
||||
node.replace_self(citation_ref)
|
||||
|
||||
|
||||
class MathReferenceTransform(SphinxTransform):
|
||||
class MathReferenceTransform(SphinxPostTransform):
|
||||
"""Replace pending_xref nodes for math by math_reference.
|
||||
|
||||
To handle math reference easily on LaTeX writer, this converts pending_xref
|
||||
nodes to math_reference.
|
||||
"""
|
||||
default_priority = 5 # before ReferencesResolver
|
||||
builders = ('latex',)
|
||||
|
||||
def apply(self, **kwargs):
|
||||
# type: (Any) -> None
|
||||
if self.app.builder.name != 'latex':
|
||||
return
|
||||
|
||||
def run(self, **kwargs: Any) -> None:
|
||||
equations = self.env.get_domain('math').data['objects']
|
||||
for node in self.document.traverse(addnodes.pending_xref):
|
||||
if node['refdomain'] == 'math' and node['reftype'] in ('eq', 'numref'):
|
||||
@ -574,31 +539,80 @@ class MathReferenceTransform(SphinxTransform):
|
||||
node.replace_self(refnode)
|
||||
|
||||
|
||||
class LiteralBlockTransform(SphinxTransform):
|
||||
class LiteralBlockTransform(SphinxPostTransform):
|
||||
"""Replace container nodes for literal_block by captioned_literal_block."""
|
||||
default_priority = 400
|
||||
builders = ('latex',)
|
||||
|
||||
def apply(self, **kwargs):
|
||||
# type: (Any) -> None
|
||||
if self.app.builder.name != 'latex':
|
||||
return
|
||||
|
||||
def run(self, **kwargs: Any) -> None:
|
||||
matcher = NodeMatcher(nodes.container, literal_block=True)
|
||||
for node in self.document.traverse(matcher): # type: nodes.container
|
||||
newnode = captioned_literal_block('', *node.children, **node.attributes)
|
||||
node.replace_self(newnode)
|
||||
|
||||
|
||||
class DocumentTargetTransform(SphinxTransform):
|
||||
class DocumentTargetTransform(SphinxPostTransform):
|
||||
"""Add :doc label to the first section of each document."""
|
||||
default_priority = 400
|
||||
builders = ('latex',)
|
||||
|
||||
def apply(self, **kwargs):
|
||||
# type: (Any) -> None
|
||||
if self.app.builder.name != 'latex':
|
||||
return
|
||||
|
||||
def run(self, **kwargs: Any) -> None:
|
||||
for node in self.document.traverse(addnodes.start_of_file):
|
||||
section = node.next_node(nodes.section)
|
||||
if section:
|
||||
section['ids'].append(':doc') # special label for :doc:
|
||||
|
||||
|
||||
class IndexInSectionTitleTransform(SphinxTransform):
|
||||
"""Move index nodes in section title to outside of the title.
|
||||
|
||||
LaTeX index macro is not compatible with some handling of section titles
|
||||
such as uppercasing done on LaTeX side (cf. fncychap handling of ``\\chapter``).
|
||||
Moving the index node to after the title node fixes that.
|
||||
|
||||
Before::
|
||||
|
||||
<section>
|
||||
<title>
|
||||
blah blah <index entries=[...]/>blah
|
||||
<paragraph>
|
||||
blah blah blah
|
||||
...
|
||||
|
||||
After::
|
||||
|
||||
<section>
|
||||
<title>
|
||||
blah blah blah
|
||||
<index entries=[...]/>
|
||||
<paragraph>
|
||||
blah blah blah
|
||||
...
|
||||
"""
|
||||
default_priority = 400
|
||||
|
||||
def apply(self):
|
||||
for node in self.document.traverse(nodes.title):
|
||||
if isinstance(node.parent, nodes.section):
|
||||
for i, index in enumerate(node.traverse(addnodes.index)):
|
||||
# move the index node next to the section title
|
||||
node.remove(index)
|
||||
node.parent.insert(i + 1, index)
|
||||
|
||||
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.add_transform(FootnoteDocnameUpdater)
|
||||
app.add_post_transform(BibliographyTransform)
|
||||
app.add_post_transform(CitationReferenceTransform)
|
||||
app.add_post_transform(DocumentTargetTransform)
|
||||
app.add_post_transform(IndexInSectionTitleTransform)
|
||||
app.add_post_transform(LaTeXFootnoteTransform)
|
||||
app.add_post_transform(LiteralBlockTransform)
|
||||
app.add_post_transform(MathReferenceTransform)
|
||||
app.add_post_transform(ShowUrlsTransform)
|
||||
|
||||
return {
|
||||
'version': 'builtin',
|
||||
'parallel_read_safe': True,
|
||||
'parallel_write_safe': True,
|
||||
}
|
||||
|
@ -8,53 +8,39 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import warnings
|
||||
|
||||
from docutils.writers.latex2e import Babel
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||
|
||||
|
||||
class ExtBabel(Babel):
|
||||
cyrillic_languages = ('bulgarian', 'kazakh', 'mongolian', 'russian', 'ukrainian')
|
||||
|
||||
def __init__(self, language_code, use_polyglossia=False):
|
||||
# type: (str, bool) -> None
|
||||
def __init__(self, language_code: str, use_polyglossia: bool = False) -> None:
|
||||
self.language_code = language_code
|
||||
self.use_polyglossia = use_polyglossia
|
||||
self.supported = True
|
||||
super().__init__(language_code or '')
|
||||
|
||||
def get_shorthandoff(self):
|
||||
# type: () -> str
|
||||
warnings.warn('ExtBabel.get_shorthandoff() is deprecated.',
|
||||
RemovedInSphinx30Warning, stacklevel=2)
|
||||
from sphinx.writers.latex import SHORTHANDOFF
|
||||
return SHORTHANDOFF
|
||||
|
||||
def uses_cyrillic(self):
|
||||
# type: () -> bool
|
||||
def uses_cyrillic(self) -> bool:
|
||||
return self.language in self.cyrillic_languages
|
||||
|
||||
def is_supported_language(self):
|
||||
# type: () -> bool
|
||||
def is_supported_language(self) -> bool:
|
||||
return self.supported
|
||||
|
||||
def language_name(self, language_code):
|
||||
# type: (str) -> str
|
||||
def language_name(self, language_code: str) -> str:
|
||||
language = super().language_name(language_code)
|
||||
if language == 'ngerman' and self.use_polyglossia:
|
||||
# polyglossia calls new orthography (Neue Rechtschreibung) as
|
||||
# german (with new spelling option).
|
||||
return 'german'
|
||||
elif not language:
|
||||
elif language:
|
||||
return language
|
||||
elif language_code.startswith('zh'):
|
||||
return 'english' # fallback to english (behaves like supported)
|
||||
else:
|
||||
self.supported = False
|
||||
return 'english' # fallback to english
|
||||
else:
|
||||
return language
|
||||
|
||||
def get_mainlanguage_options(self):
|
||||
# type: () -> str
|
||||
def get_mainlanguage_options(self) -> str:
|
||||
"""Return options for polyglossia's ``\\setmainlanguage``."""
|
||||
if self.use_polyglossia is False:
|
||||
return None
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
The CheckExternalLinksBuilder class.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -14,26 +14,23 @@ import socket
|
||||
import threading
|
||||
from html.parser import HTMLParser
|
||||
from os import path
|
||||
from typing import Any, Dict, List, Set, Tuple
|
||||
from urllib.parse import unquote
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.nodes import Node
|
||||
from requests.exceptions import HTTPError
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import encode_uri, requests, logging
|
||||
from sphinx.util.console import ( # type: ignore
|
||||
purple, red, darkgreen, darkgray, darkred, turquoise
|
||||
purple, red, darkgreen, darkgray, turquoise
|
||||
)
|
||||
from sphinx.util.nodes import get_node_line
|
||||
from sphinx.util.requests import is_ssl_error
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, List, Set, Tuple, Union # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.util.requests.requests import Response # NOQA
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -41,23 +38,20 @@ logger = logging.getLogger(__name__)
|
||||
class AnchorCheckParser(HTMLParser):
|
||||
"""Specialized HTML parser that looks for a specific anchor."""
|
||||
|
||||
def __init__(self, search_anchor):
|
||||
# type: (str) -> None
|
||||
def __init__(self, search_anchor: str) -> None:
|
||||
super().__init__()
|
||||
|
||||
self.search_anchor = search_anchor
|
||||
self.found = False
|
||||
|
||||
def handle_starttag(self, tag, attrs):
|
||||
# type: (Any, Any) -> None
|
||||
def handle_starttag(self, tag: Any, attrs: Any) -> None:
|
||||
for key, value in attrs:
|
||||
if key in ('id', 'name') and value == self.search_anchor:
|
||||
self.found = True
|
||||
break
|
||||
|
||||
|
||||
def check_anchor(response, anchor):
|
||||
# type: (Response, str) -> bool
|
||||
def check_anchor(response: requests.requests.Response, anchor: str) -> bool:
|
||||
"""Reads HTML data from a response object `response` searching for `anchor`.
|
||||
Returns True if anchor was found, False otherwise.
|
||||
"""
|
||||
@ -65,6 +59,9 @@ def check_anchor(response, anchor):
|
||||
# Read file in chunks. If we find a matching anchor, we break
|
||||
# the loop early in hopes not to have to download the whole thing.
|
||||
for chunk in response.iter_content(chunk_size=4096, decode_unicode=True):
|
||||
if isinstance(chunk, bytes): # requests failed to decode
|
||||
chunk = chunk.decode() # manually try to decode it
|
||||
|
||||
parser.feed(chunk)
|
||||
if parser.found:
|
||||
break
|
||||
@ -80,11 +77,12 @@ class CheckExternalLinksBuilder(Builder):
|
||||
epilog = __('Look for any errors in the above output or in '
|
||||
'%(outdir)s/output.txt')
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
def init(self) -> None:
|
||||
self.to_ignore = [re.compile(x) for x in self.app.config.linkcheck_ignore]
|
||||
self.anchors_ignore = [re.compile(x)
|
||||
for x in self.app.config.linkcheck_anchors_ignore]
|
||||
self.auth = [(re.compile(pattern), auth_info) for pattern, auth_info
|
||||
in self.app.config.linkcheck_auth]
|
||||
self.good = set() # type: Set[str]
|
||||
self.broken = {} # type: Dict[str, str]
|
||||
self.redirected = {} # type: Dict[str, Tuple[str, int]]
|
||||
@ -103,19 +101,17 @@ class CheckExternalLinksBuilder(Builder):
|
||||
thread.start()
|
||||
self.workers.append(thread)
|
||||
|
||||
def check_thread(self):
|
||||
# type: () -> None
|
||||
def check_thread(self) -> None:
|
||||
kwargs = {
|
||||
'allow_redirects': True,
|
||||
'headers': {
|
||||
'Accept': 'text/html,application/xhtml+xml;q=0.9,*/*;q=0.8'
|
||||
'Accept': 'text/html,application/xhtml+xml;q=0.9,*/*;q=0.8',
|
||||
},
|
||||
}
|
||||
if self.app.config.linkcheck_timeout:
|
||||
kwargs['timeout'] = self.app.config.linkcheck_timeout
|
||||
|
||||
def check_uri():
|
||||
# type: () -> Tuple[str, str, int]
|
||||
def check_uri() -> Tuple[str, str, int]:
|
||||
# split off anchor
|
||||
if '#' in uri:
|
||||
req_url, anchor = uri.split('#', 1)
|
||||
@ -133,11 +129,18 @@ class CheckExternalLinksBuilder(Builder):
|
||||
except UnicodeError:
|
||||
req_url = encode_uri(req_url)
|
||||
|
||||
# Get auth info, if any
|
||||
for pattern, auth_info in self.auth:
|
||||
if pattern.match(uri):
|
||||
break
|
||||
else:
|
||||
auth_info = None
|
||||
|
||||
try:
|
||||
if anchor and self.app.config.linkcheck_anchors:
|
||||
# Read the whole document and see if #anchor exists
|
||||
response = requests.get(req_url, stream=True, config=self.app.config,
|
||||
**kwargs)
|
||||
auth=auth_info, **kwargs)
|
||||
found = check_anchor(response, unquote(anchor))
|
||||
|
||||
if not found:
|
||||
@ -146,18 +149,22 @@ class CheckExternalLinksBuilder(Builder):
|
||||
try:
|
||||
# try a HEAD request first, which should be easier on
|
||||
# the server and the network
|
||||
response = requests.head(req_url, config=self.app.config, **kwargs)
|
||||
response = requests.head(req_url, config=self.app.config,
|
||||
auth=auth_info, **kwargs)
|
||||
response.raise_for_status()
|
||||
except HTTPError:
|
||||
# retry with GET request if that fails, some servers
|
||||
# don't like HEAD requests.
|
||||
response = requests.get(req_url, stream=True, config=self.app.config,
|
||||
**kwargs)
|
||||
auth=auth_info, **kwargs)
|
||||
response.raise_for_status()
|
||||
except HTTPError as err:
|
||||
if err.response.status_code == 401:
|
||||
# We'll take "Unauthorized" as working.
|
||||
return 'working', ' - unauthorized', 0
|
||||
elif err.response.status_code == 503:
|
||||
# We'll take "Service Unavailable" as ignored.
|
||||
return 'ignored', str(err), 0
|
||||
else:
|
||||
return 'broken', str(err), 0
|
||||
except Exception as err:
|
||||
@ -178,8 +185,7 @@ class CheckExternalLinksBuilder(Builder):
|
||||
else:
|
||||
return 'redirected', new_url, 0
|
||||
|
||||
def check():
|
||||
# type: () -> Tuple[str, str, int]
|
||||
def check() -> Tuple[str, str, int]:
|
||||
# check for various conditions without bothering the network
|
||||
if len(uri) == 0 or uri.startswith(('#', 'mailto:', 'ftp:')):
|
||||
return 'unchecked', '', 0
|
||||
@ -217,8 +223,7 @@ class CheckExternalLinksBuilder(Builder):
|
||||
status, info, code = check()
|
||||
self.rqueue.put((uri, docname, lineno, status, info, code))
|
||||
|
||||
def process_result(self, result):
|
||||
# type: (Tuple[str, str, int, str, str, int]) -> None
|
||||
def process_result(self, result: Tuple[str, str, int, str, str, int]) -> None:
|
||||
uri, docname, lineno, status, info, code = result
|
||||
if status == 'unchecked':
|
||||
return
|
||||
@ -244,31 +249,30 @@ class CheckExternalLinksBuilder(Builder):
|
||||
else:
|
||||
logger.info(red('broken ') + uri + red(' - ' + info))
|
||||
elif status == 'redirected':
|
||||
text, color = {
|
||||
301: ('permanently', darkred),
|
||||
302: ('with Found', purple),
|
||||
303: ('with See Other', purple),
|
||||
307: ('temporarily', turquoise),
|
||||
0: ('with unknown code', purple),
|
||||
}[code]
|
||||
try:
|
||||
text, color = {
|
||||
301: ('permanently', purple),
|
||||
302: ('with Found', purple),
|
||||
303: ('with See Other', purple),
|
||||
307: ('temporarily', turquoise),
|
||||
308: ('permanently', purple),
|
||||
}[code]
|
||||
except KeyError:
|
||||
text, color = ('with unknown code', purple)
|
||||
self.write_entry('redirected ' + text, docname, lineno,
|
||||
uri + ' to ' + info)
|
||||
logger.info(color('redirect ') + uri + color(' - ' + text + ' to ' + info))
|
||||
|
||||
def get_target_uri(self, docname, typ=None):
|
||||
# type: (str, str) -> str
|
||||
def get_target_uri(self, docname: str, typ: str = None) -> str:
|
||||
return ''
|
||||
|
||||
def get_outdated_docs(self):
|
||||
# type: () -> Set[str]
|
||||
def get_outdated_docs(self) -> Set[str]:
|
||||
return self.env.found_docs
|
||||
|
||||
def prepare_writing(self, docnames):
|
||||
# type: (Set[str]) -> None
|
||||
def prepare_writing(self, docnames: Set[str]) -> None:
|
||||
return
|
||||
|
||||
def write_doc(self, docname, doctree):
|
||||
# type: (str, nodes.Node) -> None
|
||||
def write_doc(self, docname: str, doctree: Node) -> None:
|
||||
logger.info('')
|
||||
n = 0
|
||||
|
||||
@ -297,23 +301,21 @@ class CheckExternalLinksBuilder(Builder):
|
||||
if self.broken:
|
||||
self.app.statuscode = 1
|
||||
|
||||
def write_entry(self, what, docname, line, uri):
|
||||
# type: (str, str, int, str) -> None
|
||||
def write_entry(self, what: str, docname: str, line: int, uri: str) -> None:
|
||||
with open(path.join(self.outdir, 'output.txt'), 'a', encoding='utf-8') as output:
|
||||
output.write("%s:%s: [%s] %s\n" % (self.env.doc2path(docname, None),
|
||||
line, what, uri))
|
||||
|
||||
def finish(self):
|
||||
# type: () -> None
|
||||
def finish(self) -> None:
|
||||
for worker in self.workers:
|
||||
self.wqueue.put((None, None, None), False)
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.add_builder(CheckExternalLinksBuilder)
|
||||
|
||||
app.add_config_value('linkcheck_ignore', [], None)
|
||||
app.add_config_value('linkcheck_auth', [], None)
|
||||
app.add_config_value('linkcheck_retries', 1, None)
|
||||
app.add_config_value('linkcheck_timeout', None, None, [int])
|
||||
app.add_config_value('linkcheck_workers', 5, None)
|
||||
|
@ -4,18 +4,21 @@
|
||||
|
||||
Manual pages builder.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from os import path
|
||||
from typing import Any, Dict, List, Set, Tuple, Union
|
||||
|
||||
from docutils.frontend import OptionParser
|
||||
from docutils.io import FileOutput
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.environment import NoUri
|
||||
from sphinx.config import Config
|
||||
from sphinx.errors import NoUri
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import logging
|
||||
from sphinx.util import progress_message
|
||||
@ -24,12 +27,6 @@ from sphinx.util.nodes import inline_all_toctrees
|
||||
from sphinx.util.osutil import make_filename_from_project
|
||||
from sphinx.writers.manpage import ManualPageWriter, ManualPageTranslator
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, List, Set, Tuple, Union # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -45,25 +42,21 @@ class ManualPageBuilder(Builder):
|
||||
default_translator_class = ManualPageTranslator
|
||||
supported_image_types = [] # type: List[str]
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
def init(self) -> None:
|
||||
if not self.config.man_pages:
|
||||
logger.warning(__('no "man_pages" config value found; no manual pages '
|
||||
'will be written'))
|
||||
|
||||
def get_outdated_docs(self):
|
||||
# type: () -> Union[str, List[str]]
|
||||
def get_outdated_docs(self) -> Union[str, List[str]]:
|
||||
return 'all manpages' # for now
|
||||
|
||||
def get_target_uri(self, docname, typ=None):
|
||||
# type: (str, str) -> str
|
||||
def get_target_uri(self, docname: str, typ: str = None) -> str:
|
||||
if typ == 'token':
|
||||
return ''
|
||||
raise NoUri
|
||||
raise NoUri(docname, typ)
|
||||
|
||||
@progress_message(__('writing'))
|
||||
def write(self, *ignored):
|
||||
# type: (Any) -> None
|
||||
def write(self, *ignored: Any) -> None:
|
||||
docwriter = ManualPageWriter(self)
|
||||
docsettings = OptionParser(
|
||||
defaults=self.env.settings,
|
||||
@ -106,21 +99,18 @@ class ManualPageBuilder(Builder):
|
||||
|
||||
docwriter.write(largetree, destination)
|
||||
|
||||
def finish(self):
|
||||
# type: () -> None
|
||||
def finish(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def default_man_pages(config):
|
||||
# type: (Config) -> List[Tuple[str, str, str, List[str], int]]
|
||||
def default_man_pages(config: Config) -> List[Tuple[str, str, str, List[str], int]]:
|
||||
""" Better default man_pages settings. """
|
||||
filename = make_filename_from_project(config.project)
|
||||
return [(config.master_doc, filename, '%s %s' % (config.project, config.release),
|
||||
[config.author], 1)]
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.add_builder(ManualPageBuilder)
|
||||
|
||||
app.add_config_value('man_pages', default_man_pages, None)
|
||||
|
@ -4,22 +4,19 @@
|
||||
|
||||
Build input files for the Qt collection generator.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import warnings
|
||||
from typing import Any, Dict
|
||||
|
||||
from sphinxcontrib.qthelp import QtHelpBuilder, render_file
|
||||
|
||||
import sphinx
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
|
||||
deprecated_alias('sphinx.builders.qthelp',
|
||||
{
|
||||
@ -29,8 +26,7 @@ deprecated_alias('sphinx.builders.qthelp',
|
||||
RemovedInSphinx40Warning)
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
warnings.warn('sphinx.builders.qthelp has been moved to sphinxcontrib-qthelp.',
|
||||
RemovedInSphinx40Warning)
|
||||
|
||||
|
@ -4,15 +4,19 @@
|
||||
|
||||
Single HTML builders.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from os import path
|
||||
from typing import Any, Dict, List, Tuple, Union
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.nodes import Node
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders.html import StandaloneHTMLBuilder
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
|
||||
from sphinx.environment.adapters.toctree import TocTree
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import logging
|
||||
@ -20,11 +24,6 @@ from sphinx.util import progress_message
|
||||
from sphinx.util.console import darkgreen # type: ignore
|
||||
from sphinx.util.nodes import inline_all_toctrees
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, List, Tuple, Union # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -38,12 +37,10 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
|
||||
copysource = False
|
||||
|
||||
def get_outdated_docs(self): # type: ignore
|
||||
# type: () -> Union[str, List[str]]
|
||||
def get_outdated_docs(self) -> Union[str, List[str]]: # type: ignore
|
||||
return 'all documents'
|
||||
|
||||
def get_target_uri(self, docname, typ=None):
|
||||
# type: (str, str) -> str
|
||||
def get_target_uri(self, docname: str, typ: str = None) -> str:
|
||||
if docname in self.env.all_docs:
|
||||
# all references are on the same page...
|
||||
return self.config.master_doc + self.out_suffix + \
|
||||
@ -52,13 +49,11 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
# chances are this is a html_additional_page
|
||||
return docname + self.out_suffix
|
||||
|
||||
def get_relative_uri(self, from_, to, typ=None):
|
||||
# type: (str, str, str) -> str
|
||||
def get_relative_uri(self, from_: str, to: str, typ: str = None) -> str:
|
||||
# ignore source
|
||||
return self.get_target_uri(to, typ)
|
||||
|
||||
def fix_refuris(self, tree):
|
||||
# type: (nodes.Node) -> None
|
||||
def fix_refuris(self, tree: Node) -> None:
|
||||
# fix refuris with double anchor
|
||||
fname = self.config.master_doc + self.out_suffix
|
||||
for refnode in tree.traverse(nodes.reference):
|
||||
@ -72,17 +67,15 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
if hashindex >= 0:
|
||||
refnode['refuri'] = fname + refuri[hashindex:]
|
||||
|
||||
def _get_local_toctree(self, docname, collapse=True, **kwds):
|
||||
# type: (str, bool, Any) -> str
|
||||
if 'includehidden' not in kwds:
|
||||
kwds['includehidden'] = False
|
||||
toctree = TocTree(self.env).get_toctree_for(docname, self, collapse, **kwds)
|
||||
def _get_local_toctree(self, docname: str, collapse: bool = True, **kwargs: Any) -> str:
|
||||
if 'includehidden' not in kwargs:
|
||||
kwargs['includehidden'] = False
|
||||
toctree = TocTree(self.env).get_toctree_for(docname, self, collapse, **kwargs)
|
||||
if toctree is not None:
|
||||
self.fix_refuris(toctree)
|
||||
return self.render_partial(toctree)['fragment']
|
||||
|
||||
def assemble_doctree(self):
|
||||
# type: () -> nodes.document
|
||||
def assemble_doctree(self) -> nodes.document:
|
||||
master = self.config.master_doc
|
||||
tree = self.env.get_doctree(master)
|
||||
tree = inline_all_toctrees(self, set(), master, tree, darkgreen, [master])
|
||||
@ -91,8 +84,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
self.fix_refuris(tree)
|
||||
return tree
|
||||
|
||||
def assemble_toc_secnumbers(self):
|
||||
# type: () -> Dict[str, Dict[str, Tuple[int, ...]]]
|
||||
def assemble_toc_secnumbers(self) -> Dict[str, Dict[str, Tuple[int, ...]]]:
|
||||
# Assemble toc_secnumbers to resolve section numbers on SingleHTML.
|
||||
# Merge all secnumbers to single secnumber.
|
||||
#
|
||||
@ -110,8 +102,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
|
||||
return {self.config.master_doc: new_secnumbers}
|
||||
|
||||
def assemble_toc_fignumbers(self):
|
||||
# type: () -> Dict[str, Dict[str, Dict[str, Tuple[int, ...]]]]
|
||||
def assemble_toc_fignumbers(self) -> Dict[str, Dict[str, Dict[str, Tuple[int, ...]]]]:
|
||||
# Assemble toc_fignumbers to resolve figure numbers on SingleHTML.
|
||||
# Merge all fignumbers to single fignumber.
|
||||
#
|
||||
@ -132,8 +123,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
|
||||
return {self.config.master_doc: new_fignumbers}
|
||||
|
||||
def get_doc_context(self, docname, body, metatags):
|
||||
# type: (str, str, str) -> Dict
|
||||
def get_doc_context(self, docname: str, body: str, metatags: str) -> Dict:
|
||||
# no relation links...
|
||||
toctree = TocTree(self.env).get_toctree_for(self.config.master_doc, self, False)
|
||||
# if there is no toctree, toc is None
|
||||
@ -159,8 +149,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
'display_toc': display_toc,
|
||||
}
|
||||
|
||||
def write(self, *ignored):
|
||||
# type: (Any) -> None
|
||||
def write(self, *ignored: Any) -> None:
|
||||
docnames = self.env.all_docs
|
||||
|
||||
with progress_message(__('preparing documents')):
|
||||
@ -175,8 +164,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
self.write_doc_serialized(self.config.master_doc, doctree)
|
||||
self.write_doc(self.config.master_doc, doctree)
|
||||
|
||||
def finish(self):
|
||||
# type: () -> None
|
||||
def finish(self) -> None:
|
||||
self.write_additional_files()
|
||||
self.copy_image_files()
|
||||
self.copy_download_files()
|
||||
@ -186,8 +174,7 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
self.dump_inventory()
|
||||
|
||||
@progress_message(__('writing additional files'))
|
||||
def write_additional_files(self):
|
||||
# type: () -> None
|
||||
def write_additional_files(self) -> None:
|
||||
# no indices or search pages are supported
|
||||
|
||||
# additional pages from conf.py
|
||||
@ -201,8 +188,15 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
self.handle_page('opensearch', {}, 'opensearch.xml', outfilename=fn)
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
# for compatibility
|
||||
deprecated_alias('sphinx.builders.html',
|
||||
{
|
||||
'SingleFileHTMLBuilder': SingleFileHTMLBuilder,
|
||||
},
|
||||
RemovedInSphinx40Warning)
|
||||
|
||||
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.setup_extension('sphinx.builders.html')
|
||||
|
||||
app.add_builder(SingleFileHTMLBuilder)
|
||||
|
@ -4,12 +4,13 @@
|
||||
|
||||
Texinfo builder.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import os
|
||||
from os import path
|
||||
from typing import Any, Dict, Iterable, List, Tuple, Union
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.frontend import OptionParser
|
||||
@ -17,9 +18,11 @@ from docutils.io import FileOutput
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx import package_dir
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.environment import NoUri
|
||||
from sphinx.config import Config
|
||||
from sphinx.environment.adapters.asset import ImageAdapter
|
||||
from sphinx.errors import NoUri
|
||||
from sphinx.locale import _, __
|
||||
from sphinx.util import logging
|
||||
from sphinx.util import progress_message, status_iterator
|
||||
@ -27,15 +30,9 @@ from sphinx.util.console import darkgreen # type: ignore
|
||||
from sphinx.util.docutils import new_document
|
||||
from sphinx.util.fileutil import copy_asset_file
|
||||
from sphinx.util.nodes import inline_all_toctrees
|
||||
from sphinx.util.osutil import SEP, make_filename_from_project
|
||||
from sphinx.util.osutil import SEP, ensuredir, make_filename_from_project
|
||||
from sphinx.writers.texinfo import TexinfoWriter, TexinfoTranslator
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
from typing import Any, Dict, Iterable, List, Tuple, Union # NOQA
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
template_dir = os.path.join(package_dir, 'templates', 'texinfo')
|
||||
@ -57,29 +54,24 @@ class TexinfoBuilder(Builder):
|
||||
'image/gif']
|
||||
default_translator_class = TexinfoTranslator
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
def init(self) -> None:
|
||||
self.docnames = [] # type: Iterable[str]
|
||||
self.document_data = [] # type: List[Tuple[str, str, str, str, str, str, str, bool]]
|
||||
|
||||
def get_outdated_docs(self):
|
||||
# type: () -> Union[str, List[str]]
|
||||
def get_outdated_docs(self) -> Union[str, List[str]]:
|
||||
return 'all documents' # for now
|
||||
|
||||
def get_target_uri(self, docname, typ=None):
|
||||
# type: (str, str) -> str
|
||||
def get_target_uri(self, docname: str, typ: str = None) -> str:
|
||||
if docname not in self.docnames:
|
||||
raise NoUri
|
||||
raise NoUri(docname, typ)
|
||||
else:
|
||||
return '%' + docname
|
||||
|
||||
def get_relative_uri(self, from_, to, typ=None):
|
||||
# type: (str, str, str) -> str
|
||||
def get_relative_uri(self, from_: str, to: str, typ: str = None) -> str:
|
||||
# ignore source path
|
||||
return self.get_target_uri(to, typ)
|
||||
|
||||
def init_document_data(self):
|
||||
# type: () -> None
|
||||
def init_document_data(self) -> None:
|
||||
preliminary_document_data = [list(x) for x in self.config.texinfo_documents]
|
||||
if not preliminary_document_data:
|
||||
logger.warning(__('no "texinfo_documents" config value found; no documents '
|
||||
@ -98,8 +90,7 @@ class TexinfoBuilder(Builder):
|
||||
docname = docname[:-5]
|
||||
self.titles.append((docname, entry[2]))
|
||||
|
||||
def write(self, *ignored):
|
||||
# type: (Any) -> None
|
||||
def write(self, *ignored: Any) -> None:
|
||||
self.init_document_data()
|
||||
for entry in self.document_data:
|
||||
docname, targetname, title, author = entry[:4]
|
||||
@ -134,9 +125,9 @@ class TexinfoBuilder(Builder):
|
||||
settings.docname = docname
|
||||
doctree.settings = settings
|
||||
docwriter.write(doctree, destination)
|
||||
self.copy_image_files(targetname[:-5])
|
||||
|
||||
def assemble_doctree(self, indexfile, toctree_only, appendices):
|
||||
# type: (str, bool, List[str]) -> nodes.document
|
||||
def assemble_doctree(self, indexfile: str, toctree_only: bool, appendices: List[str]) -> nodes.document: # NOQA
|
||||
self.docnames = set([indexfile] + appendices)
|
||||
logger.info(darkgreen(indexfile) + " ", nonl=True)
|
||||
tree = self.env.get_doctree(indexfile)
|
||||
@ -178,13 +169,10 @@ class TexinfoBuilder(Builder):
|
||||
pendingnode.replace_self(newnodes)
|
||||
return largetree
|
||||
|
||||
def finish(self):
|
||||
# type: () -> None
|
||||
self.copy_image_files()
|
||||
def finish(self) -> None:
|
||||
self.copy_support_files()
|
||||
|
||||
def copy_image_files(self):
|
||||
# type: () -> None
|
||||
def copy_image_files(self, targetname: str) -> None:
|
||||
if self.images:
|
||||
stringify_func = ImageAdapter(self.app.env).get_original_image_uri
|
||||
for src in status_iterator(self.images, __('copying images... '), "brown",
|
||||
@ -192,14 +180,14 @@ class TexinfoBuilder(Builder):
|
||||
stringify_func=stringify_func):
|
||||
dest = self.images[src]
|
||||
try:
|
||||
copy_asset_file(path.join(self.srcdir, src),
|
||||
path.join(self.outdir, dest))
|
||||
imagedir = path.join(self.outdir, targetname + '-figures')
|
||||
ensuredir(imagedir)
|
||||
copy_asset_file(path.join(self.srcdir, dest), imagedir)
|
||||
except Exception as err:
|
||||
logger.warning(__('cannot copy image file %r: %s'),
|
||||
path.join(self.srcdir, src), err)
|
||||
|
||||
def copy_support_files(self):
|
||||
# type: () -> None
|
||||
def copy_support_files(self) -> None:
|
||||
try:
|
||||
with progress_message(__('copying Texinfo support files')):
|
||||
logger.info('Makefile ', nonl=True)
|
||||
@ -208,16 +196,14 @@ class TexinfoBuilder(Builder):
|
||||
logger.warning(__("error writing file Makefile: %s"), err)
|
||||
|
||||
|
||||
def default_texinfo_documents(config):
|
||||
# type: (Config) -> List[Tuple[str, str, str, str, str, str, str]]
|
||||
def default_texinfo_documents(config: Config) -> List[Tuple[str, str, str, str, str, str, str]]: # NOQA
|
||||
""" Better default texinfo_documents settings. """
|
||||
filename = make_filename_from_project(config.project)
|
||||
return [(config.master_doc, filename, config.project, config.author, filename,
|
||||
'One line description of project', 'Miscellaneous')]
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.add_builder(TexinfoBuilder)
|
||||
|
||||
app.add_config_value('texinfo_documents', default_texinfo_documents, None)
|
||||
|
@ -4,26 +4,23 @@
|
||||
|
||||
Plain-text Sphinx builder.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from os import path
|
||||
from typing import Any, Dict, Iterator, Set, Tuple
|
||||
|
||||
from docutils.io import StringOutput
|
||||
from docutils.nodes import Node
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.osutil import ensuredir, os_path
|
||||
from sphinx.writers.text import TextWriter, TextTranslator
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, Iterator, Set, Tuple # NOQA
|
||||
from docutils import nodes # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@ -38,13 +35,11 @@ class TextBuilder(Builder):
|
||||
|
||||
current_docname = None # type: str
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
def init(self) -> None:
|
||||
# section numbers for headings in the currently visited document
|
||||
self.secnumbers = {} # type: Dict[str, Tuple[int, ...]]
|
||||
|
||||
def get_outdated_docs(self):
|
||||
# type: () -> Iterator[str]
|
||||
def get_outdated_docs(self) -> Iterator[str]:
|
||||
for docname in self.env.found_docs:
|
||||
if docname not in self.env.all_docs:
|
||||
yield docname
|
||||
@ -62,16 +57,13 @@ class TextBuilder(Builder):
|
||||
# source doesn't exist anymore
|
||||
pass
|
||||
|
||||
def get_target_uri(self, docname, typ=None):
|
||||
# type: (str, str) -> str
|
||||
def get_target_uri(self, docname: str, typ: str = None) -> str:
|
||||
return ''
|
||||
|
||||
def prepare_writing(self, docnames):
|
||||
# type: (Set[str]) -> None
|
||||
def prepare_writing(self, docnames: Set[str]) -> None:
|
||||
self.writer = TextWriter(self)
|
||||
|
||||
def write_doc(self, docname, doctree):
|
||||
# type: (str, nodes.Node) -> None
|
||||
def write_doc(self, docname: str, doctree: Node) -> None:
|
||||
self.current_docname = docname
|
||||
self.secnumbers = self.env.toc_secnumbers.get(docname, {})
|
||||
destination = StringOutput(encoding='utf-8')
|
||||
@ -84,13 +76,11 @@ class TextBuilder(Builder):
|
||||
except OSError as err:
|
||||
logger.warning(__("error writing file %s: %s"), outfilename, err)
|
||||
|
||||
def finish(self):
|
||||
# type: () -> None
|
||||
def finish(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.add_builder(TextBuilder)
|
||||
|
||||
app.add_config_value('text_sectionchars', '*=-~"+`', 'env')
|
||||
|
@ -4,16 +4,19 @@
|
||||
|
||||
Docutils-native XML and pseudo-XML builders.
|
||||
|
||||
:copyright: Copyright 2007-2019 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from os import path
|
||||
from typing import Any, Dict, Iterator, Set, Union
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.io import StringOutput
|
||||
from docutils.nodes import Node
|
||||
from docutils.writers.docutils_xml import XMLTranslator
|
||||
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import logging
|
||||
@ -22,9 +25,8 @@ from sphinx.writers.xml import XMLWriter, PseudoXMLWriter
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, Iterator, Set, Type # NOQA
|
||||
from docutils.writers.xml import BaseXMLWriter # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from typing import Type # for python3.5.1
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -40,15 +42,13 @@ class XMLBuilder(Builder):
|
||||
out_suffix = '.xml'
|
||||
allow_parallel = True
|
||||
|
||||
_writer_class = XMLWriter # type: Type[BaseXMLWriter]
|
||||
_writer_class = XMLWriter # type: Union[Type[XMLWriter], Type[PseudoXMLWriter]]
|
||||
default_translator_class = XMLTranslator
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
def init(self) -> None:
|
||||
pass
|
||||
|
||||
def get_outdated_docs(self):
|
||||
# type: () -> Iterator[str]
|
||||
def get_outdated_docs(self) -> Iterator[str]:
|
||||
for docname in self.env.found_docs:
|
||||
if docname not in self.env.all_docs:
|
||||
yield docname
|
||||
@ -66,16 +66,13 @@ class XMLBuilder(Builder):
|
||||
# source doesn't exist anymore
|
||||
pass
|
||||
|
||||
def get_target_uri(self, docname, typ=None):
|
||||
# type: (str, str) -> str
|
||||
def get_target_uri(self, docname: str, typ: str = None) -> str:
|
||||
return docname
|
||||
|
||||
def prepare_writing(self, docnames):
|
||||
# type: (Set[str]) -> None
|
||||
def prepare_writing(self, docnames: Set[str]) -> None:
|
||||
self.writer = self._writer_class(self)
|
||||
|
||||
def write_doc(self, docname, doctree):
|
||||
# type: (str, nodes.Node) -> None
|
||||
def write_doc(self, docname: str, doctree: Node) -> None:
|
||||
# work around multiple string % tuple issues in docutils;
|
||||
# replace tuples in attribute values with lists
|
||||
doctree = doctree.deepcopy()
|
||||
@ -98,8 +95,7 @@ class XMLBuilder(Builder):
|
||||
except OSError as err:
|
||||
logger.warning(__("error writing file %s: %s"), outfilename, err)
|
||||
|
||||
def finish(self):
|
||||
# type: () -> None
|
||||
def finish(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
@ -116,8 +112,7 @@ class PseudoXMLBuilder(XMLBuilder):
|
||||
_writer_class = PseudoXMLWriter
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[str, Any]
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.add_builder(XMLBuilder)
|
||||
app.add_builder(PseudoXMLBuilder)
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user