mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch 'master' into body-width
This commit is contained in:
commit
1d0a087f75
@ -6,19 +6,12 @@ environment:
|
|||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
- PYTHON: 27
|
- PYTHON: 27
|
||||||
DOCUTILS: 0.13.1
|
|
||||||
TEST_IGNORE: --ignore py35
|
|
||||||
- PYTHON: 27
|
|
||||||
DOCUTILS: 0.14
|
|
||||||
TEST_IGNORE: --ignore py35
|
TEST_IGNORE: --ignore py35
|
||||||
- PYTHON: 36
|
- PYTHON: 36
|
||||||
DOCUTILS: 0.14
|
|
||||||
- PYTHON: 36-x64
|
- PYTHON: 36-x64
|
||||||
DOCUTILS: 0.14
|
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- C:\Python%PYTHON%\python.exe -m pip install -U pip setuptools
|
- C:\Python%PYTHON%\python.exe -m pip install -U pip setuptools
|
||||||
- C:\Python%PYTHON%\python.exe -m pip install docutils==%DOCUTILS% mock
|
|
||||||
- C:\Python%PYTHON%\python.exe -m pip install .[test,websupport]
|
- C:\Python%PYTHON%\python.exe -m pip install .[test,websupport]
|
||||||
|
|
||||||
# No automatic build, just run python tests
|
# No automatic build, just run python tests
|
||||||
|
@ -6,7 +6,6 @@ cache: pip
|
|||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
- PYTHONFAULTHANDLER=x
|
- PYTHONFAULTHANDLER=x
|
||||||
- PYTHONWARNINGS=all
|
|
||||||
- SKIP_LATEX_BUILD=1
|
- SKIP_LATEX_BUILD=1
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
|
2
AUTHORS
2
AUTHORS
@ -18,6 +18,7 @@ Other co-maintainers:
|
|||||||
Other contributors, listed alphabetically, are:
|
Other contributors, listed alphabetically, are:
|
||||||
|
|
||||||
* Alastair Houghton -- Apple Help builder
|
* Alastair Houghton -- Apple Help builder
|
||||||
|
* Alexander Todorov -- inheritance_diagram tests and improvements
|
||||||
* Andi Albrecht -- agogo theme
|
* Andi Albrecht -- agogo theme
|
||||||
* Jakob Lykke Andersen -- Rewritten C++ domain
|
* Jakob Lykke Andersen -- Rewritten C++ domain
|
||||||
* Henrique Bastos -- SVG support for graphviz extension
|
* Henrique Bastos -- SVG support for graphviz extension
|
||||||
@ -68,6 +69,7 @@ Other contributors, listed alphabetically, are:
|
|||||||
* Barry Warsaw -- setup command improvements
|
* Barry Warsaw -- setup command improvements
|
||||||
* Sebastian Wiesner -- image handling, distutils support
|
* Sebastian Wiesner -- image handling, distutils support
|
||||||
* Michael Wilson -- Intersphinx HTTP basic auth support
|
* Michael Wilson -- Intersphinx HTTP basic auth support
|
||||||
|
* Matthew Woodcraft -- text output improvements
|
||||||
* Joel Wurtz -- cellspanning support in LaTeX
|
* Joel Wurtz -- cellspanning support in LaTeX
|
||||||
* Hong Xu -- svg support in imgmath extension and various bug fixes
|
* Hong Xu -- svg support in imgmath extension and various bug fixes
|
||||||
* Stephen Finucane -- setup command improvements and documentation
|
* Stephen Finucane -- setup command improvements and documentation
|
||||||
|
71
CHANGES
71
CHANGES
@ -1,6 +1,11 @@
|
|||||||
Release 1.7 (in development)
|
Release 1.7 (in development)
|
||||||
============================
|
============================
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
|
||||||
|
* Add ``packaging`` package
|
||||||
|
|
||||||
Incompatible changes
|
Incompatible changes
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
@ -13,6 +18,15 @@ Incompatible changes
|
|||||||
* #3929: apidoc: Move sphinx.apidoc to sphinx.ext.apidoc
|
* #3929: apidoc: Move sphinx.apidoc to sphinx.ext.apidoc
|
||||||
* #4226: apidoc: Generate new style makefile (make-mode)
|
* #4226: apidoc: Generate new style makefile (make-mode)
|
||||||
* #4274: sphinx-build returns 2 as an exit code on argument error
|
* #4274: sphinx-build returns 2 as an exit code on argument error
|
||||||
|
* #4389: output directory will be created after loading extensions
|
||||||
|
* autodoc does not generate warnings messages to the generated document even if
|
||||||
|
:confval:`keep_warnings` is True. They are only emitted to stderr.
|
||||||
|
* shebang line is removed from generated conf.py
|
||||||
|
* #2557: autodoc: :confval:`autodoc_mock_imports` only mocks specified modules
|
||||||
|
with their descendants. It does not mock their ancestors. If you want to
|
||||||
|
mock them, please specify the name of ancestors implicitly.
|
||||||
|
* #3620: html theme: move DOCUMENTATION_OPTIONS to independent JavaScript file
|
||||||
|
(refs: #4295)
|
||||||
* #4246: Limit width of text body for all themes. Conifigurable via theme
|
* #4246: Limit width of text body for all themes. Conifigurable via theme
|
||||||
options ``body_min_width`` and ``body_max_width``.
|
options ``body_min_width`` and ``body_max_width``.
|
||||||
|
|
||||||
@ -23,6 +37,12 @@ Deprecated
|
|||||||
values will be accepted at 2.0.
|
values will be accepted at 2.0.
|
||||||
* ``format_annotation()`` and ``formatargspec()`` is deprecated. Please use
|
* ``format_annotation()`` and ``formatargspec()`` is deprecated. Please use
|
||||||
``sphinx.util.inspect.Signature`` instead.
|
``sphinx.util.inspect.Signature`` instead.
|
||||||
|
* ``sphinx.ext.autodoc.AutodocReporter`` is replaced by ``sphinx.util.docutils.
|
||||||
|
switch_source_input()`` and now deprecated. It will be removed in Sphinx-2.0.
|
||||||
|
* ``sphinx.ext.autodoc.add_documenter()`` and ``AutoDirective._register`` is now
|
||||||
|
deprecated. Please use ``app.add_autodocumenter()`` instead.
|
||||||
|
* ``AutoDirective._special_attrgetters`` is now deprecated. Please use
|
||||||
|
``app.add_autodoc_attrgetter()`` instead.
|
||||||
|
|
||||||
Features added
|
Features added
|
||||||
--------------
|
--------------
|
||||||
@ -57,7 +77,21 @@ Features added
|
|||||||
code-blocks
|
code-blocks
|
||||||
* #947: autodoc now supports ignore-module-all to ignore a module's ``__all__``
|
* #947: autodoc now supports ignore-module-all to ignore a module's ``__all__``
|
||||||
* #4332: Let LaTeX obey :confval:`math_numfig` for equation numbering
|
* #4332: Let LaTeX obey :confval:`math_numfig` for equation numbering
|
||||||
|
* #4093: sphinx-build creates empty directories for unknown targets/builders
|
||||||
|
* Add ``top-classes`` option for the ``sphinx.ext.inheritance_diagram``
|
||||||
|
extension to limit the scope of inheritance graphs.
|
||||||
|
* #4183: doctest: ``:pyversion:`` option also follows PEP-440 specification
|
||||||
|
* #4235: html: Add :confval:`manpages_url` to make manpage roles to hyperlinks
|
||||||
|
* #3570: autodoc: Do not display 'typing.' module for type hints
|
||||||
|
* #4354: sphinx-build now emits finish message. Builders can modify it through
|
||||||
|
``Builder.epilog`` attribute
|
||||||
|
* #4245: html themes: Add ``language`` to javascript vars list
|
||||||
|
* #4079: html: Add ``notranslate`` class to each code-blocks, literals and maths
|
||||||
|
to let Google Translate know they are not translatable
|
||||||
|
* #4137: doctest: doctest block is always highlighted as python console (pycon)
|
||||||
|
* #4137: doctest: testcode block is always highlighted as python
|
||||||
|
* #3998: text: Assign section numbers by default. You can control it using
|
||||||
|
:confval:`text_add_secnumbers` and :confval:`text_secnumber_suffix`
|
||||||
|
|
||||||
Features removed
|
Features removed
|
||||||
----------------
|
----------------
|
||||||
@ -88,6 +122,8 @@ Features removed
|
|||||||
* LaTeX environment ``notice``, use ``sphinxadmonition`` instead
|
* LaTeX environment ``notice``, use ``sphinxadmonition`` instead
|
||||||
* LaTeX ``\sphinxstylethead``, use ``\sphinxstyletheadfamily``
|
* LaTeX ``\sphinxstylethead``, use ``\sphinxstyletheadfamily``
|
||||||
* C++, support of function concepts. Thanks to mickk-on-cpp.
|
* C++, support of function concepts. Thanks to mickk-on-cpp.
|
||||||
|
* Not used and previously not documented LaTeX macros ``\shortversion``
|
||||||
|
and ``\setshortversion``
|
||||||
|
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
@ -103,13 +139,18 @@ Bugs fixed
|
|||||||
one of figures and tables
|
one of figures and tables
|
||||||
* #4330: PDF 'howto' documents have an incoherent default LaTeX tocdepth counter
|
* #4330: PDF 'howto' documents have an incoherent default LaTeX tocdepth counter
|
||||||
setting
|
setting
|
||||||
|
* #4198: autosummary emits multiple 'autodoc-process-docstring' event. Thanks
|
||||||
|
to Joel Nothman.
|
||||||
|
* #4081: Warnings and errors colored the same when building
|
||||||
|
* latex: Do not display 'Release' label if :confval:`release` is not set
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
--------
|
--------
|
||||||
|
|
||||||
* Add support for docutils 0.14
|
* Add support for docutils 0.14
|
||||||
|
* Add tests for the ``sphinx.ext.inheritance_diagram`` extension.
|
||||||
|
|
||||||
Release 1.6.6 (in development)
|
Release 1.6.7 (in development)
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
Dependencies
|
Dependencies
|
||||||
@ -124,14 +165,35 @@ Deprecated
|
|||||||
Features added
|
Features added
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
Bugs fixed
|
||||||
|
----------
|
||||||
|
|
||||||
|
* #1922: html search: Upper characters problem in French
|
||||||
|
|
||||||
|
|
||||||
|
Testing
|
||||||
|
--------
|
||||||
|
|
||||||
|
Release 1.6.6 (released Jan 08, 2018)
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
Features added
|
||||||
|
--------------
|
||||||
|
|
||||||
* #4181: autodoc: Sort dictionary keys when possible
|
* #4181: autodoc: Sort dictionary keys when possible
|
||||||
* ``VerbatimHighlightColor`` is a new
|
* ``VerbatimHighlightColor`` is a new
|
||||||
:ref:`LaTeX 'sphinxsetup' <latexsphinxsetup>` key (refs: #4285)
|
:ref:`LaTeX 'sphinxsetup' <latexsphinxsetup>` key (refs: #4285)
|
||||||
* Easier customizability of LaTeX macros involved in rendering of code-blocks
|
* Easier customizability of LaTeX macros involved in rendering of code-blocks
|
||||||
|
* Show traceback if conf.py raises an exception (refs: #4369)
|
||||||
|
* Add :confval:`smartquotes` to disable smart quotes through ``conf.py``
|
||||||
|
(refs: #3967)
|
||||||
|
* Add :confval:`smartquotes_action` and :confval:`smartquotes_excludes`
|
||||||
|
(refs: #4142, #4357)
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
* #4334: sphinx-apidoc: Don't generate references to non-existing files in TOC
|
||||||
* #4206: latex: reST label between paragraphs loses paragraph break
|
* #4206: latex: reST label between paragraphs loses paragraph break
|
||||||
* #4231: html: Apply fixFirefoxAnchorBug only under Firefox
|
* #4231: html: Apply fixFirefoxAnchorBug only under Firefox
|
||||||
* #4221: napoleon depends on autodoc, but users need to load it manually
|
* #4221: napoleon depends on autodoc, but users need to load it manually
|
||||||
@ -148,9 +210,8 @@ Bugs fixed
|
|||||||
* #4315: For PDF 'howto' documents, ``latex_toplevel_sectioning='part'`` generates
|
* #4315: For PDF 'howto' documents, ``latex_toplevel_sectioning='part'`` generates
|
||||||
``\chapter`` commands
|
``\chapter`` commands
|
||||||
* #4214: Two todolist directives break sphinx-1.6.5
|
* #4214: Two todolist directives break sphinx-1.6.5
|
||||||
|
* Fix links to external option docs with intersphinx (refs: #3769)
|
||||||
Testing
|
* #4091: Private members not documented without :undoc-members:
|
||||||
--------
|
|
||||||
|
|
||||||
Release 1.6.5 (released Oct 23, 2017)
|
Release 1.6.5 (released Oct 23, 2017)
|
||||||
=====================================
|
=====================================
|
||||||
|
4
EXAMPLES
4
EXAMPLES
@ -93,7 +93,7 @@ Documentation using the classic theme
|
|||||||
* simuPOP: http://simupop.sourceforge.net/manual_release/build/userGuide.html (customized)
|
* simuPOP: http://simupop.sourceforge.net/manual_release/build/userGuide.html (customized)
|
||||||
* Sprox: http://sprox.org/ (customized)
|
* Sprox: http://sprox.org/ (customized)
|
||||||
* SymPy: http://docs.sympy.org/
|
* SymPy: http://docs.sympy.org/
|
||||||
* TurboGears: https://turbogears.readthedocs.org/ (customized)
|
* TurboGears: https://turbogears.readthedocs.io/ (customized)
|
||||||
* tvtk: http://docs.enthought.com/mayavi/tvtk/
|
* tvtk: http://docs.enthought.com/mayavi/tvtk/
|
||||||
* Varnish: https://www.varnish-cache.org/docs/ (customized, alabaster for index)
|
* Varnish: https://www.varnish-cache.org/docs/ (customized, alabaster for index)
|
||||||
* Waf: https://waf.io/apidocs/
|
* Waf: https://waf.io/apidocs/
|
||||||
@ -259,7 +259,7 @@ Documentation using sphinx_bootstrap_theme
|
|||||||
* Bootstrap Theme: https://ryan-roemer.github.io/sphinx-bootstrap-theme/
|
* Bootstrap Theme: https://ryan-roemer.github.io/sphinx-bootstrap-theme/
|
||||||
* C/C++ Software Development with Eclipse: http://eclipsebook.in/
|
* C/C++ Software Development with Eclipse: http://eclipsebook.in/
|
||||||
* Dataverse: http://guides.dataverse.org/
|
* Dataverse: http://guides.dataverse.org/
|
||||||
* e-cidadania: http://e-cidadania.readthedocs.org/
|
* e-cidadania: https://e-cidadania.readthedocs.io/
|
||||||
* Hangfire: http://docs.hangfire.io/
|
* Hangfire: http://docs.hangfire.io/
|
||||||
* Hedge: https://documen.tician.de/hedge/
|
* Hedge: https://documen.tician.de/hedge/
|
||||||
* ObsPy: https://docs.obspy.org/
|
* ObsPy: https://docs.obspy.org/
|
||||||
|
6
doc/_templates/index.html
vendored
6
doc/_templates/index.html
vendored
@ -74,9 +74,9 @@
|
|||||||
|
|
||||||
<p>{%trans%}
|
<p>{%trans%}
|
||||||
You can also download PDF/EPUB versions of the Sphinx documentation:
|
You can also download PDF/EPUB versions of the Sphinx documentation:
|
||||||
a <a href="http://readthedocs.org/projects/sphinx/downloads/pdf/stable/">PDF version</a> generated from
|
a <a href="https://media.readthedocs.org/pdf/sphinx/stable/sphinx.pdf">PDF version</a> generated from
|
||||||
the LaTeX Sphinx produces, and
|
the LaTeX Sphinx produces, and
|
||||||
a <a href="http://readthedocs.org/projects/sphinx/downloads/epub/stable/">EPUB version</a>.
|
a <a href="https://media.readthedocs.org/epub/sphinx/stable/sphinx.epub">EPUB version</a>.
|
||||||
{%endtrans%}
|
{%endtrans%}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
@ -106,7 +106,7 @@
|
|||||||
<h2>{%trans%}Hosting{%endtrans%}</h2>
|
<h2>{%trans%}Hosting{%endtrans%}</h2>
|
||||||
|
|
||||||
<p>{%trans%}Need a place to host your Sphinx docs?
|
<p>{%trans%}Need a place to host your Sphinx docs?
|
||||||
<a href="http://readthedocs.org">readthedocs.org</a> hosts a lot of Sphinx docs
|
<a href="https://readthedocs.org/">readthedocs.org</a> hosts a lot of Sphinx docs
|
||||||
already, and integrates well with projects' source control. It also features a
|
already, and integrates well with projects' source control. It also features a
|
||||||
powerful built-in search that exceeds the possibilities of Sphinx' JavaScript-based
|
powerful built-in search that exceeds the possibilities of Sphinx' JavaScript-based
|
||||||
offline search.{%endtrans%}</p>
|
offline search.{%endtrans%}</p>
|
||||||
|
8
doc/_templates/indexsidebar.html
vendored
8
doc/_templates/indexsidebar.html
vendored
@ -20,12 +20,14 @@ Index</a>, or install it with:{%endtrans%}</p>
|
|||||||
<h3>{%trans%}Questions? Suggestions?{%endtrans%}</h3>
|
<h3>{%trans%}Questions? Suggestions?{%endtrans%}</h3>
|
||||||
|
|
||||||
<p>{%trans%}Join the <a href="http://groups.google.com/group/sphinx-users">sphinx-users</a> mailing list on Google Groups:{%endtrans%}</p>
|
<p>{%trans%}Join the <a href="http://groups.google.com/group/sphinx-users">sphinx-users</a> mailing list on Google Groups:{%endtrans%}</p>
|
||||||
|
<div class="subscribeformwrapper">
|
||||||
<form action="http://groups.google.com/group/sphinx-users/boxsubscribe"
|
<form action="http://groups.google.com/group/sphinx-users/boxsubscribe"
|
||||||
style="padding-left: 0.5em">
|
class="subscribeform">
|
||||||
<input type="text" name="email" value="your@email" style="font-size: 90%; width: 120px"
|
<input type="text" name="email" value="your@email"
|
||||||
onfocus="$(this).val('');" />
|
onfocus="$(this).val('');" />
|
||||||
<input type="submit" name="sub" value="Subscribe" style="font-size: 90%; width: 70px"/>
|
<input type="submit" name="sub" value="Subscribe" />
|
||||||
</form>
|
</form>
|
||||||
|
</div>
|
||||||
<p>{%trans%}or come to the <tt>#sphinx-doc</tt> channel on FreeNode.{%endtrans%}</p>
|
<p>{%trans%}or come to the <tt>#sphinx-doc</tt> channel on FreeNode.{%endtrans%}</p>
|
||||||
<p>{%trans%}You can also open an issue at the
|
<p>{%trans%}You can also open an issue at the
|
||||||
<a href="https://github.com/sphinx-doc/sphinx/issues">tracker</a>.{%endtrans%}</p>
|
<a href="https://github.com/sphinx-doc/sphinx/issues">tracker</a>.{%endtrans%}</p>
|
||||||
|
30
doc/_themes/sphinx13/static/sphinx13.css
vendored
30
doc/_themes/sphinx13/static/sphinx13.css
vendored
@ -140,11 +140,37 @@ div.sphinxsidebar .logo img {
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.subscribeformwrapper {
|
||||||
|
display: block;
|
||||||
|
overflow: auto;
|
||||||
|
margin-bottom: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
div.sphinxsidebar input {
|
div.sphinxsidebar input {
|
||||||
border: 1px solid #aaa;
|
border: 1px solid #aaa;
|
||||||
font-family: 'Open Sans', 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
|
font-family: 'Open Sans', 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
|
||||||
'Verdana', sans-serif;
|
'Verdana', sans-serif;
|
||||||
font-size: 1em;
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar .subscribeform {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar .subscribeform input {
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
font-size: 0.9em;
|
||||||
|
float: left;
|
||||||
|
padding: 0.25em 0.5em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar .subscribeform input[type="text"] {
|
||||||
|
width: 60%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar .subscribeform input[type="submit"] {
|
||||||
|
width: 40%;
|
||||||
|
border-left: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.sphinxsidebar h3 {
|
div.sphinxsidebar h3 {
|
||||||
@ -281,7 +307,7 @@ tt {
|
|||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
color: #333;
|
color: #333;
|
||||||
padding: 1px;
|
padding: 1px 0.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
tt.descname, tt.descclassname, tt.xref {
|
tt.descname, tt.descclassname, tt.xref {
|
||||||
|
@ -293,6 +293,24 @@ General configuration
|
|||||||
|
|
||||||
.. versionadded:: 1.3
|
.. versionadded:: 1.3
|
||||||
|
|
||||||
|
.. confval:: manpages_url
|
||||||
|
|
||||||
|
A URL to cross-reference :rst:role:`manpage` directives. If this is
|
||||||
|
defined to ``https://manpages.debian.org/{path}``, the
|
||||||
|
:literal:`:manpage:`man(1)`` role will like to
|
||||||
|
<https://manpages.debian.org/man(1)>. The patterns available are:
|
||||||
|
|
||||||
|
* ``page`` - the manual page (``man``)
|
||||||
|
* ``section`` - the manual section (``1``)
|
||||||
|
* ``path`` - the original manual page and section specified (``man(1)``)
|
||||||
|
|
||||||
|
This also supports manpages specified as ``man.1``.
|
||||||
|
|
||||||
|
.. note:: This currently affects only HTML writers but could be
|
||||||
|
expanded in the future.
|
||||||
|
|
||||||
|
.. versionadded:: 1.7
|
||||||
|
|
||||||
.. confval:: nitpicky
|
.. confval:: nitpicky
|
||||||
|
|
||||||
If true, Sphinx will warn about *all* references where the target cannot be
|
If true, Sphinx will warn about *all* references where the target cannot be
|
||||||
@ -354,6 +372,63 @@ General configuration
|
|||||||
The LaTeX builder obeys this setting (if :confval:`numfig` is set to
|
The LaTeX builder obeys this setting (if :confval:`numfig` is set to
|
||||||
``True``).
|
``True``).
|
||||||
|
|
||||||
|
.. confval:: smartquotes
|
||||||
|
|
||||||
|
If true, the `Docutils Smart Quotes transform`__, originally based on
|
||||||
|
`SmartyPants`__ (limited to English) and currently applying to many
|
||||||
|
languages, will be used to convert quotes and dashes to typographically
|
||||||
|
correct entities. Default: ``True``.
|
||||||
|
|
||||||
|
__ http://docutils.sourceforge.net/docs/user/smartquotes.html
|
||||||
|
__ https://daringfireball.net/projects/smartypants/
|
||||||
|
|
||||||
|
.. versionadded:: 1.6.6
|
||||||
|
It replaces deprecated :confval:`html_use_smartypants`.
|
||||||
|
It applies by default to all builders except ``man`` and ``text``
|
||||||
|
(see :confval:`smartquotes_excludes`.)
|
||||||
|
|
||||||
|
A `docutils.conf`__ file located in the configuration directory (or a
|
||||||
|
global :file:`~/.docutils` file) is obeyed unconditionally if it
|
||||||
|
*deactivates* smart quotes via the corresponding `Docutils option`__. But
|
||||||
|
if it *activates* them, then :confval:`smartquotes` does prevail.
|
||||||
|
|
||||||
|
__ http://docutils.sourceforge.net/docs/user/config.html
|
||||||
|
__ http://docutils.sourceforge.net/docs/user/config.html#smart-quotes
|
||||||
|
|
||||||
|
.. confval:: smartquotes_action
|
||||||
|
|
||||||
|
This string, for use with Docutils ``0.14`` or later, customizes the Smart
|
||||||
|
Quotes transform. See the file :file:`smartquotes.py` at the `Docutils
|
||||||
|
repository`__ for details. The default ``'qDe'`` educates normal **q**\
|
||||||
|
uote characters ``"``, ``'``, em- and en-**D**\ ashes ``---``, ``--``, and
|
||||||
|
**e**\ llipses ``...``.
|
||||||
|
|
||||||
|
.. versionadded:: 1.6.6
|
||||||
|
|
||||||
|
__ https://sourceforge.net/p/docutils/code/HEAD/tree/trunk/docutils/
|
||||||
|
|
||||||
|
.. confval:: smartquotes_excludes
|
||||||
|
|
||||||
|
This is a ``dict`` whose default is::
|
||||||
|
|
||||||
|
{'languages': ['ja'], 'builders': ['man', 'text']}
|
||||||
|
|
||||||
|
Each entry gives a sufficient condition to ignore the
|
||||||
|
:confval:`smartquotes` setting and deactivate the Smart Quotes transform.
|
||||||
|
Accepted keys are as above ``'builders'`` or ``'languages'``.
|
||||||
|
The values are lists.
|
||||||
|
|
||||||
|
.. note:: Currently, in case of invocation of :program:`make` with multiple
|
||||||
|
targets, the first target name is the only one which is tested against
|
||||||
|
the ``'builders'`` entry and it decides for all. Also, a ``make text``
|
||||||
|
following ``make html`` needs to be issued in the form ``make text
|
||||||
|
O="-E"`` to force re-parsing of source files, as the cached ones are
|
||||||
|
already transformed. On the other hand the issue does not arise with
|
||||||
|
direct usage of :program:`sphinx-build` as it caches
|
||||||
|
(in its default usage) the parsed source files in per builder locations.
|
||||||
|
|
||||||
|
.. versionadded:: 1.6.6
|
||||||
|
|
||||||
.. confval:: tls_verify
|
.. confval:: tls_verify
|
||||||
|
|
||||||
If true, Sphinx verifies server certifications. Default is ``True``.
|
If true, Sphinx verifies server certifications. Default is ``True``.
|
||||||
@ -785,15 +860,11 @@ that use Sphinx's HTMLWriter class.
|
|||||||
|
|
||||||
.. confval:: html_use_smartypants
|
.. confval:: html_use_smartypants
|
||||||
|
|
||||||
If true, `SmartyPants <https://daringfireball.net/projects/smartypants/>`_
|
If true, quotes and dashes are converted to typographically correct
|
||||||
will be used to convert quotes and dashes to typographically correct
|
|
||||||
entities. Default: ``True``.
|
entities. Default: ``True``.
|
||||||
|
|
||||||
.. deprecated:: 1.6
|
.. deprecated:: 1.6
|
||||||
To disable or customize smart quotes, use the Docutils configuration file
|
To disable smart quotes, use rather :confval:`smartquotes`.
|
||||||
(``docutils.conf``) instead to set there its `smart_quotes option`_.
|
|
||||||
|
|
||||||
.. _`smart_quotes option`: http://docutils.sourceforge.net/docs/user/config.html#smart-quotes
|
|
||||||
|
|
||||||
.. confval:: html_add_permalinks
|
.. confval:: html_add_permalinks
|
||||||
|
|
||||||
@ -1968,6 +2039,20 @@ These options influence text output.
|
|||||||
|
|
||||||
.. versionadded:: 1.1
|
.. versionadded:: 1.1
|
||||||
|
|
||||||
|
.. confval:: text_add_secnumbers
|
||||||
|
|
||||||
|
A boolean that decides whether section numbers are included in text output.
|
||||||
|
Default is ``True``.
|
||||||
|
|
||||||
|
.. versionadded:: 1.7
|
||||||
|
|
||||||
|
.. confval:: text_secnumber_suffix
|
||||||
|
|
||||||
|
Suffix for section numbers in text output. Default: ``". "``. Set to ``" "``
|
||||||
|
to suppress the final dot on section numbers.
|
||||||
|
|
||||||
|
.. versionadded:: 1.7
|
||||||
|
|
||||||
|
|
||||||
.. _man-options:
|
.. _man-options:
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ own extensions.
|
|||||||
.. _cmakedomain: https://bitbucket.org/klorenz/sphinxcontrib-cmakedomain
|
.. _cmakedomain: https://bitbucket.org/klorenz/sphinxcontrib-cmakedomain
|
||||||
.. _GNU Make: http://www.gnu.org/software/make/
|
.. _GNU Make: http://www.gnu.org/software/make/
|
||||||
.. _makedomain: https://bitbucket.org/klorenz/sphinxcontrib-makedomain
|
.. _makedomain: https://bitbucket.org/klorenz/sphinxcontrib-makedomain
|
||||||
.. _inlinesyntaxhighlight: http://sphinxcontrib-inlinesyntaxhighlight.readthedocs.org
|
.. _inlinesyntaxhighlight: https://sphinxcontrib-inlinesyntaxhighlight.readthedocs.io/
|
||||||
.. _CMake: https://cmake.org
|
.. _CMake: https://cmake.org
|
||||||
.. _domaintools: https://bitbucket.org/klorenz/sphinxcontrib-domaintools
|
.. _domaintools: https://bitbucket.org/klorenz/sphinxcontrib-domaintools
|
||||||
.. _restbuilder: https://pypi.python.org/pypi/sphinxcontrib-restbuilder
|
.. _restbuilder: https://pypi.python.org/pypi/sphinxcontrib-restbuilder
|
||||||
|
@ -80,12 +80,24 @@ a comma-separated list of group names.
|
|||||||
.. doctest::
|
.. doctest::
|
||||||
:pyversion: > 3.3
|
:pyversion: > 3.3
|
||||||
|
|
||||||
The supported operands are ``<``, ``<=``, ``==``, ``>=``, ``>``, and
|
The following operands are supported:
|
||||||
comparison is performed by `distutils.version.LooseVersion
|
|
||||||
<https://www.python.org/dev/peps/pep-0386/#distutils>`__.
|
* ``~=``: Compatible release clause
|
||||||
|
* ``==``: Version matching clause
|
||||||
|
* ``!=``: Version exclusion clause
|
||||||
|
* ``<=``, ``>=``: Inclusive ordered comparison clause
|
||||||
|
* ``<``, ``>``: Exclusive ordered comparison clause
|
||||||
|
* ``===``: Arbitrary equality clause.
|
||||||
|
|
||||||
|
``pyversion`` option is followed `PEP-440: Version Specifiers
|
||||||
|
<https://www.python.org/dev/peps/pep-0440/#version-specifiers>`__.
|
||||||
|
|
||||||
.. versionadded:: 1.6
|
.. versionadded:: 1.6
|
||||||
|
|
||||||
|
.. versionchanged:: 1.7
|
||||||
|
|
||||||
|
Supported PEP-440 operands and notations
|
||||||
|
|
||||||
Note that like with standard doctests, you have to use ``<BLANKLINE>`` to
|
Note that like with standard doctests, you have to use ``<BLANKLINE>`` to
|
||||||
signal a blank line in the expected output. The ``<BLANKLINE>`` is removed
|
signal a blank line in the expected output. The ``<BLANKLINE>`` is removed
|
||||||
when building presentation output (HTML, LaTeX etc.).
|
when building presentation output (HTML, LaTeX etc.).
|
||||||
|
@ -42,6 +42,54 @@ It adds this directive:
|
|||||||
.. versionchanged:: 1.5
|
.. versionchanged:: 1.5
|
||||||
Added ``caption`` option
|
Added ``caption`` option
|
||||||
|
|
||||||
|
It also supports a ``top-classes`` option which requires one or more class
|
||||||
|
names separated by comma. If specified inheritance traversal will stop at the
|
||||||
|
specified class names. Given the following Python module::
|
||||||
|
|
||||||
|
"""
|
||||||
|
A
|
||||||
|
/ \
|
||||||
|
B C
|
||||||
|
/ \ / \
|
||||||
|
E D F
|
||||||
|
"""
|
||||||
|
|
||||||
|
class A(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class B(A):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class C(A):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class D(B, C):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class E(B):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class F(C):
|
||||||
|
pass
|
||||||
|
|
||||||
|
If you have specified a module in the inheritance diagram like this::
|
||||||
|
|
||||||
|
.. inheritance-diagram:: dummy.test
|
||||||
|
:top-classes: dummy.test.B, dummy.test.C
|
||||||
|
|
||||||
|
any base classes which are ancestors to ``top-classes`` and are also defined
|
||||||
|
in the same module will be rendered as stand alone nodes. In this example
|
||||||
|
class A will be rendered as stand alone node in the graph. This is a known
|
||||||
|
issue due to how this extension works internally.
|
||||||
|
|
||||||
|
If you don't want class A (or any other ancestors) to be visible then specify
|
||||||
|
only the classes you would like to generate the diagram for like this::
|
||||||
|
|
||||||
|
.. inheritance-diagram:: dummy.test.D dummy.test.E dummy.test.F
|
||||||
|
:top-classes: dummy.test.B, dummy.test.C
|
||||||
|
|
||||||
|
.. versionchanged:: 1.7
|
||||||
|
Added ``top-classes`` option to limit the scope of inheritance graphs.
|
||||||
|
|
||||||
New config values are:
|
New config values are:
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ repository. It is open for anyone who wants to maintain an extension
|
|||||||
publicly; just send a short message asking for write permissions.
|
publicly; just send a short message asking for write permissions.
|
||||||
|
|
||||||
There are also several extensions hosted elsewhere. The `Sphinx extension
|
There are also several extensions hosted elsewhere. The `Sphinx extension
|
||||||
survey <http://sphinxext-survey.readthedocs.org/en/latest/>`__ contains a
|
survey <https://sphinxext-survey.readthedocs.io/>`__ contains a
|
||||||
comprehensive list.
|
comprehensive list.
|
||||||
|
|
||||||
If you write an extension that you think others will find useful or you think
|
If you write an extension that you think others will find useful or you think
|
||||||
|
@ -15,6 +15,7 @@ Builder API
|
|||||||
|
|
||||||
.. autoattribute:: name
|
.. autoattribute:: name
|
||||||
.. autoattribute:: format
|
.. autoattribute:: format
|
||||||
|
.. autoattribute:: epilog
|
||||||
.. autoattribute:: supported_image_types
|
.. autoattribute:: supported_image_types
|
||||||
|
|
||||||
These methods are predefined and will be called from the application:
|
These methods are predefined and will be called from the application:
|
||||||
|
@ -117,12 +117,30 @@ Both APIs parse the content into a given node. They are used like this::
|
|||||||
|
|
||||||
node = docutils.nodes.paragraph()
|
node = docutils.nodes.paragraph()
|
||||||
# either
|
# either
|
||||||
from sphinx.ext.autodoc import AutodocReporter
|
|
||||||
self.state.memo.reporter = AutodocReporter(self.result, self.state.memo.reporter) # override reporter to avoid errors from "include" directive
|
|
||||||
nested_parse_with_titles(self.state, self.result, node)
|
nested_parse_with_titles(self.state, self.result, node)
|
||||||
# or
|
# or
|
||||||
self.state.nested_parse(self.result, 0, node)
|
self.state.nested_parse(self.result, 0, node)
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
``sphinx.util.docutils.switch_source_input()`` allows to change a target file
|
||||||
|
during nested_parse. It is useful to mixed contents. For example, ``sphinx.
|
||||||
|
ext.autodoc`` uses it to parse docstrings::
|
||||||
|
|
||||||
|
from sphinx.util.docutils import switch_source_input
|
||||||
|
|
||||||
|
# Switch source_input between parsing content.
|
||||||
|
# Inside this context, all parsing errors and warnings are reported as
|
||||||
|
# happened in new source_input (in this case, ``self.result``).
|
||||||
|
with switch_source_input(self.state, self.result):
|
||||||
|
node = docutils.nodes.paragraph()
|
||||||
|
self.state.nested_parse(self.result, 0, node)
|
||||||
|
|
||||||
|
.. 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()``.
|
||||||
|
|
||||||
If you don't need the wrapping node, you can use any concrete node type and
|
If you don't need the wrapping node, you can use any concrete node type and
|
||||||
return ``node.children`` from the Directive.
|
return ``node.children`` from the Directive.
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ Read the Docs
|
|||||||
Sphinx. They will host sphinx documentation, along with supporting a number
|
Sphinx. They will host sphinx documentation, along with supporting a number
|
||||||
of other features including version support, PDF generation, and more. The
|
of other features including version support, PDF generation, and more. The
|
||||||
`Getting Started
|
`Getting Started
|
||||||
<http://read-the-docs.readthedocs.org/en/latest/getting_started.html>`_
|
<https://read-the-docs.readthedocs.io/en/latest/getting_started.html>`_
|
||||||
guide is a good place to start.
|
guide is a good place to start.
|
||||||
|
|
||||||
Epydoc
|
Epydoc
|
||||||
|
@ -3,7 +3,7 @@ Introduction
|
|||||||
|
|
||||||
This is the documentation for the Sphinx documentation builder. Sphinx is a
|
This is the documentation for the Sphinx documentation builder. Sphinx is a
|
||||||
tool that translates a set of reStructuredText_ source files into various output
|
tool that translates a set of reStructuredText_ source files into various output
|
||||||
formats, automatically producing cross-references, indices etc. That is, if
|
formats, automatically producing cross-references, indices, etc. That is, if
|
||||||
you have a directory containing a bunch of reST-formatted documents (and
|
you have a directory containing a bunch of reST-formatted documents (and
|
||||||
possibly subdirectories of docs in there as well), Sphinx can generate a
|
possibly subdirectories of docs in there as well), Sphinx can generate a
|
||||||
nicely-organized arrangement of HTML files (in some other directory) for easy
|
nicely-organized arrangement of HTML files (in some other directory) for easy
|
||||||
@ -17,7 +17,7 @@ docs have a look at `Epydoc <http://epydoc.sourceforge.net/>`_, which also
|
|||||||
understands reST.
|
understands reST.
|
||||||
|
|
||||||
For a great "introduction" to writing docs in general -- the whys and hows, see
|
For a great "introduction" to writing docs in general -- the whys and hows, see
|
||||||
also `Write the docs <http://write-the-docs.readthedocs.org/>`_, written by Eric
|
also `Write the docs <https://write-the-docs.readthedocs.io/>`_, written by Eric
|
||||||
Holscher.
|
Holscher.
|
||||||
|
|
||||||
.. _rinohtype: https://github.com/brechtm/rinohtype
|
.. _rinohtype: https://github.com/brechtm/rinohtype
|
||||||
@ -38,7 +38,7 @@ to reStructuredText/Sphinx from other documentation systems.
|
|||||||
code to convert Python-doc-style LaTeX markup to Sphinx reST.
|
code to convert Python-doc-style LaTeX markup to Sphinx reST.
|
||||||
|
|
||||||
* Marcin Wojdyr has written a script to convert Docbook to reST with Sphinx
|
* Marcin Wojdyr has written a script to convert Docbook to reST with Sphinx
|
||||||
markup; it is at `Google Code <https://github.com/wojdyr/db2rst>`_.
|
markup; it is at `GitHub <https://github.com/wojdyr/db2rst>`_.
|
||||||
|
|
||||||
* Christophe de Vienne wrote a tool to convert from Open/LibreOffice documents
|
* Christophe de Vienne wrote a tool to convert from Open/LibreOffice documents
|
||||||
to Sphinx: `odt2sphinx <https://pypi.python.org/pypi/odt2sphinx/>`_.
|
to Sphinx: `odt2sphinx <https://pypi.python.org/pypi/odt2sphinx/>`_.
|
||||||
|
@ -355,7 +355,8 @@ in a different style:
|
|||||||
.. rst:role:: manpage
|
.. rst:role:: manpage
|
||||||
|
|
||||||
A reference to a Unix manual page including the section,
|
A reference to a Unix manual page including the section,
|
||||||
e.g. ``:manpage:`ls(1)```.
|
e.g. ``:manpage:`ls(1)```. Creates a hyperlink to an external site
|
||||||
|
rendering the manpage if :confval:`manpages_url` is defined.
|
||||||
|
|
||||||
.. rst:role:: menuselection
|
.. rst:role:: menuselection
|
||||||
|
|
||||||
|
@ -323,6 +323,11 @@ following directive exists:
|
|||||||
Sphinx's merged cells interact well with ``p{width}``, ``\X{a}{b}``, ``Y{f}``
|
Sphinx's merged cells interact well with ``p{width}``, ``\X{a}{b}``, ``Y{f}``
|
||||||
and tabulary's columns.
|
and tabulary's columns.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
:rst:dir:`tabularcolumns` conflicts with ``:widths:`` option of table
|
||||||
|
directives. If both are specified, ``:widths:`` option will be ignored.
|
||||||
|
|
||||||
Math
|
Math
|
||||||
----
|
----
|
||||||
|
|
||||||
|
@ -44,6 +44,10 @@ incremental = True
|
|||||||
check_untyped_defs = True
|
check_untyped_defs = True
|
||||||
warn_unused_ignores = True
|
warn_unused_ignores = True
|
||||||
|
|
||||||
|
[tool:pytest]
|
||||||
|
filterwarnings =
|
||||||
|
ignore::DeprecationWarning:docutils.io
|
||||||
|
|
||||||
[coverage:run]
|
[coverage:run]
|
||||||
branch = True
|
branch = True
|
||||||
source = sphinx
|
source = sphinx
|
||||||
|
1
setup.py
1
setup.py
@ -26,6 +26,7 @@ requires = [
|
|||||||
'imagesize',
|
'imagesize',
|
||||||
'requests>=2.0.0',
|
'requests>=2.0.0',
|
||||||
'setuptools',
|
'setuptools',
|
||||||
|
'packaging',
|
||||||
'sphinxcontrib-websupport',
|
'sphinxcontrib-websupport',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -157,10 +157,6 @@ class Sphinx(object):
|
|||||||
# status code for command-line application
|
# status code for command-line application
|
||||||
self.statuscode = 0
|
self.statuscode = 0
|
||||||
|
|
||||||
if not path.isdir(outdir):
|
|
||||||
logger.info('making output directory...')
|
|
||||||
ensuredir(outdir)
|
|
||||||
|
|
||||||
# read config
|
# read config
|
||||||
self.tags = Tags(tags)
|
self.tags = Tags(tags)
|
||||||
self.config = Config(confdir, CONFIG_FILENAME,
|
self.config = Config(confdir, CONFIG_FILENAME,
|
||||||
@ -197,6 +193,10 @@ class Sphinx(object):
|
|||||||
# preload builder module (before init config values)
|
# preload builder module (before init config values)
|
||||||
self.preload_builder(buildername)
|
self.preload_builder(buildername)
|
||||||
|
|
||||||
|
if not path.isdir(outdir):
|
||||||
|
logger.info('making output directory...')
|
||||||
|
ensuredir(outdir)
|
||||||
|
|
||||||
# the config file itself can be an extension
|
# the config file itself can be an extension
|
||||||
if self.config.setup:
|
if self.config.setup:
|
||||||
self._setting_up_extension = ['conf.py']
|
self._setting_up_extension = ['conf.py']
|
||||||
@ -338,6 +338,13 @@ class Sphinx(object):
|
|||||||
(status, self._warncount)))
|
(status, self._warncount)))
|
||||||
else:
|
else:
|
||||||
logger.info(bold(__('build %s.') % status))
|
logger.info(bold(__('build %s.') % status))
|
||||||
|
|
||||||
|
if self.statuscode == 0 and self.builder.epilog:
|
||||||
|
logger.info('')
|
||||||
|
logger.info(self.builder.epilog % {
|
||||||
|
'outdir': path.relpath(self.outdir),
|
||||||
|
'project': self.config.project
|
||||||
|
})
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
# delete the saved env to force a fresh build next time
|
# delete the saved env to force a fresh build next time
|
||||||
envfile = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
|
envfile = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
|
||||||
@ -642,15 +649,14 @@ class Sphinx(object):
|
|||||||
def add_autodocumenter(self, cls):
|
def add_autodocumenter(self, cls):
|
||||||
# type: (Any) -> None
|
# type: (Any) -> None
|
||||||
logger.debug('[app] adding autodocumenter: %r', cls)
|
logger.debug('[app] adding autodocumenter: %r', cls)
|
||||||
from sphinx.ext import autodoc
|
from sphinx.ext.autodoc.directive import AutodocDirective
|
||||||
autodoc.add_documenter(cls)
|
self.registry.add_documenter(cls.objtype, cls)
|
||||||
self.add_directive('auto' + cls.objtype, autodoc.AutoDirective)
|
self.add_directive('auto' + cls.objtype, AutodocDirective)
|
||||||
|
|
||||||
def add_autodoc_attrgetter(self, type, getter):
|
def add_autodoc_attrgetter(self, typ, getter):
|
||||||
# type: (Any, Callable) -> None
|
# type: (Type, Callable[[Any, unicode, Any], Any]) -> None
|
||||||
logger.debug('[app] adding autodoc attrgetter: %r', (type, getter))
|
logger.debug('[app] adding autodoc attrgetter: %r', (typ, getter))
|
||||||
from sphinx.ext import autodoc
|
self.registry.add_autodoc_attrgetter(typ, getter)
|
||||||
autodoc.AutoDirective._special_attrgetters[type] = getter
|
|
||||||
|
|
||||||
def add_search_language(self, cls):
|
def add_search_language(self, cls):
|
||||||
# type: (Any) -> None
|
# type: (Any) -> None
|
||||||
|
@ -54,6 +54,11 @@ class Builder(object):
|
|||||||
name = '' # type: unicode
|
name = '' # type: unicode
|
||||||
#: The builder's output format, or '' if no document output is produced.
|
#: The builder's output format, or '' if no document output is produced.
|
||||||
format = '' # type: unicode
|
format = '' # type: unicode
|
||||||
|
#: The message emitted upon successful build completion. This can be a
|
||||||
|
#: printf-style template string with the following keys: ``outdir``,
|
||||||
|
#: ``project``
|
||||||
|
epilog = '' # type: unicode
|
||||||
|
|
||||||
# default translator class for the builder. This will be overrided by
|
# default translator class for the builder. This will be overrided by
|
||||||
# ``app.set_translator()``.
|
# ``app.set_translator()``.
|
||||||
default_translator_class = None # type: nodes.NodeVisitor
|
default_translator_class = None # type: nodes.NodeVisitor
|
||||||
|
@ -75,6 +75,10 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
|
|||||||
on the ``hiutil`` command line tool.
|
on the ``hiutil`` command line tool.
|
||||||
"""
|
"""
|
||||||
name = 'applehelp'
|
name = 'applehelp'
|
||||||
|
epilog = ('The help book is in %(outdir)s.\n'
|
||||||
|
'Note that won\'t be able to view it unless you put it in '
|
||||||
|
'~/Library/Documentation/Help or install it in your application '
|
||||||
|
'bundle.')
|
||||||
|
|
||||||
# don't copy the reST source
|
# don't copy the reST source
|
||||||
copysource = False
|
copysource = False
|
||||||
|
@ -38,6 +38,7 @@ class ChangesBuilder(Builder):
|
|||||||
Write a summary with all versionadded/changed directives.
|
Write a summary with all versionadded/changed directives.
|
||||||
"""
|
"""
|
||||||
name = 'changes'
|
name = 'changes'
|
||||||
|
epilog = 'The overview file is in %(outdir)s.'
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
|
@ -43,6 +43,10 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
|
|||||||
Builder that also outputs GNOME Devhelp file.
|
Builder that also outputs GNOME Devhelp file.
|
||||||
"""
|
"""
|
||||||
name = 'devhelp'
|
name = 'devhelp'
|
||||||
|
epilog = ('To view the help file:\n'
|
||||||
|
'$ mkdir -p $HOME/.local/share/devhelp/%(project)s\n'
|
||||||
|
'$ ln -s %(outdir)s $HOME/.local/share/devhelp/%(project)s\n'
|
||||||
|
'$ devhelp')
|
||||||
|
|
||||||
# don't copy the reST source
|
# don't copy the reST source
|
||||||
copysource = False
|
copysource = False
|
||||||
|
@ -21,6 +21,8 @@ if False:
|
|||||||
|
|
||||||
class DummyBuilder(Builder):
|
class DummyBuilder(Builder):
|
||||||
name = 'dummy'
|
name = 'dummy'
|
||||||
|
epilog = 'The dummy builder generates no files.'
|
||||||
|
|
||||||
allow_parallel = True
|
allow_parallel = True
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
|
@ -63,6 +63,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
|
|||||||
an epub file.
|
an epub file.
|
||||||
"""
|
"""
|
||||||
name = 'epub'
|
name = 'epub'
|
||||||
|
epilog = 'The ePub file is in %(outdir)s.'
|
||||||
|
|
||||||
supported_remote_images = False
|
supported_remote_images = False
|
||||||
template_dir = path.join(package_dir, 'templates', 'epub3')
|
template_dir = path.join(package_dir, 'templates', 'epub3')
|
||||||
|
@ -214,6 +214,7 @@ class MessageCatalogBuilder(I18nBuilder):
|
|||||||
Builds gettext-style message catalogs (.pot files).
|
Builds gettext-style message catalogs (.pot files).
|
||||||
"""
|
"""
|
||||||
name = 'gettext'
|
name = 'gettext'
|
||||||
|
epilog = 'The message catalogs are in %(outdir)s.'
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
|
@ -153,6 +153,8 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
"""
|
"""
|
||||||
name = 'html'
|
name = 'html'
|
||||||
format = 'html'
|
format = 'html'
|
||||||
|
epilog = 'The HTML pages are in %(outdir)s.'
|
||||||
|
|
||||||
copysource = True
|
copysource = True
|
||||||
allow_parallel = True
|
allow_parallel = True
|
||||||
out_suffix = '.html'
|
out_suffix = '.html'
|
||||||
@ -1066,6 +1068,8 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
|||||||
HTML page.
|
HTML page.
|
||||||
"""
|
"""
|
||||||
name = 'singlehtml'
|
name = 'singlehtml'
|
||||||
|
epilog = 'The HTML page is in %(outdir)s.'
|
||||||
|
|
||||||
copysource = False
|
copysource = False
|
||||||
|
|
||||||
def get_outdated_docs(self): # type: ignore
|
def get_outdated_docs(self): # type: ignore
|
||||||
@ -1328,12 +1332,14 @@ class PickleHTMLBuilder(SerializingHTMLBuilder):
|
|||||||
"""
|
"""
|
||||||
A Builder that dumps the generated HTML into pickle files.
|
A Builder that dumps the generated HTML into pickle files.
|
||||||
"""
|
"""
|
||||||
|
name = 'pickle'
|
||||||
|
epilog = 'You can now process the pickle files in %(outdir)s.'
|
||||||
|
|
||||||
implementation = pickle
|
implementation = pickle
|
||||||
implementation_dumps_unicode = False
|
implementation_dumps_unicode = False
|
||||||
additional_dump_args = (pickle.HIGHEST_PROTOCOL,)
|
additional_dump_args = (pickle.HIGHEST_PROTOCOL,)
|
||||||
indexer_format = pickle
|
indexer_format = pickle
|
||||||
indexer_dumps_unicode = False
|
indexer_dumps_unicode = False
|
||||||
name = 'pickle'
|
|
||||||
out_suffix = '.fpickle'
|
out_suffix = '.fpickle'
|
||||||
globalcontext_filename = 'globalcontext.pickle'
|
globalcontext_filename = 'globalcontext.pickle'
|
||||||
searchindex_filename = 'searchindex.pickle'
|
searchindex_filename = 'searchindex.pickle'
|
||||||
@ -1347,11 +1353,13 @@ class JSONHTMLBuilder(SerializingHTMLBuilder):
|
|||||||
"""
|
"""
|
||||||
A builder that dumps the generated HTML into JSON files.
|
A builder that dumps the generated HTML into JSON files.
|
||||||
"""
|
"""
|
||||||
|
name = 'json'
|
||||||
|
epilog = 'You can now process the JSON files in %(outdir)s.'
|
||||||
|
|
||||||
implementation = jsonimpl
|
implementation = jsonimpl
|
||||||
implementation_dumps_unicode = True
|
implementation_dumps_unicode = True
|
||||||
indexer_format = jsonimpl
|
indexer_format = jsonimpl
|
||||||
indexer_dumps_unicode = True
|
indexer_dumps_unicode = True
|
||||||
name = 'json'
|
|
||||||
out_suffix = '.fjson'
|
out_suffix = '.fjson'
|
||||||
globalcontext_filename = 'globalcontext.json'
|
globalcontext_filename = 'globalcontext.json'
|
||||||
searchindex_filename = 'searchindex.json'
|
searchindex_filename = 'searchindex.json'
|
||||||
|
@ -174,6 +174,8 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
|
|||||||
index files. Adapted from the original Doc/tools/prechm.py.
|
index files. Adapted from the original Doc/tools/prechm.py.
|
||||||
"""
|
"""
|
||||||
name = 'htmlhelp'
|
name = 'htmlhelp'
|
||||||
|
epilog = ('You can now run HTML Help Workshop with the .htp file in '
|
||||||
|
'%(outdir)s.')
|
||||||
|
|
||||||
# don't copy the reST source
|
# don't copy the reST source
|
||||||
copysource = False
|
copysource = False
|
||||||
|
@ -49,6 +49,12 @@ class LaTeXBuilder(Builder):
|
|||||||
"""
|
"""
|
||||||
name = 'latex'
|
name = 'latex'
|
||||||
format = 'latex'
|
format = 'latex'
|
||||||
|
epilog = 'The LaTeX files are in %(outdir)s.'
|
||||||
|
if os.name == 'posix':
|
||||||
|
epilog += ("\nRun 'make' in that directory to run these through "
|
||||||
|
"(pdf)latex\n"
|
||||||
|
"(use `make latexpdf' here to do that automatically).")
|
||||||
|
|
||||||
supported_image_types = ['application/pdf', 'image/png', 'image/jpeg']
|
supported_image_types = ['application/pdf', 'image/png', 'image/jpeg']
|
||||||
supported_remote_images = False
|
supported_remote_images = False
|
||||||
default_translator_class = LaTeXTranslator
|
default_translator_class = LaTeXTranslator
|
||||||
|
@ -90,6 +90,8 @@ class CheckExternalLinksBuilder(Builder):
|
|||||||
Checks for broken external links.
|
Checks for broken external links.
|
||||||
"""
|
"""
|
||||||
name = 'linkcheck'
|
name = 'linkcheck'
|
||||||
|
epilog = ('Look for any errors in the above output or in '
|
||||||
|
'%(outdir)s/output.txt')
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
|
@ -40,6 +40,8 @@ class ManualPageBuilder(Builder):
|
|||||||
"""
|
"""
|
||||||
name = 'man'
|
name = 'man'
|
||||||
format = 'man'
|
format = 'man'
|
||||||
|
epilog = 'The manual pages are in %(outdir)s.'
|
||||||
|
|
||||||
default_translator_class = ManualPageTranslator
|
default_translator_class = ManualPageTranslator
|
||||||
supported_image_types = [] # type: List[unicode]
|
supported_image_types = [] # type: List[unicode]
|
||||||
|
|
||||||
|
@ -108,6 +108,11 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
|
|||||||
Builder that also outputs Qt help project, contents and index files.
|
Builder that also outputs Qt help project, contents and index files.
|
||||||
"""
|
"""
|
||||||
name = 'qthelp'
|
name = 'qthelp'
|
||||||
|
epilog = ('You can now run "qcollectiongenerator" with the .qhcp '
|
||||||
|
'project file in %(outdir)s, like this:\n'
|
||||||
|
'$ qcollectiongenerator %(outdir)s/%(project)s.qhcp\n'
|
||||||
|
'To view the help file:\n'
|
||||||
|
'$ assistant -collectionFile %(outdir)s/%(project)s.qhc')
|
||||||
|
|
||||||
# don't copy the reST source
|
# don't copy the reST source
|
||||||
copysource = False
|
copysource = False
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
from os import path
|
from os import path
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
@ -97,6 +98,12 @@ class TexinfoBuilder(Builder):
|
|||||||
"""
|
"""
|
||||||
name = 'texinfo'
|
name = 'texinfo'
|
||||||
format = 'texinfo'
|
format = 'texinfo'
|
||||||
|
epilog = 'The Texinfo files are in %(outdir)s.'
|
||||||
|
if os.name == 'posix':
|
||||||
|
epilog += ("\nRun 'make' in that directory to run these through "
|
||||||
|
"makeinfo\n"
|
||||||
|
"(use 'make info' here to do that automatically).")
|
||||||
|
|
||||||
supported_image_types = ['image/png', 'image/jpeg',
|
supported_image_types = ['image/png', 'image/jpeg',
|
||||||
'image/gif']
|
'image/gif']
|
||||||
default_translator_class = TexinfoTranslator
|
default_translator_class = TexinfoTranslator
|
||||||
|
@ -21,7 +21,7 @@ from sphinx.writers.text import TextWriter, TextTranslator
|
|||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Any, Dict, Iterator, Set # NOQA
|
from typing import Any, Dict, Iterator, Set, Tuple # NOQA
|
||||||
from docutils import nodes # NOQA
|
from docutils import nodes # NOQA
|
||||||
from sphinx.application import Sphinx # NOQA
|
from sphinx.application import Sphinx # NOQA
|
||||||
|
|
||||||
@ -31,6 +31,8 @@ logger = logging.getLogger(__name__)
|
|||||||
class TextBuilder(Builder):
|
class TextBuilder(Builder):
|
||||||
name = 'text'
|
name = 'text'
|
||||||
format = 'text'
|
format = 'text'
|
||||||
|
epilog = 'The text files are in %(outdir)s.'
|
||||||
|
|
||||||
out_suffix = '.txt'
|
out_suffix = '.txt'
|
||||||
allow_parallel = True
|
allow_parallel = True
|
||||||
default_translator_class = TextTranslator
|
default_translator_class = TextTranslator
|
||||||
@ -39,7 +41,8 @@ class TextBuilder(Builder):
|
|||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
pass
|
# section numbers for headings in the currently visited document
|
||||||
|
self.secnumbers = {} # type: Dict[unicode, Tuple[int, ...]]
|
||||||
|
|
||||||
def get_outdated_docs(self):
|
def get_outdated_docs(self):
|
||||||
# type: () -> Iterator[unicode]
|
# type: () -> Iterator[unicode]
|
||||||
@ -72,6 +75,7 @@ class TextBuilder(Builder):
|
|||||||
def write_doc(self, docname, doctree):
|
def write_doc(self, docname, doctree):
|
||||||
# type: (unicode, nodes.Node) -> None
|
# type: (unicode, nodes.Node) -> None
|
||||||
self.current_docname = docname
|
self.current_docname = docname
|
||||||
|
self.secnumbers = self.env.toc_secnumbers.get(docname, {})
|
||||||
destination = StringOutput(encoding='utf-8')
|
destination = StringOutput(encoding='utf-8')
|
||||||
self.writer.write(doctree, destination)
|
self.writer.write(doctree, destination)
|
||||||
outfilename = path.join(self.outdir, os_path(docname) + self.out_suffix)
|
outfilename = path.join(self.outdir, os_path(docname) + self.out_suffix)
|
||||||
@ -93,6 +97,8 @@ def setup(app):
|
|||||||
|
|
||||||
app.add_config_value('text_sectionchars', '*=-~"+`', 'env')
|
app.add_config_value('text_sectionchars', '*=-~"+`', 'env')
|
||||||
app.add_config_value('text_newlines', 'unix', 'env')
|
app.add_config_value('text_newlines', 'unix', 'env')
|
||||||
|
app.add_config_value('text_add_secnumbers', True, 'env')
|
||||||
|
app.add_config_value('text_secnumber_suffix', '. ', 'env')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'version': 'builtin',
|
'version': 'builtin',
|
||||||
|
@ -35,6 +35,8 @@ class XMLBuilder(Builder):
|
|||||||
"""
|
"""
|
||||||
name = 'xml'
|
name = 'xml'
|
||||||
format = 'xml'
|
format = 'xml'
|
||||||
|
epilog = 'The XML files are in %(outdir)s.'
|
||||||
|
|
||||||
out_suffix = '.xml'
|
out_suffix = '.xml'
|
||||||
allow_parallel = True
|
allow_parallel = True
|
||||||
|
|
||||||
@ -108,6 +110,8 @@ class PseudoXMLBuilder(XMLBuilder):
|
|||||||
"""
|
"""
|
||||||
name = 'pseudoxml'
|
name = 'pseudoxml'
|
||||||
format = 'pseudoxml'
|
format = 'pseudoxml'
|
||||||
|
epilog = 'The pseudo-XML files are in %(outdir)s.'
|
||||||
|
|
||||||
out_suffix = '.pseudoxml'
|
out_suffix = '.pseudoxml'
|
||||||
|
|
||||||
_writer_class = PseudoXMLWriter
|
_writer_class = PseudoXMLWriter
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
import traceback
|
||||||
from os import path, getenv
|
from os import path, getenv
|
||||||
|
|
||||||
from six import PY2, PY3, iteritems, string_types, binary_type, text_type, integer_types
|
from six import PY2, PY3, iteritems, string_types, binary_type, text_type, integer_types
|
||||||
@ -35,6 +36,7 @@ copyright_year_re = re.compile(r'^((\d{4}-)?)(\d{4})(?=[ ,])')
|
|||||||
CONFIG_SYNTAX_ERROR = "There is a syntax error in your configuration file: %s"
|
CONFIG_SYNTAX_ERROR = "There is a syntax error in your configuration file: %s"
|
||||||
if PY3:
|
if PY3:
|
||||||
CONFIG_SYNTAX_ERROR += "\nDid you change the syntax from 2.x to 3.x?"
|
CONFIG_SYNTAX_ERROR += "\nDid you change the syntax from 2.x to 3.x?"
|
||||||
|
CONFIG_ERROR = "There is a programable error in your configuration file:\n\n%s"
|
||||||
CONFIG_EXIT_ERROR = "The configuration file (or one of the modules it imports) " \
|
CONFIG_EXIT_ERROR = "The configuration file (or one of the modules it imports) " \
|
||||||
"called sys.exit()"
|
"called sys.exit()"
|
||||||
CONFIG_ENUM_WARNING = "The config value `{name}` has to be a one of {candidates}, " \
|
CONFIG_ENUM_WARNING = "The config value `{name}` has to be a one of {candidates}, " \
|
||||||
@ -123,6 +125,7 @@ class Config(object):
|
|||||||
primary_domain = ('py', 'env', [NoneType]),
|
primary_domain = ('py', 'env', [NoneType]),
|
||||||
needs_sphinx = (None, None, string_classes),
|
needs_sphinx = (None, None, string_classes),
|
||||||
needs_extensions = ({}, None),
|
needs_extensions = ({}, None),
|
||||||
|
manpages_url = (None, 'env'),
|
||||||
nitpicky = (False, None),
|
nitpicky = (False, None),
|
||||||
nitpick_ignore = ([], None),
|
nitpick_ignore = ([], None),
|
||||||
numfig = (False, 'env'),
|
numfig = (False, 'env'),
|
||||||
@ -135,6 +138,11 @@ class Config(object):
|
|||||||
|
|
||||||
tls_verify = (True, 'env'),
|
tls_verify = (True, 'env'),
|
||||||
tls_cacerts = (None, 'env'),
|
tls_cacerts = (None, 'env'),
|
||||||
|
smartquotes = (True, 'env'),
|
||||||
|
smartquotes_action = ('qDe', 'env'),
|
||||||
|
smartquotes_excludes = ({'languages': ['ja'],
|
||||||
|
'builders': ['man', 'text']},
|
||||||
|
'env'),
|
||||||
) # type: Dict[unicode, Tuple]
|
) # type: Dict[unicode, Tuple]
|
||||||
|
|
||||||
def __init__(self, dirname, filename, overrides, tags):
|
def __init__(self, dirname, filename, overrides, tags):
|
||||||
@ -155,6 +163,8 @@ class Config(object):
|
|||||||
raise ConfigError(CONFIG_SYNTAX_ERROR % err)
|
raise ConfigError(CONFIG_SYNTAX_ERROR % err)
|
||||||
except SystemExit:
|
except SystemExit:
|
||||||
raise ConfigError(CONFIG_EXIT_ERROR)
|
raise ConfigError(CONFIG_EXIT_ERROR)
|
||||||
|
except Exception:
|
||||||
|
raise ConfigError(CONFIG_ERROR % traceback.format_exc())
|
||||||
|
|
||||||
self._raw_config = config
|
self._raw_config = config
|
||||||
# these two must be preinitialized because extensions can add their
|
# these two must be preinitialized because extensions can add their
|
||||||
|
@ -959,12 +959,18 @@ class StandardDomain(Domain):
|
|||||||
|
|
||||||
def get_full_qualified_name(self, node):
|
def get_full_qualified_name(self, node):
|
||||||
# type: (nodes.Node) -> unicode
|
# type: (nodes.Node) -> unicode
|
||||||
|
if node.get('reftype') == 'option':
|
||||||
progname = node.get('std:program')
|
progname = node.get('std:program')
|
||||||
target = node.get('reftarget')
|
command = ws_re.split(node.get('reftarget'))
|
||||||
if progname is None or target is None:
|
if progname:
|
||||||
|
command.insert(0, progname)
|
||||||
|
option = command.pop()
|
||||||
|
if command:
|
||||||
|
return '.'.join(['-'.join(command), option])
|
||||||
|
else:
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return '.'.join([progname, target])
|
return None
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
|
@ -23,8 +23,7 @@ from collections import defaultdict
|
|||||||
from six import BytesIO, itervalues, class_types, next
|
from six import BytesIO, itervalues, class_types, next
|
||||||
from six.moves import cPickle as pickle
|
from six.moves import cPickle as pickle
|
||||||
|
|
||||||
from docutils.utils import Reporter, get_source_line, normalize_language_tag
|
from docutils.utils import Reporter, get_source_line
|
||||||
from docutils.utils.smartquotes import smartchars
|
|
||||||
from docutils.frontend import OptionParser
|
from docutils.frontend import OptionParser
|
||||||
|
|
||||||
from sphinx import addnodes, versioning
|
from sphinx import addnodes, versioning
|
||||||
@ -47,7 +46,7 @@ from sphinx.environment.adapters.toctree import TocTree
|
|||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Any, Callable, Dict, IO, Iterator, List, Pattern, Set, Tuple, Type, Union # NOQA
|
from typing import Any, Callable, Dict, IO, Iterator, List, Pattern, Set, Tuple, Type, Union, Generator # NOQA
|
||||||
from docutils import nodes # NOQA
|
from docutils import nodes # NOQA
|
||||||
from sphinx.application import Sphinx # NOQA
|
from sphinx.application import Sphinx # NOQA
|
||||||
from sphinx.builders import Builder # NOQA
|
from sphinx.builders import Builder # NOQA
|
||||||
@ -66,6 +65,7 @@ default_settings = {
|
|||||||
'sectsubtitle_xform': False,
|
'sectsubtitle_xform': False,
|
||||||
'halt_level': 5,
|
'halt_level': 5,
|
||||||
'file_insertion_enabled': True,
|
'file_insertion_enabled': True,
|
||||||
|
'smartquotes_locales': [],
|
||||||
}
|
}
|
||||||
|
|
||||||
# This is increased every time an environment attribute is added
|
# This is increased every time an environment attribute is added
|
||||||
@ -642,17 +642,10 @@ class BuildEnvironment(object):
|
|||||||
self.config.trim_footnote_reference_space
|
self.config.trim_footnote_reference_space
|
||||||
self.settings['gettext_compact'] = self.config.gettext_compact
|
self.settings['gettext_compact'] = self.config.gettext_compact
|
||||||
|
|
||||||
language = self.config.language or 'en'
|
self.settings['language_code'] = self.config.language or 'en'
|
||||||
self.settings['language_code'] = language
|
|
||||||
if 'smart_quotes' not in self.settings:
|
|
||||||
self.settings['smart_quotes'] = True
|
|
||||||
|
|
||||||
# confirm selected language supports smart_quotes or not
|
# Allow to disable by 3rd party extension (workaround)
|
||||||
for tag in normalize_language_tag(language):
|
self.settings.setdefault('smart_quotes', True)
|
||||||
if tag in smartchars.quotes:
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
self.settings['smart_quotes'] = False
|
|
||||||
|
|
||||||
def read_doc(self, docname, app=None):
|
def read_doc(self, docname, app=None):
|
||||||
# type: (unicode, Sphinx) -> None
|
# type: (unicode, Sphinx) -> None
|
||||||
|
@ -117,7 +117,11 @@ def create_package_file(root, master_package, subroot, py_files, opts, subs, is_
|
|||||||
text += '\n'
|
text += '\n'
|
||||||
|
|
||||||
# build a list of directories that are szvpackages (contain an INITPY file)
|
# build a list of directories that are szvpackages (contain an INITPY file)
|
||||||
subs = [sub for sub in subs if path.isfile(path.join(root, sub, INITPY))]
|
# and also checks the INITPY file is not empty, or there are other python
|
||||||
|
# source files in that folder.
|
||||||
|
# (depending on settings - but shall_skip() takes care of that)
|
||||||
|
subs = [sub for sub in subs if not
|
||||||
|
shall_skip(path.join(root, sub, INITPY), opts)]
|
||||||
# if there are some package directories, add a TOC for theses subpackages
|
# if there are some package directories, add a TOC for theses subpackages
|
||||||
if subs:
|
if subs:
|
||||||
text += format_heading(2, 'Subpackages')
|
text += format_heading(2, 'Subpackages')
|
||||||
|
@ -14,17 +14,15 @@
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import inspect
|
import inspect
|
||||||
import traceback
|
import warnings
|
||||||
|
|
||||||
from six import PY2, iterkeys, iteritems, itervalues, text_type, class_types, string_types
|
from six import iteritems, itervalues, text_type, class_types, string_types
|
||||||
|
|
||||||
from docutils import nodes
|
|
||||||
from docutils.utils import assemble_option_dict
|
|
||||||
from docutils.parsers.rst import Directive
|
|
||||||
from docutils.statemachine import ViewList
|
from docutils.statemachine import ViewList
|
||||||
|
|
||||||
import sphinx
|
import sphinx
|
||||||
from sphinx.ext.autodoc.importer import mock, import_module
|
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||||
|
from sphinx.ext.autodoc.importer import mock, import_object, get_object_members
|
||||||
from sphinx.ext.autodoc.importer import _MockImporter # to keep compatibility # NOQA
|
from sphinx.ext.autodoc.importer import _MockImporter # to keep compatibility # NOQA
|
||||||
from sphinx.ext.autodoc.inspector import format_annotation, formatargspec # to keep compatibility # NOQA
|
from sphinx.ext.autodoc.inspector import format_annotation, formatargspec # to keep compatibility # NOQA
|
||||||
from sphinx.util import rpartition, force_decode
|
from sphinx.util import rpartition, force_decode
|
||||||
@ -32,21 +30,23 @@ from sphinx.locale import _
|
|||||||
from sphinx.pycode import ModuleAnalyzer, PycodeError
|
from sphinx.pycode import ModuleAnalyzer, PycodeError
|
||||||
from sphinx.application import ExtensionError
|
from sphinx.application import ExtensionError
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util.nodes import nested_parse_with_titles
|
|
||||||
from sphinx.util.inspect import Signature, isdescriptor, safe_getmembers, \
|
from sphinx.util.inspect import Signature, isdescriptor, safe_getmembers, \
|
||||||
safe_getattr, object_description, is_builtin_class_method, \
|
safe_getattr, object_description, is_builtin_class_method, \
|
||||||
isenumclass, isenumattribute, getdoc
|
isenumattribute, getdoc
|
||||||
from sphinx.util.docstrings import prepare_docstring
|
from sphinx.util.docstrings import prepare_docstring
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from types import ModuleType # NOQA
|
from types import ModuleType # NOQA
|
||||||
from typing import Any, Callable, Dict, Iterator, List, Sequence, Set, Tuple, Type, Union # NOQA
|
from typing import Any, Callable, Dict, Iterator, List, Sequence, Set, Tuple, Type, Union # NOQA
|
||||||
|
from docutils import nodes # NOQA
|
||||||
from docutils.utils import Reporter # NOQA
|
from docutils.utils import Reporter # NOQA
|
||||||
from sphinx.application import Sphinx # NOQA
|
from sphinx.application import Sphinx # NOQA
|
||||||
|
from sphinx.ext.autodoc.directive import DocumenterBridge # NOQA
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
# This type isn't exposed directly in any modules, but can be found
|
# This type isn't exposed directly in any modules, but can be found
|
||||||
# here in most Python versions
|
# here in most Python versions
|
||||||
MethodDescriptorType = type(type.__subclasses__)
|
MethodDescriptorType = type(type.__subclasses__)
|
||||||
@ -63,42 +63,11 @@ py_ext_sig_re = re.compile(
|
|||||||
''', re.VERBOSE)
|
''', re.VERBOSE)
|
||||||
|
|
||||||
|
|
||||||
class DefDict(dict):
|
|
||||||
"""A dict that returns a default on nonexisting keys."""
|
|
||||||
def __init__(self, default):
|
|
||||||
# type: (Any) -> None
|
|
||||||
dict.__init__(self)
|
|
||||||
self.default = default
|
|
||||||
|
|
||||||
def __getitem__(self, key):
|
|
||||||
# type: (Any) -> Any
|
|
||||||
try:
|
|
||||||
return dict.__getitem__(self, key)
|
|
||||||
except KeyError:
|
|
||||||
return self.default
|
|
||||||
|
|
||||||
def __bool__(self):
|
|
||||||
# type: () -> bool
|
|
||||||
# docutils check "if option_spec"
|
|
||||||
return True
|
|
||||||
__nonzero__ = __bool__ # for python2 compatibility
|
|
||||||
|
|
||||||
|
|
||||||
def identity(x):
|
def identity(x):
|
||||||
# type: (Any) -> Any
|
# type: (Any) -> Any
|
||||||
return x
|
return x
|
||||||
|
|
||||||
|
|
||||||
class Options(dict):
|
|
||||||
"""A dict/attribute hybrid that returns None on nonexisting keys."""
|
|
||||||
def __getattr__(self, name):
|
|
||||||
# type: (unicode) -> Any
|
|
||||||
try:
|
|
||||||
return self[name.replace('_', '-')]
|
|
||||||
except KeyError:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
ALL = object()
|
ALL = object()
|
||||||
INSTANCEATTR = object()
|
INSTANCEATTR = object()
|
||||||
|
|
||||||
@ -146,6 +115,9 @@ class AutodocReporter(object):
|
|||||||
"""
|
"""
|
||||||
def __init__(self, viewlist, reporter):
|
def __init__(self, viewlist, reporter):
|
||||||
# type: (ViewList, Reporter) -> None
|
# type: (ViewList, Reporter) -> None
|
||||||
|
warnings.warn('AutodocReporter is now deprecated. '
|
||||||
|
'Use sphinx.util.docutils.switch_source_input() instead.',
|
||||||
|
RemovedInSphinx20Warning)
|
||||||
self.viewlist = viewlist
|
self.viewlist = viewlist
|
||||||
self.reporter = reporter
|
self.reporter = reporter
|
||||||
|
|
||||||
@ -284,14 +256,10 @@ class Documenter(object):
|
|||||||
|
|
||||||
option_spec = {'noindex': bool_option} # type: Dict[unicode, Callable]
|
option_spec = {'noindex': bool_option} # type: Dict[unicode, Callable]
|
||||||
|
|
||||||
@staticmethod
|
def get_attr(self, obj, name, *defargs):
|
||||||
def get_attr(obj, name, *defargs):
|
|
||||||
# type: (Any, unicode, Any) -> Any
|
# type: (Any, unicode, Any) -> Any
|
||||||
"""getattr() override for types such as Zope interfaces."""
|
"""getattr() override for types such as Zope interfaces."""
|
||||||
for typ, func in iteritems(AutoDirective._special_attrgetters):
|
return autodoc_attrgetter(self.env.app, obj, name, *defargs)
|
||||||
if isinstance(obj, typ):
|
|
||||||
return func(obj, name, *defargs)
|
|
||||||
return safe_getattr(obj, name, *defargs)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def can_document_member(cls, member, membername, isattr, parent):
|
def can_document_member(cls, member, membername, isattr, parent):
|
||||||
@ -300,7 +268,7 @@ class Documenter(object):
|
|||||||
raise NotImplementedError('must be implemented in subclasses')
|
raise NotImplementedError('must be implemented in subclasses')
|
||||||
|
|
||||||
def __init__(self, directive, name, indent=u''):
|
def __init__(self, directive, name, indent=u''):
|
||||||
# type: (Directive, unicode, unicode) -> None
|
# type: (DocumenterBridge, unicode, unicode) -> None
|
||||||
self.directive = directive
|
self.directive = directive
|
||||||
self.env = directive.env
|
self.env = directive.env
|
||||||
self.options = directive.genopt
|
self.options = directive.genopt
|
||||||
@ -324,6 +292,12 @@ class Documenter(object):
|
|||||||
# the module analyzer to get at attribute docs, or None
|
# the module analyzer to get at attribute docs, or None
|
||||||
self.analyzer = None # type: Any
|
self.analyzer = None # type: Any
|
||||||
|
|
||||||
|
@property
|
||||||
|
def documenters(self):
|
||||||
|
# type: () -> Dict[unicode, Type[Documenter]]
|
||||||
|
"""Returns registered Documenter classes"""
|
||||||
|
return get_documenters(self.env.app)
|
||||||
|
|
||||||
def add_line(self, line, source, *lineno):
|
def add_line(self, line, source, *lineno):
|
||||||
# type: (unicode, unicode, int) -> None
|
# type: (unicode, unicode, int) -> None
|
||||||
"""Append one line of generated reST to the output."""
|
"""Append one line of generated reST to the output."""
|
||||||
@ -354,8 +328,7 @@ class Documenter(object):
|
|||||||
explicit_modname, path, base, args, retann = \
|
explicit_modname, path, base, args, retann = \
|
||||||
py_ext_sig_re.match(self.name).groups() # type: ignore
|
py_ext_sig_re.match(self.name).groups() # type: ignore
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.directive.warn('invalid signature for auto%s (%r)' %
|
logger.warning('invalid signature for auto%s (%r)' % (self.objtype, self.name))
|
||||||
(self.objtype, self.name))
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# support explicit module and class name separation via ::
|
# support explicit module and class name separation via ::
|
||||||
@ -384,56 +357,15 @@ class Documenter(object):
|
|||||||
|
|
||||||
Returns True if successful, False if an error occurred.
|
Returns True if successful, False if an error occurred.
|
||||||
"""
|
"""
|
||||||
if self.objpath:
|
|
||||||
logger.debug('[autodoc] from %s import %s',
|
|
||||||
self.modname, '.'.join(self.objpath))
|
|
||||||
# always enable mock import hook
|
|
||||||
# it will do nothing if autodoc_mock_imports is empty
|
|
||||||
with mock(self.env.config.autodoc_mock_imports):
|
with mock(self.env.config.autodoc_mock_imports):
|
||||||
try:
|
try:
|
||||||
logger.debug('[autodoc] import %s', self.modname)
|
ret = import_object(self.modname, self.objpath, self.objtype,
|
||||||
obj = import_module(self.modname, self.env.config.autodoc_warningiserror)
|
attrgetter=self.get_attr,
|
||||||
parent = None
|
warningiserror=self.env.config.autodoc_warningiserror)
|
||||||
self.module = obj
|
self.module, self.parent, self.object_name, self.object = ret
|
||||||
logger.debug('[autodoc] => %r', obj)
|
|
||||||
for part in self.objpath:
|
|
||||||
parent = obj
|
|
||||||
logger.debug('[autodoc] getattr(_, %r)', part)
|
|
||||||
obj = self.get_attr(obj, part)
|
|
||||||
logger.debug('[autodoc] => %r', obj)
|
|
||||||
self.object_name = part
|
|
||||||
self.parent = parent
|
|
||||||
self.object = obj
|
|
||||||
return True
|
return True
|
||||||
except (AttributeError, ImportError) as exc:
|
except ImportError as exc:
|
||||||
if self.objpath:
|
logger.warning(exc.args[0])
|
||||||
errmsg = 'autodoc: failed to import %s %r from module %r' % \
|
|
||||||
(self.objtype, '.'.join(self.objpath), self.modname)
|
|
||||||
else:
|
|
||||||
errmsg = 'autodoc: failed to import %s %r' % \
|
|
||||||
(self.objtype, self.fullname)
|
|
||||||
|
|
||||||
if isinstance(exc, ImportError):
|
|
||||||
# import_module() raises ImportError having real exception obj and
|
|
||||||
# traceback
|
|
||||||
real_exc, traceback_msg = exc.args
|
|
||||||
if isinstance(real_exc, SystemExit):
|
|
||||||
errmsg += ('; the module executes module level statement ' +
|
|
||||||
'and it might call sys.exit().')
|
|
||||||
elif isinstance(real_exc, ImportError):
|
|
||||||
errmsg += ('; the following exception was raised:\n%s' %
|
|
||||||
real_exc.args[0])
|
|
||||||
else:
|
|
||||||
errmsg += ('; the following exception was raised:\n%s' %
|
|
||||||
traceback_msg)
|
|
||||||
else:
|
|
||||||
errmsg += ('; the following exception was raised:\n%s' %
|
|
||||||
traceback.format_exc())
|
|
||||||
|
|
||||||
if PY2:
|
|
||||||
errmsg = errmsg.decode('utf-8') # type: ignore
|
|
||||||
logger.debug(errmsg)
|
|
||||||
self.directive.warn(errmsg)
|
|
||||||
self.env.note_reread()
|
self.env.note_reread()
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -493,8 +425,8 @@ class Documenter(object):
|
|||||||
try:
|
try:
|
||||||
args = self.format_args()
|
args = self.format_args()
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
self.directive.warn('error while formatting arguments for '
|
logger.warning('error while formatting arguments for %s: %s' %
|
||||||
'%s: %s' % (self.fullname, err))
|
(self.fullname, err))
|
||||||
args = None
|
args = None
|
||||||
|
|
||||||
retann = self.retann
|
retann = self.retann
|
||||||
@ -606,57 +538,24 @@ class Documenter(object):
|
|||||||
If *want_all* is True, return all members. Else, only return those
|
If *want_all* is True, return all members. Else, only return those
|
||||||
members given by *self.options.members* (which may also be none).
|
members given by *self.options.members* (which may also be none).
|
||||||
"""
|
"""
|
||||||
analyzed_member_names = set()
|
members = get_object_members(self.object, self.objpath, self.get_attr, self.analyzer)
|
||||||
if self.analyzer:
|
|
||||||
attr_docs = self.analyzer.find_attr_docs()
|
|
||||||
namespace = '.'.join(self.objpath)
|
|
||||||
for item in iteritems(attr_docs):
|
|
||||||
if item[0][0] == namespace:
|
|
||||||
analyzed_member_names.add(item[0][1])
|
|
||||||
if not want_all:
|
if not want_all:
|
||||||
if not self.options.members:
|
if not self.options.members:
|
||||||
return False, []
|
return False, []
|
||||||
# specific members given
|
# specific members given
|
||||||
members = []
|
selected = []
|
||||||
for mname in self.options.members:
|
for name in self.options.members:
|
||||||
try:
|
if name in members:
|
||||||
members.append((mname, self.get_attr(self.object, mname)))
|
selected.append((name, members[name].value))
|
||||||
except AttributeError:
|
else:
|
||||||
if mname not in analyzed_member_names:
|
logger.warning('missing attribute %s in object %s' %
|
||||||
self.directive.warn('missing attribute %s in object %s'
|
(name, self.fullname))
|
||||||
% (mname, self.fullname))
|
return False, sorted(selected)
|
||||||
elif self.options.inherited_members:
|
elif self.options.inherited_members:
|
||||||
# safe_getmembers() uses dir() which pulls in members from all
|
return False, sorted((m.name, m.value) for m in itervalues(members))
|
||||||
# base classes
|
|
||||||
members = safe_getmembers(self.object, attr_getter=self.get_attr)
|
|
||||||
else:
|
else:
|
||||||
# __dict__ contains only the members directly defined in
|
return False, sorted((m.name, m.value) for m in itervalues(members)
|
||||||
# the class (but get them via getattr anyway, to e.g. get
|
if m.directly_defined)
|
||||||
# unbound method objects instead of function objects);
|
|
||||||
# using list(iterkeys()) because apparently there are objects for which
|
|
||||||
# __dict__ changes while getting attributes
|
|
||||||
try:
|
|
||||||
obj_dict = self.get_attr(self.object, '__dict__')
|
|
||||||
except AttributeError:
|
|
||||||
members = []
|
|
||||||
else:
|
|
||||||
members = [(mname, self.get_attr(self.object, mname, None))
|
|
||||||
for mname in list(iterkeys(obj_dict))]
|
|
||||||
|
|
||||||
# Py34 doesn't have enum members in __dict__.
|
|
||||||
if isenumclass(self.object):
|
|
||||||
members.extend(
|
|
||||||
item for item in self.object.__members__.items()
|
|
||||||
if item not in members
|
|
||||||
)
|
|
||||||
|
|
||||||
membernames = set(m[0] for m in members)
|
|
||||||
# add instance attributes from the analyzer
|
|
||||||
for aname in analyzed_member_names:
|
|
||||||
if aname not in membernames and \
|
|
||||||
(want_all or aname in self.options.members):
|
|
||||||
members.append((aname, INSTANCEATTR))
|
|
||||||
return False, sorted(members)
|
|
||||||
|
|
||||||
def filter_members(self, members, want_all):
|
def filter_members(self, members, want_all):
|
||||||
# type: (List[Tuple[unicode, Any]], bool) -> List[Tuple[unicode, Any, bool]]
|
# type: (List[Tuple[unicode, Any]], bool) -> List[Tuple[unicode, Any, bool]]
|
||||||
@ -715,8 +614,7 @@ class Documenter(object):
|
|||||||
elif (namespace, membername) in attr_docs:
|
elif (namespace, membername) in attr_docs:
|
||||||
if want_all and membername.startswith('_'):
|
if want_all and membername.startswith('_'):
|
||||||
# ignore members whose name starts with _ by default
|
# ignore members whose name starts with _ by default
|
||||||
keep = self.options.private_members and \
|
keep = self.options.private_members
|
||||||
(has_doc or self.options.undoc_members)
|
|
||||||
else:
|
else:
|
||||||
# keep documented attributes
|
# keep documented attributes
|
||||||
keep = True
|
keep = True
|
||||||
@ -769,7 +667,7 @@ class Documenter(object):
|
|||||||
# document non-skipped members
|
# document non-skipped members
|
||||||
memberdocumenters = [] # type: List[Tuple[Documenter, bool]]
|
memberdocumenters = [] # type: List[Tuple[Documenter, bool]]
|
||||||
for (mname, member, isattr) in self.filter_members(members, want_all):
|
for (mname, member, isattr) in self.filter_members(members, want_all):
|
||||||
classes = [cls for cls in itervalues(AutoDirective._registry)
|
classes = [cls for cls in itervalues(self.documenters)
|
||||||
if cls.can_document_member(member, mname, isattr, self)]
|
if cls.can_document_member(member, mname, isattr, self)]
|
||||||
if not classes:
|
if not classes:
|
||||||
# don't know how to document this member
|
# don't know how to document this member
|
||||||
@ -820,11 +718,11 @@ class Documenter(object):
|
|||||||
"""
|
"""
|
||||||
if not self.parse_name():
|
if not self.parse_name():
|
||||||
# need a module to import
|
# need a module to import
|
||||||
self.directive.warn(
|
logger.warning(
|
||||||
'don\'t know which module to import for autodocumenting '
|
'don\'t know which module to import for autodocumenting '
|
||||||
'%r (try placing a "module" or "currentmodule" directive '
|
'%r (try placing a "module" or "currentmodule" directive '
|
||||||
'in the document, or giving an explicit module name)'
|
'in the document, or giving an explicit module name)' %
|
||||||
% self.name)
|
self.name)
|
||||||
return
|
return
|
||||||
|
|
||||||
# now, import the module and get object to document
|
# now, import the module and get object to document
|
||||||
@ -910,14 +808,14 @@ class ModuleDocumenter(Documenter):
|
|||||||
def resolve_name(self, modname, parents, path, base):
|
def resolve_name(self, modname, parents, path, base):
|
||||||
# type: (str, Any, str, Any) -> Tuple[str, List[unicode]]
|
# type: (str, Any, str, Any) -> Tuple[str, List[unicode]]
|
||||||
if modname is not None:
|
if modname is not None:
|
||||||
self.directive.warn('"::" in automodule name doesn\'t make sense')
|
logger.warning('"::" in automodule name doesn\'t make sense')
|
||||||
return (path or '') + base, []
|
return (path or '') + base, []
|
||||||
|
|
||||||
def parse_name(self):
|
def parse_name(self):
|
||||||
# type: () -> bool
|
# type: () -> bool
|
||||||
ret = Documenter.parse_name(self)
|
ret = Documenter.parse_name(self)
|
||||||
if self.args or self.retann:
|
if self.args or self.retann:
|
||||||
self.directive.warn('signature arguments or return annotation '
|
logger.warning('signature arguments or return annotation '
|
||||||
'given for automodule %s' % self.fullname)
|
'given for automodule %s' % self.fullname)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@ -950,7 +848,7 @@ class ModuleDocumenter(Documenter):
|
|||||||
# Sometimes __all__ is broken...
|
# Sometimes __all__ is broken...
|
||||||
if not isinstance(memberlist, (list, tuple)) or not \
|
if not isinstance(memberlist, (list, tuple)) or not \
|
||||||
all(isinstance(entry, string_types) for entry in memberlist):
|
all(isinstance(entry, string_types) for entry in memberlist):
|
||||||
self.directive.warn(
|
logger.warning(
|
||||||
'__all__ should be a list of strings, not %r '
|
'__all__ should be a list of strings, not %r '
|
||||||
'(in module %s) -- ignoring __all__' %
|
'(in module %s) -- ignoring __all__' %
|
||||||
(memberlist, self.fullname))
|
(memberlist, self.fullname))
|
||||||
@ -963,10 +861,10 @@ class ModuleDocumenter(Documenter):
|
|||||||
try:
|
try:
|
||||||
ret.append((mname, safe_getattr(self.object, mname)))
|
ret.append((mname, safe_getattr(self.object, mname)))
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.directive.warn(
|
logger.warning(
|
||||||
'missing attribute mentioned in :members: or __all__: '
|
'missing attribute mentioned in :members: or __all__: '
|
||||||
'module %s, attribute %s' % (
|
'module %s, attribute %s' %
|
||||||
safe_getattr(self.object, '__name__', '???'), mname))
|
(safe_getattr(self.object, '__name__', '???'), mname))
|
||||||
return False, ret
|
return False, ret
|
||||||
|
|
||||||
|
|
||||||
@ -1505,118 +1403,56 @@ class InstanceAttributeDocumenter(AttributeDocumenter):
|
|||||||
AttributeDocumenter.add_content(self, more_content, no_docstring=True)
|
AttributeDocumenter.add_content(self, more_content, no_docstring=True)
|
||||||
|
|
||||||
|
|
||||||
class AutoDirective(Directive):
|
class DeprecatedDict(dict):
|
||||||
"""
|
def __init__(self, message):
|
||||||
The AutoDirective class is used for all autodoc directives. It dispatches
|
self.message = message
|
||||||
most of the work to one of the Documenters, which it selects through its
|
super(DeprecatedDict, self).__init__()
|
||||||
*_registry* dictionary.
|
|
||||||
|
|
||||||
The *_special_attrgetters* attribute is used to customize ``getattr()``
|
def __setitem__(self, key, value):
|
||||||
calls that the Documenters make; its entries are of the form ``type:
|
warnings.warn(self.message, RemovedInSphinx20Warning)
|
||||||
getattr_function``.
|
super(DeprecatedDict, self).__setitem__(key, value)
|
||||||
|
|
||||||
|
def setdefault(self, key, default=None):
|
||||||
|
warnings.warn(self.message, RemovedInSphinx20Warning)
|
||||||
|
super(DeprecatedDict, self).setdefault(key, default)
|
||||||
|
|
||||||
|
def update(self, other=None):
|
||||||
|
warnings.warn(self.message, RemovedInSphinx20Warning)
|
||||||
|
super(DeprecatedDict, self).update(other)
|
||||||
|
|
||||||
|
|
||||||
|
class AutodocRegistry(object):
|
||||||
|
"""
|
||||||
|
A registry of Documenters and attrgetters.
|
||||||
|
|
||||||
Note: When importing an object, all items along the import chain are
|
Note: When importing an object, all items along the import chain are
|
||||||
accessed using the descendant's *_special_attrgetters*, thus this
|
accessed using the descendant's *_special_attrgetters*, thus this
|
||||||
dictionary should include all necessary functions for accessing
|
dictionary should include all necessary functions for accessing
|
||||||
attributes of the parents.
|
attributes of the parents.
|
||||||
"""
|
"""
|
||||||
# a registry of objtype -> documenter class
|
# a registry of objtype -> documenter class (Deprecated)
|
||||||
_registry = {} # type: Dict[unicode, Type[Documenter]]
|
_registry = DeprecatedDict(
|
||||||
|
'AutoDirective._registry has been deprecated. '
|
||||||
|
'Please use app.add_autodocumenter() instead.'
|
||||||
|
) # type: Dict[unicode, Type[Documenter]]
|
||||||
|
|
||||||
# a registry of type -> getattr function
|
# a registry of type -> getattr function
|
||||||
_special_attrgetters = {} # type: Dict[Type, Callable]
|
_special_attrgetters = DeprecatedDict(
|
||||||
|
'AutoDirective._special_attrgetters has been deprecated. '
|
||||||
|
'Please use app.add_autodoc_attrgetter() instead.'
|
||||||
|
) # type: Dict[Type, Callable]
|
||||||
|
|
||||||
# flags that can be given in autodoc_default_flags
|
|
||||||
_default_flags = set([
|
|
||||||
'members', 'undoc-members', 'inherited-members', 'show-inheritance',
|
|
||||||
'private-members', 'special-members', 'ignore-module-all'
|
|
||||||
])
|
|
||||||
|
|
||||||
# standard docutils directive settings
|
AutoDirective = AutodocRegistry # for backward compatibility
|
||||||
has_content = True
|
|
||||||
required_arguments = 1
|
|
||||||
optional_arguments = 0
|
|
||||||
final_argument_whitespace = True
|
|
||||||
# allow any options to be passed; the options are parsed further
|
|
||||||
# by the selected Documenter
|
|
||||||
option_spec = DefDict(identity)
|
|
||||||
|
|
||||||
def warn(self, msg):
|
|
||||||
# type: (unicode) -> None
|
|
||||||
self.warnings.append(self.reporter.warning(msg, line=self.lineno))
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
# type: () -> List[nodes.Node]
|
|
||||||
self.filename_set = set() # type: Set[unicode]
|
|
||||||
# a set of dependent filenames
|
|
||||||
self.reporter = self.state.document.reporter
|
|
||||||
self.env = self.state.document.settings.env
|
|
||||||
self.warnings = [] # type: List[unicode]
|
|
||||||
self.result = ViewList()
|
|
||||||
|
|
||||||
try:
|
|
||||||
source, lineno = self.reporter.get_source_and_line(self.lineno)
|
|
||||||
except AttributeError:
|
|
||||||
source = lineno = None
|
|
||||||
logger.debug('[autodoc] %s:%s: input:\n%s',
|
|
||||||
source, lineno, self.block_text)
|
|
||||||
|
|
||||||
# find out what documenter to call
|
|
||||||
objtype = self.name[4:]
|
|
||||||
doc_class = self._registry[objtype]
|
|
||||||
# add default flags
|
|
||||||
for flag in self._default_flags:
|
|
||||||
if flag not in doc_class.option_spec:
|
|
||||||
continue
|
|
||||||
negated = self.options.pop('no-' + flag, 'not given') is None
|
|
||||||
if flag in self.env.config.autodoc_default_flags and \
|
|
||||||
not negated:
|
|
||||||
self.options[flag] = None
|
|
||||||
# process the options with the selected documenter's option_spec
|
|
||||||
try:
|
|
||||||
self.genopt = Options(assemble_option_dict(
|
|
||||||
self.options.items(), doc_class.option_spec))
|
|
||||||
except (KeyError, ValueError, TypeError) as err:
|
|
||||||
# an option is either unknown or has a wrong type
|
|
||||||
msg = self.reporter.error('An option to %s is either unknown or '
|
|
||||||
'has an invalid value: %s' % (self.name, err),
|
|
||||||
line=self.lineno)
|
|
||||||
return [msg]
|
|
||||||
# generate the output
|
|
||||||
documenter = doc_class(self, self.arguments[0])
|
|
||||||
documenter.generate(more_content=self.content)
|
|
||||||
if not self.result:
|
|
||||||
return self.warnings
|
|
||||||
|
|
||||||
logger.debug('[autodoc] output:\n%s', '\n'.join(self.result))
|
|
||||||
|
|
||||||
# record all filenames as dependencies -- this will at least
|
|
||||||
# partially make automatic invalidation possible
|
|
||||||
for fn in self.filename_set:
|
|
||||||
self.state.document.settings.record_dependencies.add(fn)
|
|
||||||
|
|
||||||
# use a custom reporter that correctly assigns lines to source
|
|
||||||
# filename/description and lineno
|
|
||||||
old_reporter = self.state.memo.reporter
|
|
||||||
self.state.memo.reporter = AutodocReporter(self.result,
|
|
||||||
self.state.memo.reporter)
|
|
||||||
|
|
||||||
if documenter.titles_allowed:
|
|
||||||
node = nodes.section()
|
|
||||||
# necessary so that the child nodes get the right source/line set
|
|
||||||
node.document = self.state.document
|
|
||||||
nested_parse_with_titles(self.state, self.result, node)
|
|
||||||
else:
|
|
||||||
node = nodes.paragraph()
|
|
||||||
node.document = self.state.document
|
|
||||||
self.state.nested_parse(self.result, 0, node)
|
|
||||||
self.state.memo.reporter = old_reporter
|
|
||||||
return self.warnings + node.children
|
|
||||||
|
|
||||||
|
|
||||||
def add_documenter(cls):
|
def add_documenter(cls):
|
||||||
# type: (Type[Documenter]) -> None
|
# type: (Type[Documenter]) -> None
|
||||||
"""Register a new Documenter."""
|
"""Register a new Documenter."""
|
||||||
|
warnings.warn('sphinx.ext.autodoc.add_documenter() has been deprecated. '
|
||||||
|
'Please use app.add_autodocumenter() instead.',
|
||||||
|
RemovedInSphinx20Warning)
|
||||||
|
|
||||||
if not issubclass(cls, Documenter):
|
if not issubclass(cls, Documenter):
|
||||||
raise ExtensionError('autodoc documenter %r must be a subclass '
|
raise ExtensionError('autodoc documenter %r must be a subclass '
|
||||||
'of Documenter' % cls)
|
'of Documenter' % cls)
|
||||||
@ -1627,6 +1463,29 @@ def add_documenter(cls):
|
|||||||
AutoDirective._registry[cls.objtype] = cls
|
AutoDirective._registry[cls.objtype] = cls
|
||||||
|
|
||||||
|
|
||||||
|
def get_documenters(app):
|
||||||
|
# type: (Sphinx) -> Dict[unicode, Type[Documenter]]
|
||||||
|
"""Returns registered Documenter classes"""
|
||||||
|
classes = dict(AutoDirective._registry) # registered directly
|
||||||
|
if app:
|
||||||
|
classes.update(app.registry.documenters) # registered by API
|
||||||
|
return classes
|
||||||
|
|
||||||
|
|
||||||
|
def autodoc_attrgetter(app, obj, name, *defargs):
|
||||||
|
# type: (Sphinx, Any, unicode, Any) -> Any
|
||||||
|
"""Alternative getattr() for types"""
|
||||||
|
candidates = dict(AutoDirective._special_attrgetters)
|
||||||
|
if app:
|
||||||
|
candidates.update(app.registry.autodoc_attrgettrs)
|
||||||
|
|
||||||
|
for typ, func in iteritems(candidates):
|
||||||
|
if isinstance(obj, typ):
|
||||||
|
return func(obj, name, *defargs)
|
||||||
|
|
||||||
|
return safe_getattr(obj, name, *defargs)
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
# type: (Sphinx) -> Dict[unicode, Any]
|
# type: (Sphinx) -> Dict[unicode, Any]
|
||||||
app.add_autodocumenter(ModuleDocumenter)
|
app.add_autodocumenter(ModuleDocumenter)
|
||||||
|
155
sphinx/ext/autodoc/directive.py
Normal file
155
sphinx/ext/autodoc/directive.py
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
sphinx.ext.autodoc.directive
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||||
|
:license: BSD, see LICENSE for details.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from docutils import nodes
|
||||||
|
from docutils.parsers.rst import Directive
|
||||||
|
from docutils.statemachine import ViewList
|
||||||
|
from docutils.utils import assemble_option_dict
|
||||||
|
|
||||||
|
from sphinx.ext.autodoc import get_documenters
|
||||||
|
from sphinx.util import logging
|
||||||
|
from sphinx.util.docutils import switch_source_input
|
||||||
|
from sphinx.util.nodes import nested_parse_with_titles
|
||||||
|
|
||||||
|
if False:
|
||||||
|
# For type annotation
|
||||||
|
from typing import Any, Dict, List, Set, Type # NOQA
|
||||||
|
from docutils.statemachine import State, StateMachine, StringList # NOQA
|
||||||
|
from docutils.utils import Reporter # NOQA
|
||||||
|
from sphinx.config import Config # NOQA
|
||||||
|
from sphinx.environment import BuildEnvironment # NOQA
|
||||||
|
from sphinx.ext.autodoc import Documenter # NOQA
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
# common option names for autodoc directives
|
||||||
|
AUTODOC_DEFAULT_OPTIONS = ['members', 'undoc-members', 'inherited-members',
|
||||||
|
'show-inheritance', 'private-members', 'special-members',
|
||||||
|
'ignore-module-all']
|
||||||
|
|
||||||
|
|
||||||
|
class DummyOptionSpec(object):
|
||||||
|
"""An option_spec allows any options."""
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
# type: (Any) -> Any
|
||||||
|
return lambda x: x
|
||||||
|
|
||||||
|
|
||||||
|
class Options(dict):
|
||||||
|
"""A dict/attribute hybrid that returns None on nonexisting keys."""
|
||||||
|
def __getattr__(self, name):
|
||||||
|
# type: (unicode) -> Any
|
||||||
|
try:
|
||||||
|
return self[name.replace('_', '-')]
|
||||||
|
except KeyError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class DocumenterBridge(object):
|
||||||
|
"""A parameters container for Documenters."""
|
||||||
|
|
||||||
|
def __init__(self, env, reporter, options, lineno):
|
||||||
|
# type: (BuildEnvironment, Reporter, Options, int) -> None
|
||||||
|
self.env = env
|
||||||
|
self.reporter = reporter
|
||||||
|
self.genopt = options
|
||||||
|
self.lineno = lineno
|
||||||
|
self.filename_set = set() # type: Set[unicode]
|
||||||
|
self.result = ViewList()
|
||||||
|
|
||||||
|
def warn(self, msg):
|
||||||
|
# type: (unicode) -> None
|
||||||
|
logger.warning(msg, line=self.lineno)
|
||||||
|
|
||||||
|
|
||||||
|
def process_documenter_options(documenter, config, options):
|
||||||
|
# type: (Type[Documenter], Config, Dict) -> Options
|
||||||
|
"""Recognize options of Documenter from user input."""
|
||||||
|
for name in AUTODOC_DEFAULT_OPTIONS:
|
||||||
|
if name not in documenter.option_spec:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
negated = options.pop('no-' + name, True) is None
|
||||||
|
if name in config.autodoc_default_flags and not negated:
|
||||||
|
options[name] = None
|
||||||
|
|
||||||
|
return Options(assemble_option_dict(options.items(), documenter.option_spec))
|
||||||
|
|
||||||
|
|
||||||
|
def parse_generated_content(state, content, documenter):
|
||||||
|
# type: (State, StringList, Documenter) -> List[nodes.Node]
|
||||||
|
"""Parse a generated content by Documenter."""
|
||||||
|
with switch_source_input(state, content):
|
||||||
|
if documenter.titles_allowed:
|
||||||
|
node = nodes.section()
|
||||||
|
# necessary so that the child nodes get the right source/line set
|
||||||
|
node.document = state.document
|
||||||
|
nested_parse_with_titles(state, content, node)
|
||||||
|
else:
|
||||||
|
node = nodes.paragraph()
|
||||||
|
node.document = state.document
|
||||||
|
state.nested_parse(content, 0, node)
|
||||||
|
|
||||||
|
return node.children
|
||||||
|
|
||||||
|
|
||||||
|
class AutodocDirective(Directive):
|
||||||
|
"""A directive class for all autodoc directives. It works as a dispatcher of Documenters.
|
||||||
|
|
||||||
|
It invokes a Documenter on running. After the processing, it parses and returns
|
||||||
|
the generated content by Documenter.
|
||||||
|
"""
|
||||||
|
option_spec = DummyOptionSpec()
|
||||||
|
has_content = True
|
||||||
|
required_arguments = 1
|
||||||
|
optional_arguments = 0
|
||||||
|
final_argument_whitespace = True
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
# type: () -> List[nodes.Node]
|
||||||
|
env = self.state.document.settings.env
|
||||||
|
reporter = self.state.document.reporter
|
||||||
|
|
||||||
|
try:
|
||||||
|
source, lineno = reporter.get_source_and_line(self.lineno)
|
||||||
|
except AttributeError:
|
||||||
|
source, lineno = (None, None)
|
||||||
|
logger.debug('[autodoc] %s:%s: input:\n%s', source, lineno, self.block_text)
|
||||||
|
|
||||||
|
# look up target Documenter
|
||||||
|
objtype = self.name[4:] # strip prefix (auto-).
|
||||||
|
doccls = get_documenters(env.app)[objtype]
|
||||||
|
|
||||||
|
# process the options with the selected documenter's option_spec
|
||||||
|
try:
|
||||||
|
documenter_options = process_documenter_options(doccls, env.config, self.options)
|
||||||
|
except (KeyError, ValueError, TypeError) as exc:
|
||||||
|
# an option is either unknown or has a wrong type
|
||||||
|
logger.error('An option to %s is either unknown or has an invalid value: %s' %
|
||||||
|
(self.name, exc), line=lineno)
|
||||||
|
return []
|
||||||
|
|
||||||
|
# generate the output
|
||||||
|
params = DocumenterBridge(env, reporter, documenter_options, lineno)
|
||||||
|
documenter = doccls(params, self.arguments[0])
|
||||||
|
documenter.generate(more_content=self.content)
|
||||||
|
if not params.result:
|
||||||
|
return []
|
||||||
|
|
||||||
|
logger.debug('[autodoc] output:\n%s', '\n'.join(params.result))
|
||||||
|
|
||||||
|
# record all filenames as dependencies -- this will at least
|
||||||
|
# partially make automatic invalidation possible
|
||||||
|
for fn in params.filename_set:
|
||||||
|
self.state.document.settings.record_dependencies.add(fn)
|
||||||
|
|
||||||
|
result = parse_generated_content(self.state, params.result, documenter)
|
||||||
|
return result
|
@ -13,13 +13,17 @@ import sys
|
|||||||
import warnings
|
import warnings
|
||||||
import traceback
|
import traceback
|
||||||
import contextlib
|
import contextlib
|
||||||
|
from collections import namedtuple
|
||||||
from types import FunctionType, MethodType, ModuleType
|
from types import FunctionType, MethodType, ModuleType
|
||||||
|
|
||||||
|
from six import PY2
|
||||||
|
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
|
from sphinx.util.inspect import isenumclass, safe_getattr
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Any, Generator, List, Set # NOQA
|
from typing import Any, Callable, Dict, Generator, List, Optional # NOQA
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -80,13 +84,7 @@ class _MockModule(ModuleType):
|
|||||||
class _MockImporter(object):
|
class _MockImporter(object):
|
||||||
def __init__(self, names):
|
def __init__(self, names):
|
||||||
# type: (List[str]) -> None
|
# type: (List[str]) -> None
|
||||||
self.base_packages = set() # type: Set[str]
|
self.names = names
|
||||||
for n in names:
|
|
||||||
# Convert module names:
|
|
||||||
# ['a.b.c', 'd.e']
|
|
||||||
# to a set of base packages:
|
|
||||||
# set(['a', 'd'])
|
|
||||||
self.base_packages.add(n.split('.')[0])
|
|
||||||
self.mocked_modules = [] # type: List[str]
|
self.mocked_modules = [] # type: List[str]
|
||||||
# enable hook by adding itself to meta_path
|
# enable hook by adding itself to meta_path
|
||||||
sys.meta_path = sys.meta_path + [self]
|
sys.meta_path = sys.meta_path + [self]
|
||||||
@ -102,8 +100,9 @@ class _MockImporter(object):
|
|||||||
|
|
||||||
def find_module(self, name, path=None):
|
def find_module(self, name, path=None):
|
||||||
# type: (str, str) -> Any
|
# type: (str, str) -> Any
|
||||||
base_package = name.split('.')[0]
|
# check if name is (or is a descendant of) one of our base_packages
|
||||||
if base_package in self.base_packages:
|
for n in self.names:
|
||||||
|
if n == name or name.startswith(n + '.'):
|
||||||
return self
|
return self
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@ -144,3 +143,86 @@ def import_module(modname, warningiserror=False):
|
|||||||
# Importing modules may cause any side effects, including
|
# Importing modules may cause any side effects, including
|
||||||
# SystemExit, so we need to catch all errors.
|
# SystemExit, so we need to catch all errors.
|
||||||
raise ImportError(exc, traceback.format_exc())
|
raise ImportError(exc, traceback.format_exc())
|
||||||
|
|
||||||
|
|
||||||
|
def import_object(modname, objpath, objtype='', attrgetter=safe_getattr, warningiserror=False):
|
||||||
|
# type: (str, List[unicode], str, Callable[[Any, unicode], Any], bool) -> Any
|
||||||
|
if objpath:
|
||||||
|
logger.debug('[autodoc] from %s import %s', modname, '.'.join(objpath))
|
||||||
|
else:
|
||||||
|
logger.debug('[autodoc] import %s', modname)
|
||||||
|
|
||||||
|
try:
|
||||||
|
module = import_module(modname, warningiserror=warningiserror)
|
||||||
|
logger.debug('[autodoc] => %r', module)
|
||||||
|
obj = module
|
||||||
|
parent = None
|
||||||
|
object_name = None
|
||||||
|
for attrname in objpath:
|
||||||
|
parent = obj
|
||||||
|
logger.debug('[autodoc] getattr(_, %r)', attrname)
|
||||||
|
obj = attrgetter(obj, attrname)
|
||||||
|
logger.debug('[autodoc] => %r', obj)
|
||||||
|
object_name = attrname
|
||||||
|
return [module, parent, object_name, obj]
|
||||||
|
except (AttributeError, ImportError) as exc:
|
||||||
|
if objpath:
|
||||||
|
errmsg = ('autodoc: failed to import %s %r from module %r' %
|
||||||
|
(objtype, '.'.join(objpath), modname))
|
||||||
|
else:
|
||||||
|
errmsg = 'autodoc: failed to import %s %r' % (objtype, modname)
|
||||||
|
|
||||||
|
if isinstance(exc, ImportError):
|
||||||
|
# import_module() raises ImportError having real exception obj and
|
||||||
|
# traceback
|
||||||
|
real_exc, traceback_msg = exc.args
|
||||||
|
if isinstance(real_exc, SystemExit):
|
||||||
|
errmsg += ('; the module executes module level statement '
|
||||||
|
'and it might call sys.exit().')
|
||||||
|
elif isinstance(real_exc, ImportError):
|
||||||
|
errmsg += '; the following exception was raised:\n%s' % real_exc.args[0]
|
||||||
|
else:
|
||||||
|
errmsg += '; the following exception was raised:\n%s' % traceback_msg
|
||||||
|
else:
|
||||||
|
errmsg += '; the following exception was raised:\n%s' % traceback.format_exc()
|
||||||
|
|
||||||
|
if PY2:
|
||||||
|
errmsg = errmsg.decode('utf-8') # type: ignore
|
||||||
|
logger.debug(errmsg)
|
||||||
|
raise ImportError(errmsg)
|
||||||
|
|
||||||
|
|
||||||
|
Attribute = namedtuple('Attribute', ['name', 'directly_defined', 'value'])
|
||||||
|
|
||||||
|
|
||||||
|
def get_object_members(subject, objpath, attrgetter, analyzer=None):
|
||||||
|
# type: (Any, List[unicode], Callable, Any) -> Dict[str, Attribute] # NOQA
|
||||||
|
"""Get members and attributes of target object."""
|
||||||
|
# the members directly defined in the class
|
||||||
|
obj_dict = attrgetter(subject, '__dict__', {})
|
||||||
|
|
||||||
|
# Py34 doesn't have enum members in __dict__.
|
||||||
|
if sys.version_info[:2] == (3, 4) and isenumclass(subject):
|
||||||
|
obj_dict = dict(obj_dict)
|
||||||
|
for name, value in subject.__members__.items():
|
||||||
|
obj_dict[name] = value
|
||||||
|
|
||||||
|
members = {}
|
||||||
|
for name in dir(subject):
|
||||||
|
try:
|
||||||
|
value = attrgetter(subject, name)
|
||||||
|
directly_defined = name in obj_dict
|
||||||
|
members[name] = Attribute(name, directly_defined, value)
|
||||||
|
except AttributeError:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if analyzer:
|
||||||
|
# append instance attributes (cf. self.attr1) if analyzer knows
|
||||||
|
from sphinx.ext.autodoc import INSTANCEATTR
|
||||||
|
|
||||||
|
namespace = '.'.join(objpath)
|
||||||
|
for (ns, name) in analyzer.find_attr_docs():
|
||||||
|
if namespace == ns and name not in members:
|
||||||
|
members[name] = Attribute(name, True, INSTANCEATTR)
|
||||||
|
|
||||||
|
return members
|
||||||
|
@ -72,7 +72,8 @@ from sphinx import addnodes
|
|||||||
from sphinx.environment.adapters.toctree import TocTree
|
from sphinx.environment.adapters.toctree import TocTree
|
||||||
from sphinx.util import import_object, rst, logging
|
from sphinx.util import import_object, rst, logging
|
||||||
from sphinx.pycode import ModuleAnalyzer, PycodeError
|
from sphinx.pycode import ModuleAnalyzer, PycodeError
|
||||||
from sphinx.ext.autodoc import Options
|
from sphinx.ext.autodoc import get_documenters
|
||||||
|
from sphinx.ext.autodoc.directive import DocumenterBridge, Options
|
||||||
from sphinx.ext.autodoc.importer import import_module
|
from sphinx.ext.autodoc.importer import import_module
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
@ -153,13 +154,13 @@ def autosummary_table_visit_html(self, node):
|
|||||||
|
|
||||||
# -- autodoc integration -------------------------------------------------------
|
# -- autodoc integration -------------------------------------------------------
|
||||||
|
|
||||||
class FakeDirective(object):
|
class FakeDirective(DocumenterBridge):
|
||||||
env = {} # type: Dict
|
def __init__(self):
|
||||||
genopt = Options()
|
super(FakeDirective, self).__init__({}, None, Options(), 0) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
def get_documenter(obj, parent):
|
def get_documenter(app, obj, parent):
|
||||||
# type: (Any, Any) -> Type[Documenter]
|
# type: (Sphinx, Any, Any) -> Type[Documenter]
|
||||||
"""Get an autodoc.Documenter class suitable for documenting the given
|
"""Get an autodoc.Documenter class suitable for documenting the given
|
||||||
object.
|
object.
|
||||||
|
|
||||||
@ -167,8 +168,7 @@ def get_documenter(obj, parent):
|
|||||||
another Python object (e.g. a module or a class) to which *obj*
|
another Python object (e.g. a module or a class) to which *obj*
|
||||||
belongs to.
|
belongs to.
|
||||||
"""
|
"""
|
||||||
from sphinx.ext.autodoc import AutoDirective, DataDocumenter, \
|
from sphinx.ext.autodoc import DataDocumenter, ModuleDocumenter
|
||||||
ModuleDocumenter
|
|
||||||
|
|
||||||
if inspect.ismodule(obj):
|
if inspect.ismodule(obj):
|
||||||
# ModuleDocumenter.can_document_member always returns False
|
# ModuleDocumenter.can_document_member always returns False
|
||||||
@ -176,7 +176,7 @@ def get_documenter(obj, parent):
|
|||||||
|
|
||||||
# Construct a fake documenter for *parent*
|
# Construct a fake documenter for *parent*
|
||||||
if parent is not None:
|
if parent is not None:
|
||||||
parent_doc_cls = get_documenter(parent, None)
|
parent_doc_cls = get_documenter(app, parent, None)
|
||||||
else:
|
else:
|
||||||
parent_doc_cls = ModuleDocumenter
|
parent_doc_cls = ModuleDocumenter
|
||||||
|
|
||||||
@ -186,7 +186,7 @@ def get_documenter(obj, parent):
|
|||||||
parent_doc = parent_doc_cls(FakeDirective(), "")
|
parent_doc = parent_doc_cls(FakeDirective(), "")
|
||||||
|
|
||||||
# Get the corrent documenter class for *obj*
|
# Get the corrent documenter class for *obj*
|
||||||
classes = [cls for cls in AutoDirective._registry.values()
|
classes = [cls for cls in get_documenters(app).values()
|
||||||
if cls.can_document_member(obj, '', False, parent_doc)]
|
if cls.can_document_member(obj, '', False, parent_doc)]
|
||||||
if classes:
|
if classes:
|
||||||
classes.sort(key=lambda cls: cls.priority)
|
classes.sort(key=lambda cls: cls.priority)
|
||||||
@ -289,7 +289,7 @@ class Autosummary(Directive):
|
|||||||
full_name = modname + '::' + full_name[len(modname) + 1:]
|
full_name = modname + '::' + full_name[len(modname) + 1:]
|
||||||
# NB. using full_name here is important, since Documenters
|
# NB. using full_name here is important, since Documenters
|
||||||
# handle module prefixes slightly differently
|
# handle module prefixes slightly differently
|
||||||
documenter = get_documenter(obj, parent)(self, full_name)
|
documenter = get_documenter(self.env.app, obj, parent)(self, full_name)
|
||||||
if not documenter.parse_name():
|
if not documenter.parse_name():
|
||||||
self.warn('failed to parse name %s' % real_name)
|
self.warn('failed to parse name %s' % real_name)
|
||||||
items.append((display_name, '', '', real_name))
|
items.append((display_name, '', '', real_name))
|
||||||
@ -325,7 +325,7 @@ class Autosummary(Directive):
|
|||||||
# -- Grab the summary
|
# -- Grab the summary
|
||||||
|
|
||||||
documenter.add_content(None)
|
documenter.add_content(None)
|
||||||
doc = list(documenter.process_doc([self.result.data]))
|
doc = self.result.data
|
||||||
|
|
||||||
while doc and not doc[0].strip():
|
while doc and not doc[0].strip():
|
||||||
doc.pop(0)
|
doc.pop(0)
|
||||||
@ -615,7 +615,8 @@ def process_generate_options(app):
|
|||||||
|
|
||||||
generate_autosummary_docs(genfiles, builder=app.builder,
|
generate_autosummary_docs(genfiles, builder=app.builder,
|
||||||
warn=logger.warning, info=logger.info,
|
warn=logger.warning, info=logger.info,
|
||||||
suffix=suffix, base_path=app.srcdir)
|
suffix=suffix, base_path=app.srcdir,
|
||||||
|
app=app)
|
||||||
|
|
||||||
|
|
||||||
def setup(app):
|
def setup(app):
|
||||||
|
@ -33,24 +33,11 @@ from sphinx import __display_version__
|
|||||||
from sphinx import package_dir
|
from sphinx import package_dir
|
||||||
from sphinx.ext.autosummary import import_by_name, get_documenter
|
from sphinx.ext.autosummary import import_by_name, get_documenter
|
||||||
from sphinx.jinja2glue import BuiltinTemplateLoader
|
from sphinx.jinja2glue import BuiltinTemplateLoader
|
||||||
|
from sphinx.registry import SphinxComponentRegistry
|
||||||
from sphinx.util.osutil import ensuredir
|
from sphinx.util.osutil import ensuredir
|
||||||
from sphinx.util.inspect import safe_getattr
|
from sphinx.util.inspect import safe_getattr
|
||||||
from sphinx.util.rst import escape as rst_escape
|
from sphinx.util.rst import escape as rst_escape
|
||||||
|
|
||||||
# Add documenters to AutoDirective registry
|
|
||||||
from sphinx.ext.autodoc import add_documenter, \
|
|
||||||
ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter, \
|
|
||||||
FunctionDocumenter, MethodDocumenter, AttributeDocumenter, \
|
|
||||||
InstanceAttributeDocumenter
|
|
||||||
add_documenter(ModuleDocumenter)
|
|
||||||
add_documenter(ClassDocumenter)
|
|
||||||
add_documenter(ExceptionDocumenter)
|
|
||||||
add_documenter(DataDocumenter)
|
|
||||||
add_documenter(FunctionDocumenter)
|
|
||||||
add_documenter(MethodDocumenter)
|
|
||||||
add_documenter(AttributeDocumenter)
|
|
||||||
add_documenter(InstanceAttributeDocumenter)
|
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Any, Callable, Dict, Tuple, List # NOQA
|
from typing import Any, Callable, Dict, Tuple, List # NOQA
|
||||||
@ -60,6 +47,30 @@ if False:
|
|||||||
from sphinx.environment import BuildEnvironment # NOQA
|
from sphinx.environment import BuildEnvironment # NOQA
|
||||||
|
|
||||||
|
|
||||||
|
class DummyApplication(object):
|
||||||
|
"""Dummy Application class for sphinx-autogen command."""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
# type: () -> None
|
||||||
|
self.registry = SphinxComponentRegistry()
|
||||||
|
|
||||||
|
|
||||||
|
def setup_documenters(app):
|
||||||
|
# type: (Any) -> None
|
||||||
|
from sphinx.ext.autodoc import (
|
||||||
|
ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter,
|
||||||
|
FunctionDocumenter, MethodDocumenter, AttributeDocumenter,
|
||||||
|
InstanceAttributeDocumenter
|
||||||
|
)
|
||||||
|
documenters = [
|
||||||
|
ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter,
|
||||||
|
FunctionDocumenter, MethodDocumenter, AttributeDocumenter,
|
||||||
|
InstanceAttributeDocumenter
|
||||||
|
]
|
||||||
|
for documenter in documenters:
|
||||||
|
app.registry.add_documenter(documenter.objtype, documenter)
|
||||||
|
|
||||||
|
|
||||||
def _simple_info(msg):
|
def _simple_info(msg):
|
||||||
# type: (unicode) -> None
|
# type: (unicode) -> None
|
||||||
print(msg)
|
print(msg)
|
||||||
@ -81,8 +92,8 @@ def _underline(title, line='='):
|
|||||||
def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
|
def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
|
||||||
warn=_simple_warn, info=_simple_info,
|
warn=_simple_warn, info=_simple_info,
|
||||||
base_path=None, builder=None, template_dir=None,
|
base_path=None, builder=None, template_dir=None,
|
||||||
imported_members=False):
|
imported_members=False, app=None):
|
||||||
# type: (List[unicode], unicode, unicode, Callable, Callable, unicode, Builder, unicode, bool) -> None # NOQA
|
# type: (List[unicode], unicode, unicode, Callable, Callable, unicode, Builder, unicode, bool, Any) -> None # NOQA
|
||||||
|
|
||||||
showed_sources = list(sorted(sources))
|
showed_sources = list(sorted(sources))
|
||||||
if len(showed_sources) > 20:
|
if len(showed_sources) > 20:
|
||||||
@ -148,7 +159,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
|
|||||||
new_files.append(fn)
|
new_files.append(fn)
|
||||||
|
|
||||||
with open(fn, 'w') as f:
|
with open(fn, 'w') as f:
|
||||||
doc = get_documenter(obj, parent)
|
doc = get_documenter(app, obj, parent)
|
||||||
|
|
||||||
if template_name is not None:
|
if template_name is not None:
|
||||||
template = template_env.get_template(template_name)
|
template = template_env.get_template(template_name)
|
||||||
@ -167,7 +178,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
|
|||||||
value = safe_getattr(obj, name)
|
value = safe_getattr(obj, name)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
continue
|
continue
|
||||||
documenter = get_documenter(value, obj)
|
documenter = get_documenter(app, value, obj)
|
||||||
if documenter.objtype == typ:
|
if documenter.objtype == typ:
|
||||||
if typ == 'method':
|
if typ == 'method':
|
||||||
items.append(name)
|
items.append(name)
|
||||||
@ -392,11 +403,14 @@ The format of the autosummary directive is documented in the
|
|||||||
|
|
||||||
def main(argv=sys.argv[1:]):
|
def main(argv=sys.argv[1:]):
|
||||||
# type: (List[str]) -> None
|
# type: (List[str]) -> None
|
||||||
|
app = DummyApplication()
|
||||||
|
setup_documenters(app)
|
||||||
args = get_parser().parse_args(argv)
|
args = get_parser().parse_args(argv)
|
||||||
generate_autosummary_docs(args.source_file, args.output_dir,
|
generate_autosummary_docs(args.source_file, args.output_dir,
|
||||||
'.' + args.suffix,
|
'.' + args.suffix,
|
||||||
template_dir=args.templates,
|
template_dir=args.templates,
|
||||||
imported_members=args.imported_members)
|
imported_members=args.imported_members,
|
||||||
|
app=app)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -50,8 +50,12 @@ def compile_regex_list(name, exps):
|
|||||||
|
|
||||||
|
|
||||||
class CoverageBuilder(Builder):
|
class CoverageBuilder(Builder):
|
||||||
|
"""
|
||||||
|
Evaluates coverage of code in the documentation.
|
||||||
|
"""
|
||||||
name = 'coverage'
|
name = 'coverage'
|
||||||
|
epilog = ('Testing of coverage in the sources finished, look at the '
|
||||||
|
'results in %(outdir)s/python.txt.')
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
|
@ -20,7 +20,8 @@ from os import path
|
|||||||
import doctest
|
import doctest
|
||||||
|
|
||||||
from six import itervalues, StringIO, binary_type, text_type, PY2
|
from six import itervalues, StringIO, binary_type, text_type, PY2
|
||||||
from distutils.version import LooseVersion
|
from packaging.specifiers import SpecifierSet, InvalidSpecifier
|
||||||
|
from packaging.version import Version
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.parsers.rst import Directive, directives
|
from docutils.parsers.rst import Directive, directives
|
||||||
@ -57,28 +58,23 @@ else:
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
def compare_version(ver1, ver2, operand):
|
def is_allowed_version(spec, version):
|
||||||
# type: (unicode, unicode, unicode) -> bool
|
# type: (unicode, unicode) -> bool
|
||||||
"""Compare `ver1` to `ver2`, relying on `operand`.
|
"""Check `spec` satisfies `version` or not.
|
||||||
|
|
||||||
|
This obeys PEP-440 specifiers:
|
||||||
|
https://www.python.org/dev/peps/pep-0440/#version-specifiers
|
||||||
|
|
||||||
Some examples:
|
Some examples:
|
||||||
|
|
||||||
>>> compare_version('3.3', '3.5', '<=')
|
>>> is_allowed_version('3.3', '<=3.5')
|
||||||
True
|
True
|
||||||
>>> compare_version('3.3', '3.2', '<=')
|
>>> is_allowed_version('3.3', '<=3.2')
|
||||||
False
|
False
|
||||||
>>> compare_version('3.3a0', '3.3', '<=')
|
>>> is_allowed_version('3.3', '>3.2, <4.0')
|
||||||
True
|
True
|
||||||
"""
|
"""
|
||||||
if operand not in ('<=', '<', '==', '>=', '>'):
|
return Version(version) in SpecifierSet(spec)
|
||||||
raise ValueError("'%s' is not a valid operand.")
|
|
||||||
v1 = LooseVersion(ver1)
|
|
||||||
v2 = LooseVersion(ver2)
|
|
||||||
return ((operand == '<=' and (v1 <= v2)) or
|
|
||||||
(operand == '<' and (v1 < v2)) or
|
|
||||||
(operand == '==' and (v1 == v2)) or
|
|
||||||
(operand == '>=' and (v1 >= v2)) or
|
|
||||||
(operand == '>' and (v1 > v2)))
|
|
||||||
|
|
||||||
|
|
||||||
# set up the necessary directives
|
# set up the necessary directives
|
||||||
@ -120,7 +116,11 @@ class TestDirective(Directive):
|
|||||||
if test is not None:
|
if test is not None:
|
||||||
# only save if it differs from code
|
# only save if it differs from code
|
||||||
node['test'] = test
|
node['test'] = test
|
||||||
if self.name == 'testoutput':
|
if self.name == 'doctest':
|
||||||
|
node['language'] = 'pycon'
|
||||||
|
elif self.name == 'testcode':
|
||||||
|
node['language'] = 'python'
|
||||||
|
elif self.name == 'testoutput':
|
||||||
# don't try to highlight output
|
# don't try to highlight output
|
||||||
node['language'] = 'none'
|
node['language'] = 'none'
|
||||||
node['options'] = {}
|
node['options'] = {}
|
||||||
@ -143,16 +143,13 @@ class TestDirective(Directive):
|
|||||||
node['options'][flag] = (option[0] == '+')
|
node['options'][flag] = (option[0] == '+')
|
||||||
if self.name == 'doctest' and 'pyversion' in self.options:
|
if self.name == 'doctest' and 'pyversion' in self.options:
|
||||||
try:
|
try:
|
||||||
option = self.options['pyversion']
|
spec = self.options['pyversion']
|
||||||
# :pyversion: >= 3.6 --> operand='>=', option_version='3.6'
|
if not is_allowed_version(spec, platform.python_version()):
|
||||||
operand, option_version = [item.strip() for item in option.split()]
|
|
||||||
running_version = platform.python_version()
|
|
||||||
if not compare_version(running_version, option_version, operand):
|
|
||||||
flag = doctest.OPTIONFLAGS_BY_NAME['SKIP']
|
flag = doctest.OPTIONFLAGS_BY_NAME['SKIP']
|
||||||
node['options'][flag] = True # Skip the test
|
node['options'][flag] = True # Skip the test
|
||||||
except ValueError:
|
except InvalidSpecifier:
|
||||||
self.state.document.reporter.warning(
|
self.state.document.reporter.warning(
|
||||||
_("'%s' is not a valid pyversion option") % option,
|
_("'%s' is not a valid pyversion option") % spec,
|
||||||
line=self.lineno)
|
line=self.lineno)
|
||||||
return [node]
|
return [node]
|
||||||
|
|
||||||
@ -278,6 +275,8 @@ class DocTestBuilder(Builder):
|
|||||||
Runs test snippets in the documentation.
|
Runs test snippets in the documentation.
|
||||||
"""
|
"""
|
||||||
name = 'doctest'
|
name = 'doctest'
|
||||||
|
epilog = ('Testing of doctests in the sources finished, look at the '
|
||||||
|
'results in %(outdir)s/output.txt.')
|
||||||
|
|
||||||
def init(self):
|
def init(self):
|
||||||
# type: () -> None
|
# type: () -> None
|
||||||
|
@ -130,8 +130,8 @@ class InheritanceGraph(object):
|
|||||||
graphviz dot graph from them.
|
graphviz dot graph from them.
|
||||||
"""
|
"""
|
||||||
def __init__(self, class_names, currmodule, show_builtins=False,
|
def __init__(self, class_names, currmodule, show_builtins=False,
|
||||||
private_bases=False, parts=0, aliases=None):
|
private_bases=False, parts=0, aliases=None, top_classes=[]):
|
||||||
# type: (unicode, str, bool, bool, int, Optional[Dict[unicode, unicode]]) -> None
|
# type: (unicode, str, bool, bool, int, Optional[Dict[unicode, unicode]], List[Any]) -> None # NOQA
|
||||||
"""*class_names* is a list of child classes to show bases from.
|
"""*class_names* is a list of child classes to show bases from.
|
||||||
|
|
||||||
If *show_builtins* is True, then Python builtins will be shown
|
If *show_builtins* is True, then Python builtins will be shown
|
||||||
@ -140,7 +140,7 @@ class InheritanceGraph(object):
|
|||||||
self.class_names = class_names
|
self.class_names = class_names
|
||||||
classes = self._import_classes(class_names, currmodule)
|
classes = self._import_classes(class_names, currmodule)
|
||||||
self.class_info = self._class_info(classes, show_builtins,
|
self.class_info = self._class_info(classes, show_builtins,
|
||||||
private_bases, parts, aliases)
|
private_bases, parts, aliases, top_classes)
|
||||||
if not self.class_info:
|
if not self.class_info:
|
||||||
raise InheritanceException('No classes found for '
|
raise InheritanceException('No classes found for '
|
||||||
'inheritance diagram')
|
'inheritance diagram')
|
||||||
@ -153,13 +153,16 @@ class InheritanceGraph(object):
|
|||||||
classes.extend(import_classes(name, currmodule))
|
classes.extend(import_classes(name, currmodule))
|
||||||
return classes
|
return classes
|
||||||
|
|
||||||
def _class_info(self, classes, show_builtins, private_bases, parts, aliases):
|
def _class_info(self, classes, show_builtins, private_bases, parts, aliases, top_classes):
|
||||||
# type: (List[Any], bool, bool, int, Optional[Dict[unicode, unicode]]) -> List[Tuple[unicode, unicode, List[unicode], unicode]] # NOQA
|
# type: (List[Any], bool, bool, int, Optional[Dict[unicode, unicode]], List[Any]) -> List[Tuple[unicode, unicode, List[unicode], unicode]] # NOQA
|
||||||
"""Return name and bases for all classes that are ancestors of
|
"""Return name and bases for all classes that are ancestors of
|
||||||
*classes*.
|
*classes*.
|
||||||
|
|
||||||
*parts* gives the number of dotted name parts that is removed from the
|
*parts* gives the number of dotted name parts that is removed from the
|
||||||
displayed node names.
|
displayed node names.
|
||||||
|
|
||||||
|
*top_classes* gives the name(s) of the top most ancestor class to traverse
|
||||||
|
to. Multiple names can be specified separated by comma.
|
||||||
"""
|
"""
|
||||||
all_classes = {}
|
all_classes = {}
|
||||||
py_builtins = vars(builtins).values()
|
py_builtins = vars(builtins).values()
|
||||||
@ -189,6 +192,10 @@ class InheritanceGraph(object):
|
|||||||
|
|
||||||
baselist = [] # type: List[unicode]
|
baselist = [] # type: List[unicode]
|
||||||
all_classes[cls] = (nodename, fullname, baselist, tooltip)
|
all_classes[cls] = (nodename, fullname, baselist, tooltip)
|
||||||
|
|
||||||
|
if fullname in top_classes:
|
||||||
|
return
|
||||||
|
|
||||||
for base in cls.__bases__:
|
for base in cls.__bases__:
|
||||||
if not show_builtins and base in py_builtins:
|
if not show_builtins and base in py_builtins:
|
||||||
continue
|
continue
|
||||||
@ -322,6 +329,7 @@ class InheritanceDiagram(Directive):
|
|||||||
'parts': directives.nonnegative_int,
|
'parts': directives.nonnegative_int,
|
||||||
'private-bases': directives.flag,
|
'private-bases': directives.flag,
|
||||||
'caption': directives.unchanged,
|
'caption': directives.unchanged,
|
||||||
|
'top-classes': directives.unchanged_required,
|
||||||
}
|
}
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
@ -334,6 +342,11 @@ class InheritanceDiagram(Directive):
|
|||||||
# Store the original content for use as a hash
|
# Store the original content for use as a hash
|
||||||
node['parts'] = self.options.get('parts', 0)
|
node['parts'] = self.options.get('parts', 0)
|
||||||
node['content'] = ', '.join(class_names)
|
node['content'] = ', '.join(class_names)
|
||||||
|
node['top-classes'] = []
|
||||||
|
for cls in self.options.get('top-classes', '').split(','):
|
||||||
|
cls = cls.strip()
|
||||||
|
if cls:
|
||||||
|
node['top-classes'].append(cls)
|
||||||
|
|
||||||
# Create a graph starting with the list of classes
|
# Create a graph starting with the list of classes
|
||||||
try:
|
try:
|
||||||
@ -341,7 +354,8 @@ class InheritanceDiagram(Directive):
|
|||||||
class_names, env.ref_context.get('py:module'),
|
class_names, env.ref_context.get('py:module'),
|
||||||
parts=node['parts'],
|
parts=node['parts'],
|
||||||
private_bases='private-bases' in self.options,
|
private_bases='private-bases' in self.options,
|
||||||
aliases=env.config.inheritance_alias)
|
aliases=env.config.inheritance_alias,
|
||||||
|
top_classes=node['top-classes'])
|
||||||
except InheritanceException as err:
|
except InheritanceException as err:
|
||||||
return [node.document.reporter.warning(err.args[0],
|
return [node.document.reporter.warning(err.args[0],
|
||||||
line=self.lineno)]
|
line=self.lineno)]
|
||||||
|
@ -304,6 +304,7 @@ def missing_reference(app, env, node, contnode):
|
|||||||
in_set = setname
|
in_set = setname
|
||||||
to_try.append((inventories.named_inventory[setname], newtarget))
|
to_try.append((inventories.named_inventory[setname], newtarget))
|
||||||
if domain:
|
if domain:
|
||||||
|
node['reftarget'] = newtarget
|
||||||
full_qualified_name = env.get_domain(domain).get_full_qualified_name(node)
|
full_qualified_name = env.get_domain(domain).get_full_qualified_name(node)
|
||||||
if full_qualified_name:
|
if full_qualified_name:
|
||||||
to_try.append((inventories.named_inventory[setname], full_qualified_name))
|
to_try.append((inventories.named_inventory[setname], full_qualified_name))
|
||||||
|
@ -20,14 +20,14 @@ from sphinx.ext.mathbase import get_node_equation_number
|
|||||||
|
|
||||||
|
|
||||||
def html_visit_math(self, node):
|
def html_visit_math(self, node):
|
||||||
self.body.append(self.starttag(node, 'span', '', CLASS='math'))
|
self.body.append(self.starttag(node, 'span', '', CLASS='math notranslate'))
|
||||||
self.body.append(self.encode(node['latex']) + '</span>')
|
self.body.append(self.encode(node['latex']) + '</span>')
|
||||||
raise nodes.SkipNode
|
raise nodes.SkipNode
|
||||||
|
|
||||||
|
|
||||||
def html_visit_displaymath(self, node):
|
def html_visit_displaymath(self, node):
|
||||||
if node['nowrap']:
|
if node['nowrap']:
|
||||||
self.body.append(self.starttag(node, 'div', CLASS='math'))
|
self.body.append(self.starttag(node, 'div', CLASS='math notranslate'))
|
||||||
self.body.append(self.encode(node['latex']))
|
self.body.append(self.encode(node['latex']))
|
||||||
self.body.append('</div>')
|
self.body.append('</div>')
|
||||||
raise nodes.SkipNode
|
raise nodes.SkipNode
|
||||||
@ -40,7 +40,7 @@ def html_visit_displaymath(self, node):
|
|||||||
self.body.append('<span class="eqno">(%s)' % number)
|
self.body.append('<span class="eqno">(%s)' % number)
|
||||||
self.add_permalink_ref(node, _('Permalink to this equation'))
|
self.add_permalink_ref(node, _('Permalink to this equation'))
|
||||||
self.body.append('</span>')
|
self.body.append('</span>')
|
||||||
self.body.append(self.starttag(node, 'div', CLASS='math'))
|
self.body.append(self.starttag(node, 'div', CLASS='math notranslate'))
|
||||||
else:
|
else:
|
||||||
# but only once!
|
# but only once!
|
||||||
self.body.append('<div class="math">')
|
self.body.append('<div class="math">')
|
||||||
|
@ -21,7 +21,7 @@ from sphinx.ext.mathbase import get_node_equation_number
|
|||||||
|
|
||||||
|
|
||||||
def html_visit_math(self, node):
|
def html_visit_math(self, node):
|
||||||
self.body.append(self.starttag(node, 'span', '', CLASS='math'))
|
self.body.append(self.starttag(node, 'span', '', CLASS='math notranslate'))
|
||||||
self.body.append(self.builder.config.mathjax_inline[0] +
|
self.body.append(self.builder.config.mathjax_inline[0] +
|
||||||
self.encode(node['latex']) +
|
self.encode(node['latex']) +
|
||||||
self.builder.config.mathjax_inline[1] + '</span>')
|
self.builder.config.mathjax_inline[1] + '</span>')
|
||||||
@ -29,7 +29,7 @@ def html_visit_math(self, node):
|
|||||||
|
|
||||||
|
|
||||||
def html_visit_displaymath(self, node):
|
def html_visit_displaymath(self, node):
|
||||||
self.body.append(self.starttag(node, 'div', CLASS='math'))
|
self.body.append(self.starttag(node, 'div', CLASS='math notranslate'))
|
||||||
if node['nowrap']:
|
if node['nowrap']:
|
||||||
self.body.append(self.encode(node['latex']))
|
self.body.append(self.encode(node['latex']))
|
||||||
self.body.append('</div>')
|
self.body.append('</div>')
|
||||||
|
@ -71,12 +71,12 @@ def doctree_read(app, doctree):
|
|||||||
code = analyzer.code.decode(analyzer.encoding)
|
code = analyzer.code.decode(analyzer.encoding)
|
||||||
else:
|
else:
|
||||||
code = analyzer.code
|
code = analyzer.code
|
||||||
if entry is None or entry[0] != code:
|
if entry is False:
|
||||||
|
return
|
||||||
|
elif entry is None or entry[0] != code:
|
||||||
analyzer.find_tags()
|
analyzer.find_tags()
|
||||||
entry = code, analyzer.tags, {}, refname
|
entry = code, analyzer.tags, {}, refname
|
||||||
env._viewcode_modules[modname] = entry # type: ignore
|
env._viewcode_modules[modname] = entry # type: ignore
|
||||||
elif entry is False:
|
|
||||||
return
|
|
||||||
_, tags, used, _ = entry
|
_, tags, used, _ = entry
|
||||||
if fullname in tags:
|
if fullname in tags:
|
||||||
used[fullname] = docname
|
used[fullname] = docname
|
||||||
|
22
sphinx/io.py
22
sphinx/io.py
@ -19,11 +19,12 @@ from docutils.writers import UnfilteredWriter
|
|||||||
from six import text_type
|
from six import text_type
|
||||||
from typing import Any, Union # NOQA
|
from typing import Any, Union # NOQA
|
||||||
|
|
||||||
|
from sphinx.transforms import SphinxTransformer
|
||||||
from sphinx.transforms import (
|
from sphinx.transforms import (
|
||||||
ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences,
|
ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences,
|
||||||
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, SortIds,
|
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks, SortIds,
|
||||||
AutoNumbering, AutoIndexUpgrader, FilterSystemMessages,
|
AutoNumbering, AutoIndexUpgrader, FilterSystemMessages,
|
||||||
UnreferencedFootnotesDetector
|
UnreferencedFootnotesDetector, SphinxSmartQuotes, ManpageLink
|
||||||
)
|
)
|
||||||
from sphinx.transforms.compact_bullet_list import RefOnlyBulletListTransform
|
from sphinx.transforms.compact_bullet_list import RefOnlyBulletListTransform
|
||||||
from sphinx.transforms.i18n import (
|
from sphinx.transforms.i18n import (
|
||||||
@ -56,6 +57,11 @@ class SphinxBaseReader(standalone.Reader):
|
|||||||
This replaces reporter by Sphinx's on generating document.
|
This replaces reporter by Sphinx's on generating document.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def __init__(self, app, *args, **kwargs):
|
||||||
|
# type: (Sphinx, Any, Any) -> None
|
||||||
|
self.env = app.env
|
||||||
|
standalone.Reader.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
def get_transforms(self):
|
def get_transforms(self):
|
||||||
# type: () -> List[Transform]
|
# type: () -> List[Transform]
|
||||||
return standalone.Reader.get_transforms(self) + self.transforms
|
return standalone.Reader.get_transforms(self) + self.transforms
|
||||||
@ -66,9 +72,16 @@ class SphinxBaseReader(standalone.Reader):
|
|||||||
for logging.
|
for logging.
|
||||||
"""
|
"""
|
||||||
document = standalone.Reader.new_document(self)
|
document = standalone.Reader.new_document(self)
|
||||||
|
|
||||||
|
# substitute transformer
|
||||||
|
document.transformer = SphinxTransformer(document)
|
||||||
|
document.transformer.set_environment(self.env)
|
||||||
|
|
||||||
|
# substitute reporter
|
||||||
reporter = document.reporter
|
reporter = document.reporter
|
||||||
document.reporter = LoggingReporter.from_reporter(reporter)
|
document.reporter = LoggingReporter.from_reporter(reporter)
|
||||||
document.reporter.set_source(self.source)
|
document.reporter.set_source(self.source)
|
||||||
|
|
||||||
return document
|
return document
|
||||||
|
|
||||||
|
|
||||||
@ -80,13 +93,14 @@ class SphinxStandaloneReader(SphinxBaseReader):
|
|||||||
Locale, CitationReferences, DefaultSubstitutions, MoveModuleTargets,
|
Locale, CitationReferences, DefaultSubstitutions, MoveModuleTargets,
|
||||||
HandleCodeBlocks, AutoNumbering, AutoIndexUpgrader, SortIds,
|
HandleCodeBlocks, AutoNumbering, AutoIndexUpgrader, SortIds,
|
||||||
RemoveTranslatableInline, PreserveTranslatableMessages, FilterSystemMessages,
|
RemoveTranslatableInline, PreserveTranslatableMessages, FilterSystemMessages,
|
||||||
RefOnlyBulletListTransform, UnreferencedFootnotesDetector
|
RefOnlyBulletListTransform, UnreferencedFootnotesDetector, SphinxSmartQuotes,
|
||||||
|
ManpageLink
|
||||||
] # type: List[Transform]
|
] # type: List[Transform]
|
||||||
|
|
||||||
def __init__(self, app, *args, **kwargs):
|
def __init__(self, app, *args, **kwargs):
|
||||||
# type: (Sphinx, Any, Any) -> None
|
# type: (Sphinx, Any, Any) -> None
|
||||||
self.transforms = self.transforms + app.registry.get_transforms()
|
self.transforms = self.transforms + app.registry.get_transforms()
|
||||||
SphinxBaseReader.__init__(self, *args, **kwargs) # type: ignore
|
SphinxBaseReader.__init__(self, app, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class SphinxI18nReader(SphinxBaseReader):
|
class SphinxI18nReader(SphinxBaseReader):
|
||||||
@ -103,7 +117,7 @@ class SphinxI18nReader(SphinxBaseReader):
|
|||||||
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks,
|
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks,
|
||||||
AutoNumbering, SortIds, RemoveTranslatableInline,
|
AutoNumbering, SortIds, RemoveTranslatableInline,
|
||||||
FilterSystemMessages, RefOnlyBulletListTransform,
|
FilterSystemMessages, RefOnlyBulletListTransform,
|
||||||
UnreferencedFootnotesDetector]
|
UnreferencedFootnotesDetector, ManpageLink]
|
||||||
|
|
||||||
def set_lineno_for_reporter(self, lineno):
|
def set_lineno_for_reporter(self, lineno):
|
||||||
# type: (int) -> None
|
# type: (int) -> None
|
||||||
|
@ -97,101 +97,6 @@ class Make(object):
|
|||||||
if not osname or os.name == osname:
|
if not osname or os.name == osname:
|
||||||
print(' %s %s' % (blue(bname.ljust(10)), description))
|
print(' %s %s' % (blue(bname.ljust(10)), description))
|
||||||
|
|
||||||
def build_html(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('html') > 0:
|
|
||||||
return 1
|
|
||||||
print()
|
|
||||||
print('Build finished. The HTML pages are in %s.' % self.builddir_join('html'))
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_dirhtml(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('dirhtml') > 0:
|
|
||||||
return 1
|
|
||||||
print()
|
|
||||||
print('Build finished. The HTML pages are in %s.' %
|
|
||||||
self.builddir_join('dirhtml'))
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_singlehtml(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('singlehtml') > 0:
|
|
||||||
return 1
|
|
||||||
print()
|
|
||||||
print('Build finished. The HTML page is in %s.' %
|
|
||||||
self.builddir_join('singlehtml'))
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_pickle(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('pickle') > 0:
|
|
||||||
return 1
|
|
||||||
print()
|
|
||||||
print('Build finished; now you can process the pickle files.')
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_json(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('json') > 0:
|
|
||||||
return 1
|
|
||||||
print()
|
|
||||||
print('Build finished; now you can process the JSON files.')
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_htmlhelp(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('htmlhelp') > 0:
|
|
||||||
return 1
|
|
||||||
print()
|
|
||||||
print('Build finished; now you can run HTML Help Workshop with the '
|
|
||||||
'.hhp project file in %s.' % self.builddir_join('htmlhelp'))
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_qthelp(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('qthelp') > 0:
|
|
||||||
return 1
|
|
||||||
print()
|
|
||||||
print('Build finished; now you can run "qcollectiongenerator" with the '
|
|
||||||
'.qhcp project file in %s, like this:' % self.builddir_join('qthelp'))
|
|
||||||
print('$ qcollectiongenerator %s.qhcp' % self.builddir_join('qthelp', proj_name))
|
|
||||||
print('To view the help file:')
|
|
||||||
print('$ assistant -collectionFile %s.qhc' %
|
|
||||||
self.builddir_join('qthelp', proj_name))
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_devhelp(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('devhelp') > 0:
|
|
||||||
return 1
|
|
||||||
print()
|
|
||||||
print("Build finished.")
|
|
||||||
print("To view the help file:")
|
|
||||||
print("$ mkdir -p $HOME/.local/share/devhelp/" + proj_name)
|
|
||||||
print("$ ln -s %s $HOME/.local/share/devhelp/%s" %
|
|
||||||
(self.builddir_join('devhelp'), proj_name))
|
|
||||||
print("$ devhelp")
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_epub(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('epub') > 0:
|
|
||||||
return 1
|
|
||||||
print()
|
|
||||||
print('Build finished. The ePub file is in %s.' % self.builddir_join('epub'))
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_latex(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('latex') > 0:
|
|
||||||
return 1
|
|
||||||
print("Build finished; the LaTeX files are in %s." % self.builddir_join('latex'))
|
|
||||||
if os.name == 'posix':
|
|
||||||
print("Run `make' in that directory to run these through (pdf)latex")
|
|
||||||
print("(use `make latexpdf' here to do that automatically).")
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_latexpdf(self):
|
def build_latexpdf(self):
|
||||||
# type: () -> int
|
# type: () -> int
|
||||||
if self.run_generic_build('latex') > 0:
|
if self.run_generic_build('latex') > 0:
|
||||||
@ -206,25 +111,6 @@ class Make(object):
|
|||||||
with cd(self.builddir_join('latex')):
|
with cd(self.builddir_join('latex')):
|
||||||
return subprocess.call([self.makecmd, 'all-pdf-ja'])
|
return subprocess.call([self.makecmd, 'all-pdf-ja'])
|
||||||
|
|
||||||
def build_text(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('text') > 0:
|
|
||||||
return 1
|
|
||||||
print()
|
|
||||||
print('Build finished. The text files are in %s.' % self.builddir_join('text'))
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_texinfo(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('texinfo') > 0:
|
|
||||||
return 1
|
|
||||||
print("Build finished; the Texinfo files are in %s." %
|
|
||||||
self.builddir_join('texinfo'))
|
|
||||||
if os.name == 'posix':
|
|
||||||
print("Run `make' in that directory to run these through makeinfo")
|
|
||||||
print("(use `make info' here to do that automatically).")
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_info(self):
|
def build_info(self):
|
||||||
# type: () -> int
|
# type: () -> int
|
||||||
if self.run_generic_build('texinfo') > 0:
|
if self.run_generic_build('texinfo') > 0:
|
||||||
@ -237,60 +123,6 @@ class Make(object):
|
|||||||
dtdir = self.builddir_join('gettext', '.doctrees')
|
dtdir = self.builddir_join('gettext', '.doctrees')
|
||||||
if self.run_generic_build('gettext', doctreedir=dtdir) > 0:
|
if self.run_generic_build('gettext', doctreedir=dtdir) > 0:
|
||||||
return 1
|
return 1
|
||||||
print()
|
|
||||||
print('Build finished. The message catalogs are in %s.' %
|
|
||||||
self.builddir_join('gettext'))
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_changes(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('changes') > 0:
|
|
||||||
return 1
|
|
||||||
print()
|
|
||||||
print('Build finished. The overview file is in %s.' %
|
|
||||||
self.builddir_join('changes'))
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_linkcheck(self):
|
|
||||||
# type: () -> int
|
|
||||||
res = self.run_generic_build('linkcheck')
|
|
||||||
print()
|
|
||||||
print('Link check complete; look for any errors in the above output '
|
|
||||||
'or in %s.' % self.builddir_join('linkcheck', 'output.txt'))
|
|
||||||
return res
|
|
||||||
|
|
||||||
def build_doctest(self):
|
|
||||||
# type: () -> int
|
|
||||||
res = self.run_generic_build('doctest')
|
|
||||||
print("Testing of doctests in the sources finished, look at the "
|
|
||||||
"results in %s." % self.builddir_join('doctest', 'output.txt'))
|
|
||||||
return res
|
|
||||||
|
|
||||||
def build_coverage(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('coverage') > 0:
|
|
||||||
print("Has the coverage extension been enabled?")
|
|
||||||
return 1
|
|
||||||
print()
|
|
||||||
print("Testing of coverage in the sources finished, look at the "
|
|
||||||
"results in %s." % self.builddir_join('coverage'))
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_xml(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('xml') > 0:
|
|
||||||
return 1
|
|
||||||
print()
|
|
||||||
print('Build finished. The XML files are in %s.' % self.builddir_join('xml'))
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def build_pseudoxml(self):
|
|
||||||
# type: () -> int
|
|
||||||
if self.run_generic_build('pseudoxml') > 0:
|
|
||||||
return 1
|
|
||||||
print()
|
|
||||||
print('Build finished. The pseudo-XML files are in %s.' %
|
|
||||||
self.builddir_join('pseudoxml'))
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def run_generic_build(self, builder, doctreedir=None):
|
def run_generic_build(self, builder, doctreedir=None):
|
||||||
|
@ -15,8 +15,6 @@ from docutils.parsers.rst import states
|
|||||||
from docutils.statemachine import StringList
|
from docutils.statemachine import StringList
|
||||||
from docutils.transforms.universal import SmartQuotes
|
from docutils.transforms.universal import SmartQuotes
|
||||||
|
|
||||||
from sphinx.transforms import SphinxSmartQuotes
|
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Any, Dict, List, Type # NOQA
|
from typing import Any, Dict, List, Type # NOQA
|
||||||
@ -63,10 +61,11 @@ class RSTParser(docutils.parsers.rst.Parser):
|
|||||||
|
|
||||||
def get_transforms(self):
|
def get_transforms(self):
|
||||||
# type: () -> List[Type[Transform]]
|
# type: () -> List[Type[Transform]]
|
||||||
"""Sphinx's reST parser replaces a transform class for smart-quotes by own's"""
|
"""Sphinx's reST parser replaces a transform class for smart-quotes by own's
|
||||||
|
|
||||||
|
refs: sphinx.io.SphinxStandaloneReader"""
|
||||||
transforms = docutils.parsers.rst.Parser.get_transforms(self)
|
transforms = docutils.parsers.rst.Parser.get_transforms(self)
|
||||||
transforms.remove(SmartQuotes)
|
transforms.remove(SmartQuotes)
|
||||||
transforms.append(SphinxSmartQuotes)
|
|
||||||
return transforms
|
return transforms
|
||||||
|
|
||||||
def parse(self, inputstring, document):
|
def parse(self, inputstring, document):
|
||||||
|
@ -38,6 +38,7 @@ if False:
|
|||||||
from sphinx.builders import Builder # NOQA
|
from sphinx.builders import Builder # NOQA
|
||||||
from sphinx.domains import Domain, Index # NOQA
|
from sphinx.domains import Domain, Index # NOQA
|
||||||
from sphinx.environment import BuildEnvironment # NOQA
|
from sphinx.environment import BuildEnvironment # NOQA
|
||||||
|
from sphinx.ext.autodoc import Documenter # NOQA
|
||||||
from sphinx.util.typing import RoleFunction # NOQA
|
from sphinx.util.typing import RoleFunction # NOQA
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@ -51,7 +52,9 @@ EXTENSION_BLACKLIST = {
|
|||||||
|
|
||||||
class SphinxComponentRegistry(object):
|
class SphinxComponentRegistry(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
self.autodoc_attrgettrs = {} # type: Dict[Type, Callable[[Any, unicode, Any], Any]]
|
||||||
self.builders = {} # type: Dict[unicode, Type[Builder]]
|
self.builders = {} # type: Dict[unicode, Type[Builder]]
|
||||||
|
self.documenters = {} # type: Dict[unicode, Type[Documenter]]
|
||||||
self.domains = {} # type: Dict[unicode, Type[Domain]]
|
self.domains = {} # type: Dict[unicode, Type[Domain]]
|
||||||
self.domain_directives = {} # type: Dict[unicode, Dict[unicode, Any]]
|
self.domain_directives = {} # type: Dict[unicode, Dict[unicode, Any]]
|
||||||
self.domain_indices = {} # type: Dict[unicode, List[Type[Index]]]
|
self.domain_indices = {} # type: Dict[unicode, List[Type[Index]]]
|
||||||
@ -284,6 +287,14 @@ class SphinxComponentRegistry(object):
|
|||||||
# type: () -> List[Type[Transform]]
|
# type: () -> List[Type[Transform]]
|
||||||
return self.post_transforms
|
return self.post_transforms
|
||||||
|
|
||||||
|
def add_documenter(self, objtype, documenter):
|
||||||
|
# type: (unicode, Type[Documenter]) -> None
|
||||||
|
self.documenters[objtype] = documenter
|
||||||
|
|
||||||
|
def add_autodoc_attrgetter(self, typ, attrgetter):
|
||||||
|
# type: (Type, Callable[[Any, unicode, Any], Any]) -> None
|
||||||
|
self.autodoc_attrgettrs[typ] = attrgetter
|
||||||
|
|
||||||
def load_extension(self, app, extname):
|
def load_extension(self, app, extname):
|
||||||
# type: (Sphinx, unicode) -> None
|
# type: (Sphinx, unicode) -> None
|
||||||
"""Load a Sphinx extension."""
|
"""Load a Sphinx extension."""
|
||||||
|
@ -207,4 +207,4 @@ class SearchFrench(SearchLanguage):
|
|||||||
self.stemmer = snowballstemmer.stemmer('french')
|
self.stemmer = snowballstemmer.stemmer('french')
|
||||||
|
|
||||||
def stem(self, word):
|
def stem(self, word):
|
||||||
return self.stemmer.stemWord(word)
|
return self.stemmer.stemWord(word.lower())
|
||||||
|
@ -5,14 +5,16 @@
|
|||||||
SPHINXOPTS ?=
|
SPHINXOPTS ?=
|
||||||
SPHINXBUILD ?= sphinx-build
|
SPHINXBUILD ?= sphinx-build
|
||||||
PAPER ?=
|
PAPER ?=
|
||||||
|
SOURCEDIR = {{ rsrcdir }}
|
||||||
BUILDDIR = {{ rbuilddir }}
|
BUILDDIR = {{ rbuilddir }}
|
||||||
|
|
||||||
# Internal variables.
|
# Internal variables.
|
||||||
PAPEROPT_a4 = -D latex_elements.papersize=a4
|
PAPEROPT_a4 = -D latex_elements.papersize=a4
|
||||||
PAPEROPT_letter = -D latex_elements.papersize=letter
|
PAPEROPT_letter = -D latex_elements.papersize=letter
|
||||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) {{ rsrcdir }}
|
# $(O) is meant as a shortcut for $(SPHINXOPTS)
|
||||||
|
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) $(SOURCEDIR)
|
||||||
# the i18n builder cannot share the environment and doctrees with the others
|
# the i18n builder cannot share the environment and doctrees with the others
|
||||||
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) {{ rsrcdir }}
|
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(O) $(SOURCEDIR)
|
||||||
|
|
||||||
.PHONY: help
|
.PHONY: help
|
||||||
help:
|
help:
|
||||||
@ -49,86 +51,6 @@ help:
|
|||||||
clean:
|
clean:
|
||||||
rm -rf $(BUILDDIR)/*
|
rm -rf $(BUILDDIR)/*
|
||||||
|
|
||||||
.PHONY: html
|
|
||||||
html:
|
|
||||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
|
||||||
|
|
||||||
.PHONY: dirhtml
|
|
||||||
dirhtml:
|
|
||||||
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
|
||||||
|
|
||||||
.PHONY: singlehtml
|
|
||||||
singlehtml:
|
|
||||||
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
|
||||||
|
|
||||||
.PHONY: pickle
|
|
||||||
pickle:
|
|
||||||
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can process the pickle files."
|
|
||||||
|
|
||||||
.PHONY: json
|
|
||||||
json:
|
|
||||||
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can process the JSON files."
|
|
||||||
|
|
||||||
.PHONY: htmlhelp
|
|
||||||
htmlhelp:
|
|
||||||
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
|
||||||
".hhp project file in $(BUILDDIR)/htmlhelp."
|
|
||||||
|
|
||||||
.PHONY: qthelp
|
|
||||||
qthelp:
|
|
||||||
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
|
||||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
|
||||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/{{ project_fn }}.qhcp"
|
|
||||||
@echo "To view the help file:"
|
|
||||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/{{ project_fn }}.qhc"
|
|
||||||
|
|
||||||
.PHONY: applehelp
|
|
||||||
applehelp:
|
|
||||||
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
|
|
||||||
@echo "N.B. You won't be able to view it unless you put it in" \
|
|
||||||
"~/Library/Documentation/Help or install it in your application" \
|
|
||||||
"bundle."
|
|
||||||
|
|
||||||
.PHONY: devhelp
|
|
||||||
devhelp:
|
|
||||||
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
|
||||||
@echo
|
|
||||||
@echo "Build finished."
|
|
||||||
@echo "To view the help file:"
|
|
||||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/{{ project_fn }}"
|
|
||||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/{{ project_fn }}"
|
|
||||||
@echo "# devhelp"
|
|
||||||
|
|
||||||
.PHONY: epub
|
|
||||||
epub:
|
|
||||||
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
|
||||||
|
|
||||||
.PHONY: latex
|
|
||||||
latex:
|
|
||||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
|
||||||
@echo
|
|
||||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
|
||||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
|
||||||
"(use \`make latexpdf' here to do that automatically)."
|
|
||||||
|
|
||||||
.PHONY: latexpdf
|
.PHONY: latexpdf
|
||||||
latexpdf:
|
latexpdf:
|
||||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
@ -157,26 +79,6 @@ xelatexpdf:
|
|||||||
$(MAKE) PDFLATEX=xelatex -C $(BUILDDIR)/latex all-pdf
|
$(MAKE) PDFLATEX=xelatex -C $(BUILDDIR)/latex all-pdf
|
||||||
@echo "xelatex finished; the PDF files are in $(BUILDDIR)/latex."
|
@echo "xelatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||||
|
|
||||||
.PHONY: text
|
|
||||||
text:
|
|
||||||
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
|
||||||
|
|
||||||
.PHONY: man
|
|
||||||
man:
|
|
||||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
|
||||||
|
|
||||||
.PHONY: texinfo
|
|
||||||
texinfo:
|
|
||||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
|
|
||||||
@echo "Run \`make' in that directory to run these through makeinfo" \
|
|
||||||
"(use \`make info' here to do that automatically)."
|
|
||||||
|
|
||||||
.PHONY: info
|
.PHONY: info
|
||||||
info:
|
info:
|
||||||
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
|
||||||
@ -187,49 +89,9 @@ info:
|
|||||||
.PHONY: gettext
|
.PHONY: gettext
|
||||||
gettext:
|
gettext:
|
||||||
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
|
||||||
@echo
|
|
||||||
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
|
|
||||||
|
|
||||||
.PHONY: changes
|
# Catch-all target: route all unknown targets to Sphinx
|
||||||
changes:
|
.PHONY: Makefile
|
||||||
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
%: Makefile
|
||||||
@echo
|
$(SPHINXBUILD) -b "$@" $(ALLSPHINXOPTS) "$(BUILDDIR)/$@"
|
||||||
@echo "The overview file is in $(BUILDDIR)/changes."
|
|
||||||
|
|
||||||
.PHONY: linkcheck
|
|
||||||
linkcheck:
|
|
||||||
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
|
||||||
@echo
|
|
||||||
@echo "Link check complete; look for any errors in the above output " \
|
|
||||||
"or in $(BUILDDIR)/linkcheck/output.txt."
|
|
||||||
|
|
||||||
.PHONY: doctest
|
|
||||||
doctest:
|
|
||||||
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
|
||||||
@echo "Testing of doctests in the sources finished, look at the " \
|
|
||||||
"results in $(BUILDDIR)/doctest/output.txt."
|
|
||||||
|
|
||||||
.PHONY: coverage
|
|
||||||
coverage:
|
|
||||||
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
|
|
||||||
@echo "Testing of coverage in the sources finished, look at the " \
|
|
||||||
"results in $(BUILDDIR)/coverage/python.txt."
|
|
||||||
|
|
||||||
.PHONY: xml
|
|
||||||
xml:
|
|
||||||
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
|
|
||||||
|
|
||||||
.PHONY: pseudoxml
|
|
||||||
pseudoxml:
|
|
||||||
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
|
|
||||||
|
|
||||||
.PHONY: dummy
|
|
||||||
dummy:
|
|
||||||
$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
|
|
||||||
@echo
|
|
||||||
@echo "Build finished. Dummy builder generates no files."
|
|
||||||
|
|
||||||
|
@ -1,19 +1,12 @@
|
|||||||
{% if PY3 -%}
|
|
||||||
#!/usr/bin/env python3
|
|
||||||
{% endif -%}
|
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# {{ project }} documentation build configuration file, created by
|
# Configuration file for the Sphinx documentation builder.
|
||||||
# sphinx-quickstart on {{ now }}.
|
|
||||||
#
|
#
|
||||||
# This file is execfile()d with the current directory set to its
|
# This file does only contain a selection of the most common options. For a
|
||||||
# containing dir.
|
# full list see the documentation:
|
||||||
#
|
# http://www.sphinx-doc.org/en/stable/config
|
||||||
# Note that not all possible configuration values are present in this
|
|
||||||
# autogenerated file.
|
# -- Path setup --------------------------------------------------------------
|
||||||
#
|
|
||||||
# All configuration values have a default; values that are commented out
|
|
||||||
# serve to show the default.
|
|
||||||
|
|
||||||
# If extensions (or modules to document with autodoc) are in another directory,
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
# add these directories to sys.path here. If the directory is relative to the
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
@ -33,7 +26,19 @@ sys.path.insert(0, u'{{ module_path }}')
|
|||||||
{% endif -%}
|
{% endif -%}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
# -- General configuration ------------------------------------------------
|
# -- Project information -----------------------------------------------------
|
||||||
|
|
||||||
|
project = u'{{ project_str }}'
|
||||||
|
copyright = u'{{ copyright_str }}'
|
||||||
|
author = u'{{ author_str }}'
|
||||||
|
|
||||||
|
# The short X.Y version
|
||||||
|
version = u'{{ version_str }}'
|
||||||
|
# The full version, including alpha/beta/rc tags
|
||||||
|
release = u'{{ release_str }}'
|
||||||
|
|
||||||
|
|
||||||
|
# -- General configuration ---------------------------------------------------
|
||||||
|
|
||||||
# If your documentation needs a minimal Sphinx version, state it here.
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
#
|
#
|
||||||
@ -60,20 +65,6 @@ source_suffix = '{{ suffix }}'
|
|||||||
# The master toctree document.
|
# The master toctree document.
|
||||||
master_doc = '{{ master_str }}'
|
master_doc = '{{ master_str }}'
|
||||||
|
|
||||||
# General information about the project.
|
|
||||||
project = u'{{ project_str }}'
|
|
||||||
copyright = u'{{ copyright_str }}'
|
|
||||||
author = u'{{ author_str }}'
|
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
|
||||||
# |version| and |release|, also used in various other places throughout the
|
|
||||||
# built documents.
|
|
||||||
#
|
|
||||||
# The short X.Y version.
|
|
||||||
version = u'{{ version_str }}'
|
|
||||||
# The full version, including alpha/beta/rc tags.
|
|
||||||
release = u'{{ release_str }}'
|
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
#
|
#
|
||||||
@ -90,7 +81,7 @@ exclude_patterns = [{{ exclude_patterns }}]
|
|||||||
pygments_style = 'sphinx'
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTML output ----------------------------------------------
|
# -- Options for HTML output -------------------------------------------------
|
||||||
|
|
||||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
# a list of builtin themes.
|
# a list of builtin themes.
|
||||||
@ -119,13 +110,13 @@ html_static_path = ['{{ dot }}static']
|
|||||||
# html_sidebars = {}
|
# html_sidebars = {}
|
||||||
|
|
||||||
|
|
||||||
# -- Options for HTMLHelp output ------------------------------------------
|
# -- Options for HTMLHelp output ---------------------------------------------
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
# Output file base name for HTML help builder.
|
||||||
htmlhelp_basename = '{{ project_fn }}doc'
|
htmlhelp_basename = '{{ project_fn }}doc'
|
||||||
|
|
||||||
|
|
||||||
# -- Options for LaTeX output ---------------------------------------------
|
# -- Options for LaTeX output ------------------------------------------------
|
||||||
|
|
||||||
latex_elements = {
|
latex_elements = {
|
||||||
# The paper size ('letterpaper' or 'a4paper').
|
# The paper size ('letterpaper' or 'a4paper').
|
||||||
@ -154,7 +145,7 @@ latex_documents = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
# -- Options for manual page output ---------------------------------------
|
# -- Options for manual page output ------------------------------------------
|
||||||
|
|
||||||
# One entry per manual page. List of tuples
|
# One entry per manual page. List of tuples
|
||||||
# (source start file, name, description, authors, manual section).
|
# (source start file, name, description, authors, manual section).
|
||||||
@ -164,7 +155,7 @@ man_pages = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
# -- Options for Texinfo output -------------------------------------------
|
# -- Options for Texinfo output ----------------------------------------------
|
||||||
|
|
||||||
# Grouping the document tree into Texinfo files. List of tuples
|
# Grouping the document tree into Texinfo files. List of tuples
|
||||||
# (source start file, target name, title, author,
|
# (source start file, target name, title, author,
|
||||||
@ -177,7 +168,7 @@ texinfo_documents = [
|
|||||||
{%- if epub %}
|
{%- if epub %}
|
||||||
|
|
||||||
|
|
||||||
# -- Options for Epub output ----------------------------------------------
|
# -- Options for Epub output -------------------------------------------------
|
||||||
|
|
||||||
# Bibliographic Dublin Core info.
|
# Bibliographic Dublin Core info.
|
||||||
epub_title = project
|
epub_title = project
|
||||||
@ -200,18 +191,18 @@ epub_exclude_files = ['search.html']
|
|||||||
{%- if extensions %}
|
{%- if extensions %}
|
||||||
|
|
||||||
|
|
||||||
# -- Extension configuration ----------------------------------------------
|
# -- Extension configuration -------------------------------------------------
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- if 'sphinx.ext.intersphinx' in extensions %}
|
{%- if 'sphinx.ext.intersphinx' in extensions %}
|
||||||
|
|
||||||
# -- Options for intersphinx extension ------------------------------------
|
# -- Options for intersphinx extension ---------------------------------------
|
||||||
|
|
||||||
# Example configuration for intersphinx: refer to the Python standard library.
|
# Example configuration for intersphinx: refer to the Python standard library.
|
||||||
intersphinx_mapping = {'https://docs.python.org/': None}
|
intersphinx_mapping = {'https://docs.python.org/': None}
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
{%- if 'sphinx.ext.todo' in extensions %}
|
{%- if 'sphinx.ext.todo' in extensions %}
|
||||||
|
|
||||||
# -- Options for todo extension -------------------------------------------
|
# -- Options for todo extension ----------------------------------------------
|
||||||
|
|
||||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||||
todo_include_todos = True
|
todo_include_todos = True
|
||||||
|
@ -8,8 +8,9 @@ if "%SPHINXBUILD%" == "" (
|
|||||||
set SPHINXBUILD=sphinx-build
|
set SPHINXBUILD=sphinx-build
|
||||||
)
|
)
|
||||||
set BUILDDIR={{ rbuilddir }}
|
set BUILDDIR={{ rbuilddir }}
|
||||||
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% {{ rsrcdir }}
|
set SOURCEDIR={{ rsrcdir }}
|
||||||
set I18NSPHINXOPTS=%SPHINXOPTS% {{ rsrcdir }}
|
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% %SOURCEDIR%
|
||||||
|
set I18NSPHINXOPTS=%SPHINXOPTS% %SOURCEDIR%
|
||||||
if NOT "%PAPER%" == "" (
|
if NOT "%PAPER%" == "" (
|
||||||
set ALLSPHINXOPTS=-D latex_elements.papersize=%PAPER% %ALLSPHINXOPTS%
|
set ALLSPHINXOPTS=-D latex_elements.papersize=%PAPER% %ALLSPHINXOPTS%
|
||||||
set I18NSPHINXOPTS=-D latex_elements.papersize=%PAPER% %I18NSPHINXOPTS%
|
set I18NSPHINXOPTS=-D latex_elements.papersize=%PAPER% %I18NSPHINXOPTS%
|
||||||
@ -50,7 +51,6 @@ if "%1" == "clean" (
|
|||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
REM Check if sphinx-build is available and fallback to Python version if any
|
REM Check if sphinx-build is available and fallback to Python version if any
|
||||||
%SPHINXBUILD% 1>NUL 2>NUL
|
%SPHINXBUILD% 1>NUL 2>NUL
|
||||||
if errorlevel 9009 goto sphinx_python
|
if errorlevel 9009 goto sphinx_python
|
||||||
@ -74,92 +74,6 @@ if errorlevel 9009 (
|
|||||||
|
|
||||||
:sphinx_ok
|
:sphinx_ok
|
||||||
|
|
||||||
|
|
||||||
if "%1" == "html" (
|
|
||||||
%SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished. The HTML pages are in %BUILDDIR%/html.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "dirhtml" (
|
|
||||||
%SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "singlehtml" (
|
|
||||||
%SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "pickle" (
|
|
||||||
%SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished; now you can process the pickle files.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "json" (
|
|
||||||
%SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished; now you can process the JSON files.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "htmlhelp" (
|
|
||||||
%SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished; now you can run HTML Help Workshop with the ^
|
|
||||||
.hhp project file in %BUILDDIR%/htmlhelp.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "qthelp" (
|
|
||||||
%SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
|
||||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
|
||||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\{{ project_fn }}.qhcp
|
|
||||||
echo.To view the help file:
|
|
||||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\{{ project_fn }}.ghc
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "devhelp" (
|
|
||||||
%SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "epub" (
|
|
||||||
%SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished. The epub file is in %BUILDDIR%/epub.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "latex" (
|
|
||||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "latexpdf" (
|
if "%1" == "latexpdf" (
|
||||||
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
%SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
|
||||||
cd %BUILDDIR%/latex
|
cd %BUILDDIR%/latex
|
||||||
@ -180,96 +94,14 @@ if "%1" == "latexpdfja" (
|
|||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "text" (
|
|
||||||
%SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished. The text files are in %BUILDDIR%/text.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "man" (
|
|
||||||
%SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished. The manual pages are in %BUILDDIR%/man.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "texinfo" (
|
|
||||||
%SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "gettext" (
|
if "%1" == "gettext" (
|
||||||
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
|
%SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
|
||||||
if errorlevel 1 exit /b 1
|
if errorlevel 1 exit /b 1
|
||||||
echo.
|
|
||||||
echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
|
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
if "%1" == "changes" (
|
%SPHINXBUILD% -b %1 %ALLSPHINXOPTS% %BUILDDIR%/%1
|
||||||
%SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.The overview file is in %BUILDDIR%/changes.
|
|
||||||
goto end
|
goto end
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "linkcheck" (
|
|
||||||
%SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Link check complete; look for any errors in the above output ^
|
|
||||||
or in %BUILDDIR%/linkcheck/output.txt.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "doctest" (
|
|
||||||
%SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Testing of doctests in the sources finished, look at the ^
|
|
||||||
results in %BUILDDIR%/doctest/output.txt.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "coverage" (
|
|
||||||
%SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Testing of coverage in the sources finished, look at the ^
|
|
||||||
results in %BUILDDIR%/coverage/python.txt.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "xml" (
|
|
||||||
%SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished. The XML files are in %BUILDDIR%/xml.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "pseudoxml" (
|
|
||||||
%SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
if "%1" == "dummy" (
|
|
||||||
%SPHINXBUILD% -b dummy %ALLSPHINXOPTS% %BUILDDIR%/dummy
|
|
||||||
if errorlevel 1 exit /b 1
|
|
||||||
echo.
|
|
||||||
echo.Build finished. Dummy builder generates no files.
|
|
||||||
goto end
|
|
||||||
)
|
|
||||||
|
|
||||||
:end
|
:end
|
||||||
popd
|
popd
|
||||||
|
@ -504,7 +504,7 @@
|
|||||||
\fancyfoot[LE,RO]{{\py@HeaderFamily\thepage}}
|
\fancyfoot[LE,RO]{{\py@HeaderFamily\thepage}}
|
||||||
\fancyfoot[LO]{{\py@HeaderFamily\nouppercase{\rightmark}}}
|
\fancyfoot[LO]{{\py@HeaderFamily\nouppercase{\rightmark}}}
|
||||||
\fancyfoot[RE]{{\py@HeaderFamily\nouppercase{\leftmark}}}
|
\fancyfoot[RE]{{\py@HeaderFamily\nouppercase{\leftmark}}}
|
||||||
\fancyhead[LE,RO]{{\py@HeaderFamily \@title, \py@release}}
|
\fancyhead[LE,RO]{{\py@HeaderFamily \@title\sphinxheadercomma\py@release}}
|
||||||
\renewcommand{\headrulewidth}{0.4pt}
|
\renewcommand{\headrulewidth}{0.4pt}
|
||||||
\renewcommand{\footrulewidth}{0.4pt}
|
\renewcommand{\footrulewidth}{0.4pt}
|
||||||
% define chaptermark with \@chappos when \@chappos is available for Japanese
|
% define chaptermark with \@chappos when \@chappos is available for Japanese
|
||||||
@ -1401,18 +1401,26 @@
|
|||||||
% \date{}. This allows the date to reflect the document's date and
|
% \date{}. This allows the date to reflect the document's date and
|
||||||
% release to specify the release that is documented.
|
% release to specify the release that is documented.
|
||||||
%
|
%
|
||||||
\newcommand{\py@release}{}
|
\newcommand{\py@release}{\releasename\space\version}
|
||||||
\newcommand{\version}{}
|
\newcommand{\version}{}% part of \py@release, used by title page and headers
|
||||||
\newcommand{\shortversion}{}
|
% \releaseinfo is used on titlepage (sphinxmanual.cls, sphinxhowto.cls)
|
||||||
\newcommand{\releaseinfo}{}
|
\newcommand{\releaseinfo}{}
|
||||||
\newcommand{\releasename}{Release}
|
\newcommand{\setreleaseinfo}[1]{\renewcommand{\releaseinfo}{#1}}
|
||||||
\newcommand{\release}[1]{%
|
% this is inserted via template and #1=release config variable
|
||||||
\renewcommand{\py@release}{\releasename\space\version}%
|
\newcommand{\release}[1]{\renewcommand{\version}{#1}}
|
||||||
\renewcommand{\version}{#1}}
|
% this is defined by template to 'releasename' latex_elements key
|
||||||
\newcommand{\setshortversion}[1]{%
|
\newcommand{\releasename}{}
|
||||||
\renewcommand{\shortversion}{#1}}
|
% Fix issue in case release and releasename deliberately left blank
|
||||||
\newcommand{\setreleaseinfo}[1]{%
|
\newcommand{\sphinxheadercomma}{, }% used in fancyhdr header definition
|
||||||
\renewcommand{\releaseinfo}{#1}}
|
\newcommand{\sphinxifemptyorblank}[1]{%
|
||||||
|
% test after one expansion of macro #1 if contents is empty or spaces
|
||||||
|
\if&\expandafter\@firstofone\detokenize\expandafter{#1}&%
|
||||||
|
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}%
|
||||||
|
\AtBeginDocument {%
|
||||||
|
\sphinxifemptyorblank{\releasename}
|
||||||
|
{\sphinxifemptyorblank{\version}{\let\sphinxheadercomma\empty}{}}
|
||||||
|
{}%
|
||||||
|
}%
|
||||||
|
|
||||||
% Allow specification of the author's address separately from the
|
% Allow specification of the author's address separately from the
|
||||||
% author's name. This can be used to format them differently, which
|
% author's name. This can be used to format them differently, which
|
||||||
|
9
sphinx/themes/basic/documentation_options.js_t
Normal file
9
sphinx/themes/basic/documentation_options.js_t
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
var DOCUMENTATION_OPTIONS = {
|
||||||
|
URL_ROOT: '{{ url_root }}',
|
||||||
|
VERSION: '{{ release|e }}',
|
||||||
|
LANGUAGE: '{{ language }}',
|
||||||
|
COLLAPSE_INDEX: false,
|
||||||
|
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
|
||||||
|
HAS_SOURCE: {{ has_source|lower }},
|
||||||
|
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}'
|
||||||
|
};
|
@ -87,16 +87,7 @@
|
|||||||
{%- endmacro %}
|
{%- endmacro %}
|
||||||
|
|
||||||
{%- macro script() %}
|
{%- macro script() %}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript" src="{{ pathto('_static/documentation_options.js', 1) }}"></script>
|
||||||
var DOCUMENTATION_OPTIONS = {
|
|
||||||
URL_ROOT: '{{ url_root }}',
|
|
||||||
VERSION: '{{ release|e }}',
|
|
||||||
COLLAPSE_INDEX: false,
|
|
||||||
FILE_SUFFIX: '{{ '' if no_search_suffix else file_suffix }}',
|
|
||||||
HAS_SOURCE: {{ has_source|lower }},
|
|
||||||
SOURCELINK_SUFFIX: '{{ sourcelink_suffix }}'
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
{%- for scriptfile in script_files %}
|
{%- for scriptfile in script_files %}
|
||||||
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
|
<script type="text/javascript" src="{{ pathto(scriptfile, 1) }}"></script>
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
|
@ -10,12 +10,14 @@
|
|||||||
{%- if pagename != "search" and builder != "singlehtml" %}
|
{%- if pagename != "search" and builder != "singlehtml" %}
|
||||||
<div id="searchbox" style="display: none" role="search">
|
<div id="searchbox" style="display: none" role="search">
|
||||||
<h3>{{ _('Quick search') }}</h3>
|
<h3>{{ _('Quick search') }}</h3>
|
||||||
|
<div class="searchformwrapper">
|
||||||
<form class="search" action="{{ pathto('search') }}" method="get">
|
<form class="search" action="{{ pathto('search') }}" method="get">
|
||||||
<div><input type="text" name="q" /></div>
|
<input type="text" name="q" />
|
||||||
<div><input type="submit" value="{{ _('Go') }}" /></div>
|
<input type="submit" value="{{ _('Go') }}" />
|
||||||
<input type="hidden" name="check_keywords" value="yes" />
|
<input type="hidden" name="check_keywords" value="yes" />
|
||||||
<input type="hidden" name="area" value="default" />
|
<input type="hidden" name="area" value="default" />
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<script type="text/javascript">$('#searchbox').show(0);</script>
|
<script type="text/javascript">$('#searchbox').show(0);</script>
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
@ -82,9 +82,21 @@ div.sphinxsidebar input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
div.sphinxsidebar #searchbox input[type="text"] {
|
div.sphinxsidebar #searchbox input[type="text"] {
|
||||||
width: 170px;
|
float: left;
|
||||||
|
width: 80%;
|
||||||
|
padding: 0.25em;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar #searchbox input[type="submit"] {
|
||||||
|
float: left;
|
||||||
|
width: 20%;
|
||||||
|
border-left: none;
|
||||||
|
padding: 0.25em;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
img {
|
img {
|
||||||
border: 0;
|
border: 0;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
@ -125,12 +125,9 @@ div.sphinxsidebar input {
|
|||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.sphinxsidebar input[type=text]{
|
div.sphinxsidebar .searchformwrapper {
|
||||||
margin-left: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar input[type=submit]{
|
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- body styles ----------------------------------------------------------- */
|
/* -- body styles ----------------------------------------------------------- */
|
||||||
|
@ -148,12 +148,9 @@ div.sphinxsidebar input {
|
|||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.sphinxsidebar input[type=text]{
|
div.sphinxsidebar .searchformwrapper {
|
||||||
margin-left: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
div.sphinxsidebar input[type=submit]{
|
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
|
margin-right: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -- sidebars -------------------------------------------------------------- */
|
/* -- sidebars -------------------------------------------------------------- */
|
||||||
|
@ -9,11 +9,14 @@
|
|||||||
:license: BSD, see LICENSE for details.
|
:license: BSD, see LICENSE for details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
from docutils import nodes
|
from docutils import nodes
|
||||||
from docutils.transforms import Transform, Transformer
|
from docutils.transforms import Transform, Transformer
|
||||||
from docutils.transforms.parts import ContentsFilter
|
from docutils.transforms.parts import ContentsFilter
|
||||||
from docutils.utils import new_document
|
|
||||||
from docutils.transforms.universal import SmartQuotes
|
from docutils.transforms.universal import SmartQuotes
|
||||||
|
from docutils.utils import new_document, normalize_language_tag
|
||||||
|
from docutils.utils.smartquotes import smartchars
|
||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.locale import _
|
from sphinx.locale import _
|
||||||
@ -333,12 +336,54 @@ class SphinxContentsFilter(ContentsFilter):
|
|||||||
raise nodes.SkipNode
|
raise nodes.SkipNode
|
||||||
|
|
||||||
|
|
||||||
class SphinxSmartQuotes(SmartQuotes):
|
class SphinxSmartQuotes(SmartQuotes, SphinxTransform):
|
||||||
"""
|
"""
|
||||||
Customized SmartQuotes to avoid transform for some extra node types.
|
Customized SmartQuotes to avoid transform for some extra node types.
|
||||||
|
|
||||||
refs: sphinx.parsers.RSTParser
|
refs: sphinx.parsers.RSTParser
|
||||||
"""
|
"""
|
||||||
|
def apply(self):
|
||||||
|
# type: () -> None
|
||||||
|
if not self.is_available():
|
||||||
|
return
|
||||||
|
|
||||||
|
SmartQuotes.apply(self)
|
||||||
|
|
||||||
|
def is_available(self):
|
||||||
|
# type: () -> bool
|
||||||
|
builders = self.config.smartquotes_excludes.get('builders', [])
|
||||||
|
languages = self.config.smartquotes_excludes.get('languages', [])
|
||||||
|
|
||||||
|
if self.document.settings.smart_quotes is False:
|
||||||
|
# disabled by 3rd party extension (workaround)
|
||||||
|
return False
|
||||||
|
elif self.config.smartquotes is False:
|
||||||
|
# disabled by confval smartquotes
|
||||||
|
return False
|
||||||
|
elif self.app.builder.name in builders:
|
||||||
|
# disabled by confval smartquotes_excludes['builders']
|
||||||
|
return False
|
||||||
|
elif self.config.language in languages:
|
||||||
|
# disabled by confval smartquotes_excludes['languages']
|
||||||
|
return False
|
||||||
|
|
||||||
|
# confirm selected language supports smart_quotes or not
|
||||||
|
language = self.env.settings['language_code']
|
||||||
|
for tag in normalize_language_tag(language):
|
||||||
|
if tag in smartchars.quotes:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def smartquotes_action(self):
|
||||||
|
# type: () -> unicode
|
||||||
|
"""A smartquotes_action setting for SmartQuotes.
|
||||||
|
|
||||||
|
Users can change this setting through :confval:`smartquotes_action`.
|
||||||
|
"""
|
||||||
|
return self.config.smartquotes_action
|
||||||
|
|
||||||
def get_tokens(self, txtnodes):
|
def get_tokens(self, txtnodes):
|
||||||
# A generator that yields ``(texttype, nodetext)`` tuples for a list
|
# A generator that yields ``(texttype, nodetext)`` tuples for a list
|
||||||
# of "Text" nodes (interface to ``smartquotes.educate_tokens()``).
|
# of "Text" nodes (interface to ``smartquotes.educate_tokens()``).
|
||||||
@ -348,3 +393,21 @@ class SphinxSmartQuotes(SmartQuotes):
|
|||||||
for txtnode in txtnodes:
|
for txtnode in txtnodes:
|
||||||
notsmartquotable = not is_smartquotable(txtnode)
|
notsmartquotable = not is_smartquotable(txtnode)
|
||||||
yield (texttype[notsmartquotable], txtnode.astext())
|
yield (texttype[notsmartquotable], txtnode.astext())
|
||||||
|
|
||||||
|
|
||||||
|
class ManpageLink(SphinxTransform):
|
||||||
|
"""Find manpage section numbers and names"""
|
||||||
|
default_priority = 999
|
||||||
|
|
||||||
|
def apply(self):
|
||||||
|
for node in self.document.traverse(addnodes.manpage):
|
||||||
|
manpage = ' '.join([str(x) for x in node.children
|
||||||
|
if isinstance(x, nodes.Text)])
|
||||||
|
pattern = r'^(?P<path>(?P<page>.+)[\(\.](?P<section>[1-9]\w*)?\)?)$' # noqa
|
||||||
|
info = {'path': manpage,
|
||||||
|
'page': manpage,
|
||||||
|
'section': ''}
|
||||||
|
r = re.match(pattern, manpage)
|
||||||
|
if r:
|
||||||
|
info = r.groupdict()
|
||||||
|
node.attributes.update(info)
|
||||||
|
@ -50,7 +50,7 @@ def publish_msgstr(app, source, source_path, source_line, config, settings):
|
|||||||
:rtype: docutils.nodes.document
|
:rtype: docutils.nodes.document
|
||||||
"""
|
"""
|
||||||
from sphinx.io import SphinxI18nReader
|
from sphinx.io import SphinxI18nReader
|
||||||
reader = SphinxI18nReader()
|
reader = SphinxI18nReader(app)
|
||||||
reader.set_lineno_for_reporter(source_line)
|
reader.set_lineno_for_reporter(source_line)
|
||||||
parser = app.registry.create_source_parser(app, '')
|
parser = app.registry.create_source_parser(app, '')
|
||||||
doc = reader.read(
|
doc = reader.read(
|
||||||
|
@ -18,7 +18,7 @@ from contextlib import contextmanager
|
|||||||
|
|
||||||
import docutils
|
import docutils
|
||||||
from docutils.languages import get_language
|
from docutils.languages import get_language
|
||||||
from docutils.statemachine import ViewList
|
from docutils.statemachine import StateMachine, ViewList
|
||||||
from docutils.parsers.rst import directives, roles, convert_directive_function
|
from docutils.parsers.rst import directives, roles, convert_directive_function
|
||||||
from docutils.utils import Reporter
|
from docutils.utils import Reporter
|
||||||
|
|
||||||
@ -31,8 +31,9 @@ report_re = re.compile('^(.+?:(?:\\d+)?): \\((DEBUG|INFO|WARNING|ERROR|SEVERE)/(
|
|||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
from typing import Any, Callable, Iterator, List, Tuple # NOQA
|
from typing import Any, Callable, Generator, Iterator, List, Tuple # NOQA
|
||||||
from docutils import nodes # NOQA
|
from docutils import nodes # NOQA
|
||||||
|
from docutils.statemachine import State # NOQA
|
||||||
from sphinx.environment import BuildEnvironment # NOQA
|
from sphinx.environment import BuildEnvironment # NOQA
|
||||||
from sphinx.io import SphinxFileInput # NOQA
|
from sphinx.io import SphinxFileInput # NOQA
|
||||||
|
|
||||||
@ -216,3 +217,22 @@ def directive_helper(obj, has_content=None, argument_spec=None, **option_spec):
|
|||||||
raise ExtensionError(__('when adding directive classes, no '
|
raise ExtensionError(__('when adding directive classes, no '
|
||||||
'additional arguments may be given'))
|
'additional arguments may be given'))
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def switch_source_input(state, content):
|
||||||
|
# type: (State, ViewList) -> Generator
|
||||||
|
"""Switch current source input of state temporarily."""
|
||||||
|
try:
|
||||||
|
# remember the original ``get_source_and_line()`` method
|
||||||
|
get_source_and_line = state.memo.reporter.get_source_and_line
|
||||||
|
|
||||||
|
# replace it by new one
|
||||||
|
state_machine = StateMachine([], None)
|
||||||
|
state_machine.input_lines = content
|
||||||
|
state.memo.reporter.get_source_and_line = state_machine.get_source_and_line
|
||||||
|
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
# restore the method
|
||||||
|
state.memo.reporter.get_source_and_line = get_source_and_line
|
||||||
|
@ -404,10 +404,18 @@ class Signature(object):
|
|||||||
if annotation == Ellipsis:
|
if annotation == Ellipsis:
|
||||||
return '...'
|
return '...'
|
||||||
if not isinstance(annotation, type):
|
if not isinstance(annotation, type):
|
||||||
return repr(annotation)
|
qualified_name = repr(annotation)
|
||||||
|
if qualified_name.startswith('typing.'): # for typing.Union
|
||||||
|
return qualified_name.split('.', 1)[1]
|
||||||
|
else:
|
||||||
|
return qualified_name
|
||||||
|
|
||||||
qualified_name = (annotation.__module__ + '.' + annotation.__qualname__ # type: ignore
|
if not annotation:
|
||||||
if annotation else repr(annotation))
|
qualified_name = repr(annotation)
|
||||||
|
elif annotation.__module__ == 'typing':
|
||||||
|
qualified_name = annotation.__qualname__ # type: ignore
|
||||||
|
else:
|
||||||
|
qualified_name = (annotation.__module__ + '.' + annotation.__qualname__) # type: ignore # NOQA
|
||||||
|
|
||||||
if annotation.__module__ == 'builtins':
|
if annotation.__module__ == 'builtins':
|
||||||
return annotation.__qualname__ # type: ignore
|
return annotation.__qualname__ # type: ignore
|
||||||
|
@ -53,7 +53,7 @@ VERBOSITY_MAP.update({
|
|||||||
COLOR_MAP = defaultdict(lambda: 'blue') # type: Dict[int, unicode]
|
COLOR_MAP = defaultdict(lambda: 'blue') # type: Dict[int, unicode]
|
||||||
COLOR_MAP.update({
|
COLOR_MAP.update({
|
||||||
logging.ERROR: 'darkred',
|
logging.ERROR: 'darkred',
|
||||||
logging.WARNING: 'darkred',
|
logging.WARNING: 'red',
|
||||||
logging.DEBUG: 'darkgray',
|
logging.DEBUG: 'darkgray',
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -79,6 +79,7 @@ class HTMLTranslator(BaseTranslator):
|
|||||||
self.highlightopts = builder.config.highlight_options
|
self.highlightopts = builder.config.highlight_options
|
||||||
self.highlightlinenothreshold = sys.maxsize
|
self.highlightlinenothreshold = sys.maxsize
|
||||||
self.docnames = [builder.current_docname] # for singlehtml builder
|
self.docnames = [builder.current_docname] # for singlehtml builder
|
||||||
|
self.manpages_url = builder.config.manpages_url
|
||||||
self.protect_literal_text = 0
|
self.protect_literal_text = 0
|
||||||
self.permalink_text = builder.config.html_add_permalinks
|
self.permalink_text = builder.config.html_add_permalinks
|
||||||
# support backwards-compatible setting to a bool
|
# support backwards-compatible setting to a bool
|
||||||
@ -443,7 +444,7 @@ class HTMLTranslator(BaseTranslator):
|
|||||||
location=(self.builder.current_docname, node.line), **highlight_args
|
location=(self.builder.current_docname, node.line), **highlight_args
|
||||||
)
|
)
|
||||||
starttag = self.starttag(node, 'div', suffix='',
|
starttag = self.starttag(node, 'div', suffix='',
|
||||||
CLASS='highlight-%s' % lang)
|
CLASS='highlight-%s notranslate' % lang)
|
||||||
self.body.append(starttag + highlighted + '</div>\n')
|
self.body.append(starttag + highlighted + '</div>\n')
|
||||||
raise nodes.SkipNode
|
raise nodes.SkipNode
|
||||||
|
|
||||||
@ -493,10 +494,10 @@ class HTMLTranslator(BaseTranslator):
|
|||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
if 'kbd' in node['classes']:
|
if 'kbd' in node['classes']:
|
||||||
self.body.append(self.starttag(node, 'kbd', '',
|
self.body.append(self.starttag(node, 'kbd', '',
|
||||||
CLASS='docutils literal'))
|
CLASS='docutils literal notranslate'))
|
||||||
else:
|
else:
|
||||||
self.body.append(self.starttag(node, 'code', '',
|
self.body.append(self.starttag(node, 'code', '',
|
||||||
CLASS='docutils literal'))
|
CLASS='docutils literal notranslate'))
|
||||||
self.protect_literal_text += 1
|
self.protect_literal_text += 1
|
||||||
|
|
||||||
def depart_literal(self, node):
|
def depart_literal(self, node):
|
||||||
@ -816,9 +817,14 @@ class HTMLTranslator(BaseTranslator):
|
|||||||
def visit_manpage(self, node):
|
def visit_manpage(self, node):
|
||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
self.visit_literal_emphasis(node)
|
self.visit_literal_emphasis(node)
|
||||||
|
if self.manpages_url:
|
||||||
|
node['refuri'] = self.manpages_url.format(**node.attributes)
|
||||||
|
self.visit_reference(node)
|
||||||
|
|
||||||
def depart_manpage(self, node):
|
def depart_manpage(self, node):
|
||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
|
if self.manpages_url:
|
||||||
|
self.depart_reference(node)
|
||||||
self.depart_literal_emphasis(node)
|
self.depart_literal_emphasis(node)
|
||||||
|
|
||||||
# overwritten to add even/odd classes
|
# overwritten to add even/odd classes
|
||||||
|
@ -49,6 +49,7 @@ class HTML5Translator(BaseTranslator):
|
|||||||
self.highlightopts = builder.config.highlight_options
|
self.highlightopts = builder.config.highlight_options
|
||||||
self.highlightlinenothreshold = sys.maxsize
|
self.highlightlinenothreshold = sys.maxsize
|
||||||
self.docnames = [builder.current_docname] # for singlehtml builder
|
self.docnames = [builder.current_docname] # for singlehtml builder
|
||||||
|
self.manpages_url = builder.config.manpages_url
|
||||||
self.protect_literal_text = 0
|
self.protect_literal_text = 0
|
||||||
self.permalink_text = builder.config.html_add_permalinks
|
self.permalink_text = builder.config.html_add_permalinks
|
||||||
# support backwards-compatible setting to a bool
|
# support backwards-compatible setting to a bool
|
||||||
@ -389,7 +390,7 @@ class HTML5Translator(BaseTranslator):
|
|||||||
location=(self.builder.current_docname, node.line), **highlight_args
|
location=(self.builder.current_docname, node.line), **highlight_args
|
||||||
)
|
)
|
||||||
starttag = self.starttag(node, 'div', suffix='',
|
starttag = self.starttag(node, 'div', suffix='',
|
||||||
CLASS='highlight-%s' % lang)
|
CLASS='highlight-%s notranslate' % lang)
|
||||||
self.body.append(starttag + highlighted + '</div>\n')
|
self.body.append(starttag + highlighted + '</div>\n')
|
||||||
raise nodes.SkipNode
|
raise nodes.SkipNode
|
||||||
|
|
||||||
@ -439,10 +440,10 @@ class HTML5Translator(BaseTranslator):
|
|||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
if 'kbd' in node['classes']:
|
if 'kbd' in node['classes']:
|
||||||
self.body.append(self.starttag(node, 'kbd', '',
|
self.body.append(self.starttag(node, 'kbd', '',
|
||||||
CLASS='docutils literal'))
|
CLASS='docutils literal notranslate'))
|
||||||
else:
|
else:
|
||||||
self.body.append(self.starttag(node, 'code', '',
|
self.body.append(self.starttag(node, 'code', '',
|
||||||
CLASS='docutils literal'))
|
CLASS='docutils literal notranslate'))
|
||||||
self.protect_literal_text += 1
|
self.protect_literal_text += 1
|
||||||
|
|
||||||
def depart_literal(self, node):
|
def depart_literal(self, node):
|
||||||
@ -758,9 +759,14 @@ class HTML5Translator(BaseTranslator):
|
|||||||
def visit_manpage(self, node):
|
def visit_manpage(self, node):
|
||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
self.visit_literal_emphasis(node)
|
self.visit_literal_emphasis(node)
|
||||||
|
if self.manpages_url:
|
||||||
|
node['refuri'] = self.manpages_url.format(**dict(node))
|
||||||
|
self.visit_reference(node)
|
||||||
|
|
||||||
def depart_manpage(self, node):
|
def depart_manpage(self, node):
|
||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
|
if self.manpages_url:
|
||||||
|
self.depart_reference(node)
|
||||||
self.depart_literal_emphasis(node)
|
self.depart_literal_emphasis(node)
|
||||||
|
|
||||||
# overwritten to add even/odd classes
|
# overwritten to add even/odd classes
|
||||||
|
@ -549,7 +549,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
'author': document.settings.author, # treat as a raw LaTeX code
|
'author': document.settings.author, # treat as a raw LaTeX code
|
||||||
'indexname': _('Index'),
|
'indexname': _('Index'),
|
||||||
})
|
})
|
||||||
if not self.elements['releasename']:
|
if not self.elements['releasename'] and self.elements['release']:
|
||||||
self.elements.update({
|
self.elements.update({
|
||||||
'releasename': _('Release'),
|
'releasename': _('Release'),
|
||||||
})
|
})
|
||||||
@ -1376,6 +1376,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
self.table = Table(node)
|
self.table = Table(node)
|
||||||
if self.next_table_colspec:
|
if self.next_table_colspec:
|
||||||
self.table.colspec = '{%s}\n' % self.next_table_colspec
|
self.table.colspec = '{%s}\n' % self.next_table_colspec
|
||||||
|
if 'colwidths-given' in node.get('classes', []):
|
||||||
|
logger.info('both tabularcolumns and :widths: option are given. '
|
||||||
|
':widths: is ignored.', location=node)
|
||||||
self.next_table_colspec = None
|
self.next_table_colspec = None
|
||||||
|
|
||||||
def depart_table(self, node):
|
def depart_table(self, node):
|
||||||
@ -1853,28 +1856,14 @@ class LaTeXTranslator(nodes.NodeVisitor):
|
|||||||
(node['align'] == 'right' and 'r' or 'l', length or '0pt'))
|
(node['align'] == 'right' and 'r' or 'l', length or '0pt'))
|
||||||
self.context.append(ids + '\\end{wrapfigure}\n')
|
self.context.append(ids + '\\end{wrapfigure}\n')
|
||||||
elif self.in_minipage:
|
elif self.in_minipage:
|
||||||
if ('align' not in node.attributes or
|
|
||||||
node.attributes['align'] == 'center'):
|
|
||||||
self.body.append('\n\\begin{center}')
|
self.body.append('\n\\begin{center}')
|
||||||
self.context.append('\\end{center}\n')
|
self.context.append('\\end{center}\n')
|
||||||
else:
|
else:
|
||||||
self.body.append('\n\\begin{flush%s}' % node.attributes['align'])
|
self.body.append('\n\\begin{figure}[%s]\n\\centering\n' %
|
||||||
self.context.append('\\end{flush%s}\n' % node.attributes['align'])
|
self.elements['figure_align'])
|
||||||
else:
|
|
||||||
if ('align' not in node.attributes or
|
|
||||||
node.attributes['align'] == 'center'):
|
|
||||||
# centering does not add vertical space like center.
|
|
||||||
align = '\n\\centering'
|
|
||||||
align_end = ''
|
|
||||||
else:
|
|
||||||
# TODO non vertical space for other alignments.
|
|
||||||
align = '\\begin{flush%s}' % node.attributes['align']
|
|
||||||
align_end = '\\end{flush%s}' % node.attributes['align']
|
|
||||||
self.body.append('\n\\begin{figure}[%s]%s\n' % (
|
|
||||||
self.elements['figure_align'], align))
|
|
||||||
if any(isinstance(child, nodes.caption) for child in node):
|
if any(isinstance(child, nodes.caption) for child in node):
|
||||||
self.body.append('\\capstart\n')
|
self.body.append('\\capstart\n')
|
||||||
self.context.append(ids + align_end + '\\end{figure}\n')
|
self.context.append(ids + '\\end{figure}\n')
|
||||||
|
|
||||||
def depart_figure(self, node):
|
def depart_figure(self, node):
|
||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
|
@ -183,6 +183,8 @@ class TextTranslator(nodes.NodeVisitor):
|
|||||||
else:
|
else:
|
||||||
self.nl = '\n'
|
self.nl = '\n'
|
||||||
self.sectionchars = builder.config.text_sectionchars
|
self.sectionchars = builder.config.text_sectionchars
|
||||||
|
self.add_secnumbers = builder.config.text_add_secnumbers
|
||||||
|
self.secnumber_suffix = builder.config.text_secnumber_suffix
|
||||||
self.states = [[]] # type: List[List[Tuple[int, Union[unicode, List[unicode]]]]]
|
self.states = [[]] # type: List[List[Tuple[int, Union[unicode, List[unicode]]]]]
|
||||||
self.stateindent = [0]
|
self.stateindent = [0]
|
||||||
self.list_counter = [] # type: List[int]
|
self.list_counter = [] # type: List[int]
|
||||||
@ -307,6 +309,17 @@ class TextTranslator(nodes.NodeVisitor):
|
|||||||
raise nodes.SkipNode
|
raise nodes.SkipNode
|
||||||
self.new_state(0)
|
self.new_state(0)
|
||||||
|
|
||||||
|
def get_section_number_string(self, node):
|
||||||
|
# type: (nodes.Node) -> unicode
|
||||||
|
if isinstance(node.parent, nodes.section):
|
||||||
|
anchorname = '#' + node.parent['ids'][0]
|
||||||
|
numbers = self.builder.secnumbers.get(anchorname)
|
||||||
|
if numbers is None:
|
||||||
|
numbers = self.builder.secnumbers.get('')
|
||||||
|
if numbers is not None:
|
||||||
|
return '.'.join(map(str, numbers)) + self.secnumber_suffix
|
||||||
|
return ''
|
||||||
|
|
||||||
def depart_title(self, node):
|
def depart_title(self, node):
|
||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
if isinstance(node.parent, nodes.section):
|
if isinstance(node.parent, nodes.section):
|
||||||
@ -315,6 +328,8 @@ class TextTranslator(nodes.NodeVisitor):
|
|||||||
char = '^'
|
char = '^'
|
||||||
text = None # type: unicode
|
text = None # type: unicode
|
||||||
text = ''.join(x[1] for x in self.states.pop() if x[0] == -1) # type: ignore
|
text = ''.join(x[1] for x in self.states.pop() if x[0] == -1) # type: ignore
|
||||||
|
if self.add_secnumbers:
|
||||||
|
text = self.get_section_number_string(node) + text
|
||||||
self.stateindent.pop()
|
self.stateindent.pop()
|
||||||
title = ['', text, '%s' % (char * column_width(text)), ''] # type: List[unicode]
|
title = ['', text, '%s' % (char * column_width(text)), ''] # type: List[unicode]
|
||||||
if len(self.states) == 2 and len(self.states[-1]) == 0:
|
if len(self.states) == 2 and len(self.states[-1]) == 0:
|
||||||
@ -987,7 +1002,10 @@ class TextTranslator(nodes.NodeVisitor):
|
|||||||
|
|
||||||
def visit_reference(self, node):
|
def visit_reference(self, node):
|
||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
pass
|
if self.add_secnumbers:
|
||||||
|
numbers = node.get("secnumber")
|
||||||
|
if numbers is not None:
|
||||||
|
self.add_text('.'.join(map(str, numbers)) + self.secnumber_suffix)
|
||||||
|
|
||||||
def depart_reference(self, node):
|
def depart_reference(self, node):
|
||||||
# type: (nodes.Node) -> None
|
# type: (nodes.Node) -> None
|
||||||
|
@ -35,14 +35,6 @@ def pytest_report_header(config):
|
|||||||
sys.version.split()[0])
|
sys.version.split()[0])
|
||||||
|
|
||||||
|
|
||||||
def _filter_warnings():
|
|
||||||
def ignore(**kwargs): warnings.filterwarnings('ignore', **kwargs)
|
|
||||||
|
|
||||||
ignore(category=DeprecationWarning, module='site') # virtualenv
|
|
||||||
ignore(category=PendingDeprecationWarning, module=r'_pytest\..*')
|
|
||||||
ignore(category=ImportWarning, module='pkgutil')
|
|
||||||
|
|
||||||
|
|
||||||
def _initialize_test_directory(session):
|
def _initialize_test_directory(session):
|
||||||
testroot = os.path.join(str(session.config.rootdir), 'tests')
|
testroot = os.path.join(str(session.config.rootdir), 'tests')
|
||||||
tempdir = os.path.abspath(os.getenv('SPHINX_TEST_TEMPDIR',
|
tempdir = os.path.abspath(os.getenv('SPHINX_TEST_TEMPDIR',
|
||||||
@ -58,5 +50,4 @@ def _initialize_test_directory(session):
|
|||||||
|
|
||||||
|
|
||||||
def pytest_sessionstart(session):
|
def pytest_sessionstart(session):
|
||||||
_filter_warnings()
|
|
||||||
_initialize_test_directory(session)
|
_initialize_test_directory(session)
|
||||||
|
@ -21,6 +21,7 @@ from docutils.statemachine import ViewList
|
|||||||
|
|
||||||
from sphinx.ext.autodoc import AutoDirective, add_documenter, \
|
from sphinx.ext.autodoc import AutoDirective, add_documenter, \
|
||||||
ModuleLevelDocumenter, FunctionDocumenter, cut_lines, between, ALL
|
ModuleLevelDocumenter, FunctionDocumenter, cut_lines, between, ALL
|
||||||
|
from sphinx.util import logging
|
||||||
|
|
||||||
app = None
|
app = None
|
||||||
|
|
||||||
@ -47,7 +48,7 @@ directive = options = None
|
|||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def setup_test():
|
def setup_test():
|
||||||
global options, directive
|
global options, directive
|
||||||
global processed_docstrings, processed_signatures, _warnings
|
global processed_docstrings, processed_signatures
|
||||||
|
|
||||||
options = Struct(
|
options = Struct(
|
||||||
inherited_members = False,
|
inherited_members = False,
|
||||||
@ -70,24 +71,17 @@ def setup_test():
|
|||||||
env = app.builder.env,
|
env = app.builder.env,
|
||||||
genopt = options,
|
genopt = options,
|
||||||
result = ViewList(),
|
result = ViewList(),
|
||||||
warn = warnfunc,
|
|
||||||
filename_set = set(),
|
filename_set = set(),
|
||||||
)
|
)
|
||||||
|
|
||||||
processed_docstrings = []
|
processed_docstrings = []
|
||||||
processed_signatures = []
|
processed_signatures = []
|
||||||
_warnings = []
|
|
||||||
|
|
||||||
|
|
||||||
_warnings = []
|
|
||||||
processed_docstrings = []
|
processed_docstrings = []
|
||||||
processed_signatures = []
|
processed_signatures = []
|
||||||
|
|
||||||
|
|
||||||
def warnfunc(msg):
|
|
||||||
_warnings.append(msg)
|
|
||||||
|
|
||||||
|
|
||||||
def process_docstring(app, what, name, obj, options, lines):
|
def process_docstring(app, what, name, obj, options, lines):
|
||||||
processed_docstrings.append((what, name))
|
processed_docstrings.append((what, name))
|
||||||
if name == 'bar':
|
if name == 'bar':
|
||||||
@ -111,20 +105,21 @@ def skip_member(app, what, name, obj, skip, options):
|
|||||||
|
|
||||||
@pytest.mark.usefixtures('setup_test')
|
@pytest.mark.usefixtures('setup_test')
|
||||||
def test_generate():
|
def test_generate():
|
||||||
|
logging.setup(app, app._status, app._warning)
|
||||||
|
|
||||||
def assert_warns(warn_str, objtype, name, **kw):
|
def assert_warns(warn_str, objtype, name, **kw):
|
||||||
inst = AutoDirective._registry[objtype](directive, name)
|
inst = app.registry.documenters[objtype](directive, name)
|
||||||
inst.generate(**kw)
|
inst.generate(**kw)
|
||||||
assert len(directive.result) == 0, directive.result
|
assert len(directive.result) == 0, directive.result
|
||||||
assert len(_warnings) == 1, _warnings
|
assert warn_str in app._warning.getvalue()
|
||||||
assert warn_str in _warnings[0], _warnings
|
app._warning.truncate(0)
|
||||||
del _warnings[:]
|
|
||||||
|
|
||||||
def assert_works(objtype, name, **kw):
|
def assert_works(objtype, name, **kw):
|
||||||
inst = AutoDirective._registry[objtype](directive, name)
|
inst = app.registry.documenters[objtype](directive, name)
|
||||||
inst.generate(**kw)
|
inst.generate(**kw)
|
||||||
assert directive.result
|
assert directive.result
|
||||||
# print '\n'.join(directive.result)
|
# print '\n'.join(directive.result)
|
||||||
assert len(_warnings) == 0, _warnings
|
assert app._warning.getvalue() == ''
|
||||||
del directive.result[:]
|
del directive.result[:]
|
||||||
|
|
||||||
def assert_processes(items, objtype, name, **kw):
|
def assert_processes(items, objtype, name, **kw):
|
||||||
@ -134,18 +129,18 @@ def test_generate():
|
|||||||
assert set(processed_docstrings) | set(processed_signatures) == set(items)
|
assert set(processed_docstrings) | set(processed_signatures) == set(items)
|
||||||
|
|
||||||
def assert_result_contains(item, objtype, name, **kw):
|
def assert_result_contains(item, objtype, name, **kw):
|
||||||
inst = AutoDirective._registry[objtype](directive, name)
|
inst = app.registry.documenters[objtype](directive, name)
|
||||||
inst.generate(**kw)
|
inst.generate(**kw)
|
||||||
# print '\n'.join(directive.result)
|
# print '\n'.join(directive.result)
|
||||||
assert len(_warnings) == 0, _warnings
|
assert app._warning.getvalue() == ''
|
||||||
assert item in directive.result
|
assert item in directive.result
|
||||||
del directive.result[:]
|
del directive.result[:]
|
||||||
|
|
||||||
def assert_order(items, objtype, name, member_order, **kw):
|
def assert_order(items, objtype, name, member_order, **kw):
|
||||||
inst = AutoDirective._registry[objtype](directive, name)
|
inst = app.registry.documenters[objtype](directive, name)
|
||||||
inst.options.member_order = member_order
|
inst.options.member_order = member_order
|
||||||
inst.generate(**kw)
|
inst.generate(**kw)
|
||||||
assert len(_warnings) == 0, _warnings
|
assert app._warning.getvalue() == ''
|
||||||
items = list(reversed(items))
|
items = list(reversed(items))
|
||||||
lineiter = iter(directive.result)
|
lineiter = iter(directive.result)
|
||||||
# for line in directive.result:
|
# for line in directive.result:
|
||||||
|
0
tests/roots/test-apidoc-toc/mypackage/__init__.py
Normal file
0
tests/roots/test-apidoc-toc/mypackage/__init__.py
Normal file
16
tests/roots/test-apidoc-toc/mypackage/main.py
Executable file
16
tests/roots/test-apidoc-toc/mypackage/main.py
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
import os
|
||||||
|
|
||||||
|
import mod_resource
|
||||||
|
|
||||||
|
import mod_something
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("Hello, world! -> something returns: {}".format(mod_something.something()))
|
||||||
|
|
||||||
|
res_path = \
|
||||||
|
os.path.join(os.path.dirname(mod_resource.__file__), 'resource.txt')
|
||||||
|
with open(res_path) as f:
|
||||||
|
text = f.read()
|
||||||
|
print("From mod_resource:resource.txt -> {}".format(text))
|
1
tests/roots/test-apidoc-toc/mypackage/no_init/foo.py
Normal file
1
tests/roots/test-apidoc-toc/mypackage/no_init/foo.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
MESSAGE="There's no __init__.py in this folder, hence we should be left out"
|
@ -0,0 +1 @@
|
|||||||
|
This is a text resource to be included in this otherwise empty module. No python contents here.
|
@ -0,0 +1 @@
|
|||||||
|
"Subpackage Something"
|
@ -1,5 +1,8 @@
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
|
:numbered:
|
||||||
|
|
||||||
|
doc1
|
||||||
|
doc2
|
||||||
maxwidth
|
maxwidth
|
||||||
lineblock
|
lineblock
|
||||||
nonascii_title
|
nonascii_title
|
||||||
|
2
tests/roots/test-build-text/doc1.txt
Normal file
2
tests/roots/test-build-text/doc1.txt
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Section A
|
||||||
|
=========
|
9
tests/roots/test-build-text/doc2.txt
Normal file
9
tests/roots/test-build-text/doc2.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Section B
|
||||||
|
=========
|
||||||
|
|
||||||
|
Sub Ba
|
||||||
|
------
|
||||||
|
|
||||||
|
Sub Bb
|
||||||
|
------
|
||||||
|
|
5
tests/roots/test-inheritance/basic_diagram.rst
Normal file
5
tests/roots/test-inheritance/basic_diagram.rst
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Basic Diagram
|
||||||
|
==============
|
||||||
|
|
||||||
|
.. inheritance-diagram::
|
||||||
|
dummy.test
|
6
tests/roots/test-inheritance/conf.py
Normal file
6
tests/roots/test-inheritance/conf.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import sys, os
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
|
extensions = ['sphinx.ext.inheritance_diagram']
|
||||||
|
source_suffix = '.rst'
|
4
tests/roots/test-inheritance/contents.rst
Normal file
4
tests/roots/test-inheritance/contents.rst
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
.. toctree::
|
||||||
|
:glob:
|
||||||
|
|
||||||
|
*
|
@ -0,0 +1,6 @@
|
|||||||
|
Diagram using module with 2 top classes
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
.. inheritance-diagram::
|
||||||
|
dummy.test
|
||||||
|
:top-classes: dummy.test.B, dummy.test.C
|
7
tests/roots/test-inheritance/diagram_w_1_top_class.rst
Normal file
7
tests/roots/test-inheritance/diagram_w_1_top_class.rst
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Diagram using 1 top class
|
||||||
|
=========================
|
||||||
|
|
||||||
|
.. inheritance-diagram::
|
||||||
|
dummy.test
|
||||||
|
:top-classes: dummy.test.B
|
||||||
|
|
9
tests/roots/test-inheritance/diagram_w_2_top_classes.rst
Normal file
9
tests/roots/test-inheritance/diagram_w_2_top_classes.rst
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Diagram using 2 top classes
|
||||||
|
===========================
|
||||||
|
|
||||||
|
.. inheritance-diagram::
|
||||||
|
dummy.test.F
|
||||||
|
dummy.test.D
|
||||||
|
dummy.test.E
|
||||||
|
:top-classes: dummy.test.B, dummy.test.C
|
||||||
|
|
7
tests/roots/test-inheritance/diagram_w_parts.rst
Normal file
7
tests/roots/test-inheritance/diagram_w_parts.rst
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Diagram using the parts option
|
||||||
|
==============================
|
||||||
|
|
||||||
|
.. inheritance-diagram::
|
||||||
|
dummy.test
|
||||||
|
:parts: 1
|
||||||
|
|
0
tests/roots/test-inheritance/dummy/__init__.py
Normal file
0
tests/roots/test-inheritance/dummy/__init__.py
Normal file
30
tests/roots/test-inheritance/dummy/test.py
Normal file
30
tests/roots/test-inheritance/dummy/test.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
"""
|
||||||
|
|
||||||
|
Test with a class diagram like this::
|
||||||
|
|
||||||
|
A
|
||||||
|
/ \
|
||||||
|
B C
|
||||||
|
/ \ / \
|
||||||
|
E D F
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
class A(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class B(A):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class C(A):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class D(B, C):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class E(B):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class F(C):
|
||||||
|
pass
|
||||||
|
|
5
tests/roots/test-manpage_url/conf.py
Normal file
5
tests/roots/test-manpage_url/conf.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
master_doc = 'index'
|
||||||
|
html_theme = 'classic'
|
||||||
|
exclude_patterns = ['_build']
|
3
tests/roots/test-manpage_url/index.rst
Normal file
3
tests/roots/test-manpage_url/index.rst
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
* :manpage:`man(1)`
|
||||||
|
* :manpage:`ls.1`
|
||||||
|
* :manpage:`sphinx`
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user