mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch 'master' into feature-text-secnumbers
This commit is contained in:
commit
b688941b09
@ -6,19 +6,12 @@ environment:
|
||||
|
||||
matrix:
|
||||
- PYTHON: 27
|
||||
DOCUTILS: 0.13.1
|
||||
TEST_IGNORE: --ignore py35
|
||||
- PYTHON: 27
|
||||
DOCUTILS: 0.14
|
||||
TEST_IGNORE: --ignore py35
|
||||
- PYTHON: 36
|
||||
DOCUTILS: 0.14
|
||||
- PYTHON: 36-x64
|
||||
DOCUTILS: 0.14
|
||||
|
||||
install:
|
||||
- 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]
|
||||
|
||||
# No automatic build, just run python tests
|
||||
@ -39,7 +32,7 @@ test_script:
|
||||
if (-not $test_ignore) { $test_ignore = '' }
|
||||
$tests = $env:TEST
|
||||
if (-not $tests) { $tests = '' }
|
||||
& "C:\Python$($env:PYTHON)\python.exe" run.py $test_ignore.Split(' ') --junitxml .junit.xml $tests.Split(' ')
|
||||
& "C:\Python$($env:PYTHON)\python.exe" -m pytest $test_ignore.Split(' ') --junitxml .junit.xml $tests.Split(' ')
|
||||
Pop-Location
|
||||
if ($LastExitCode -eq 1) { Write-Host "Test Failures Occurred, leaving for test result parsing" }
|
||||
elseif ($LastExitCode -ne 0) { Write-Host "Other Error Occurred, aborting"; exit $LastExitCode }
|
||||
|
@ -6,4 +6,6 @@ jobs:
|
||||
working_directory: /sphinx
|
||||
steps:
|
||||
- checkout
|
||||
- run: /python3.4/bin/pip install -U pip setuptools
|
||||
- run: /python3.4/bin/pip install -U .[test,websupport]
|
||||
- run: make test PYTHON=/python3.4/bin/python
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -13,6 +13,7 @@ TAGS
|
||||
.tox
|
||||
.venv
|
||||
.coverage
|
||||
htmlcov
|
||||
.DS_Store
|
||||
sphinx/pycode/Grammar*pickle
|
||||
distribute-*
|
||||
|
64
.travis.yml
64
.travis.yml
@ -2,46 +2,48 @@ language: python
|
||||
sudo: false
|
||||
dist: trusty
|
||||
cache: pip
|
||||
python:
|
||||
- "pypy-5.4.1"
|
||||
- "3.6"
|
||||
- "3.5"
|
||||
- "3.4"
|
||||
- "2.7"
|
||||
- "nightly"
|
||||
|
||||
env:
|
||||
global:
|
||||
- TEST='-v --durations 25'
|
||||
- PYTHONFAULTHANDLER=x
|
||||
- PYTHONWARNINGS=all
|
||||
- SKIP_LATEX_BUILD=1
|
||||
matrix:
|
||||
- DOCUTILS=0.13.1
|
||||
- DOCUTILS=0.14
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- python: "3.4"
|
||||
env: DOCUTILS=0.13.1
|
||||
- python: "3.5"
|
||||
env: DOCUTILS=0.13.1
|
||||
- python: "3.6"
|
||||
env: DOCUTILS=0.13.1
|
||||
- python: nightly
|
||||
env: DOCUTILS=0.13.1
|
||||
- python: "pypy-5.4.1"
|
||||
env: DOCUTILS=0.13.1
|
||||
include:
|
||||
- python: 'pypy'
|
||||
env: TOXENV=pypy
|
||||
- python: '2.7'
|
||||
env:
|
||||
- TOXENV=du13
|
||||
- PYTEST_ADDOPTS = --cov sphinx --cov-append --cov-config setup.cfg
|
||||
- python: '3.4'
|
||||
env: TOXENV=py34
|
||||
- python: '3.5'
|
||||
env: TOXENV=py35
|
||||
- python: '3.6'
|
||||
env:
|
||||
- TOXENV=py36
|
||||
- PYTEST_ADDOPTS = --cov sphinx --cov-append --cov-config setup.cfg
|
||||
- python: 'nightly'
|
||||
env: TOXENV=py37
|
||||
- python: '3.6'
|
||||
env: TOXENV=docs
|
||||
- python: '3.6'
|
||||
env: TOXENV=mypy
|
||||
- python: '2.7'
|
||||
env: TOXENV=flake8
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- graphviz
|
||||
- imagemagick
|
||||
|
||||
install:
|
||||
- pip install -U pip setuptools
|
||||
- pip install docutils==$DOCUTILS
|
||||
- pip install .[test,websupport]
|
||||
- pip install flake8
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == '3.6' ]]; then python3.6 -m pip install mypy typed-ast; fi
|
||||
- pip install -U tox codecov
|
||||
|
||||
script:
|
||||
- flake8
|
||||
- if [[ $TRAVIS_PYTHON_VERSION == '3.6' ]]; then make type-check test-async; fi
|
||||
- if [[ $TRAVIS_PYTHON_VERSION != '3.6' ]]; then make test; fi
|
||||
- tox -- -v
|
||||
|
||||
after_success:
|
||||
- codecov
|
||||
|
1
AUTHORS
1
AUTHORS
@ -18,6 +18,7 @@ Other co-maintainers:
|
||||
Other contributors, listed alphabetically, are:
|
||||
|
||||
* Alastair Houghton -- Apple Help builder
|
||||
* Alexander Todorov -- inheritance_diagram tests and improvements
|
||||
* Andi Albrecht -- agogo theme
|
||||
* Jakob Lykke Andersen -- Rewritten C++ domain
|
||||
* Henrique Bastos -- SVG support for graphviz extension
|
||||
|
108
CHANGES
108
CHANGES
@ -1,6 +1,11 @@
|
||||
Release 1.7 (in development)
|
||||
============================
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
* Add ``packaging`` package
|
||||
|
||||
Incompatible changes
|
||||
--------------------
|
||||
|
||||
@ -11,12 +16,31 @@ Incompatible changes
|
||||
package when ``--implicit-namespaces`` option given, not subdirectories of
|
||||
given directory.
|
||||
* #3929: apidoc: Move sphinx.apidoc to sphinx.ext.apidoc
|
||||
* #4226: apidoc: Generate new style makefile (make-mode)
|
||||
* #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)
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
* using a string value for :confval:`html_sidebars` is deprecated and only list
|
||||
values will be accepted at 2.0.
|
||||
* ``format_annotation()`` and ``formatargspec()`` is deprecated. Please use
|
||||
``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
|
||||
--------------
|
||||
@ -24,7 +48,8 @@ Features added
|
||||
* C++, handle ``decltype(auto)``.
|
||||
* #2406: C++, add proper parsing of expressions, including linking of identifiers.
|
||||
* C++, add a ``cpp:expr`` role for inserting inline C++ expressions or types.
|
||||
* #4094: C++, allow empty template argument lists.
|
||||
* C++, support explicit member instantiations with shorthand ``template`` prefix.
|
||||
* C++, make function parameters linkable, like template params.
|
||||
* #3638: Allow to change a label of reference to equation using
|
||||
``math_eqref_format``
|
||||
|
||||
@ -43,10 +68,29 @@ Features added
|
||||
* #4168: improve zh search with jieba
|
||||
* HTML themes can set up default sidebars through ``theme.conf``
|
||||
* #3160: html: Use ``<kdb>`` to represent ``:kbd:`` role
|
||||
* #4212: autosummary: catch all exceptions when importing modules
|
||||
* #4166: Add :confval:`math_numfig` for equation numbering by section (refs:
|
||||
#3991, #4080). Thanks to Oliver Jahn.
|
||||
* #4311: Let LaTeX obey :confval:`numfig_secnum_depth` for figures, tables, and
|
||||
code-blocks
|
||||
* #947: autodoc now supports ignore-module-all to ignore a module's ``__all__``
|
||||
* #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: Add new config values :confval:`text_add_secnumbers` and
|
||||
:confval:`text_secnumber_suffix`
|
||||
|
||||
|
||||
Features removed
|
||||
----------------
|
||||
|
||||
@ -75,19 +119,36 @@ Features removed
|
||||
* ``sphinx.util.nodes.process_only_nodes()``
|
||||
* LaTeX environment ``notice``, use ``sphinxadmonition`` instead
|
||||
* LaTeX ``\sphinxstylethead``, use ``\sphinxstyletheadfamily``
|
||||
* C++, support of function concepts. Thanks to mickk-on-cpp.
|
||||
* Not used and previously not documented LaTeX macros ``\shortversion``
|
||||
and ``\setshortversion``
|
||||
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* #3882: Update the order of files for HTMLHelp and QTHelp
|
||||
* #3962: sphinx-apidoc does not recognize implicit namespace packages correctly
|
||||
* #4094: C++, allow empty template argument lists.
|
||||
* C++, also hyperlink types in the name of declarations with qualified names.
|
||||
* C++, do not add index entries for declarations inside concepts.
|
||||
* C++, support the template disambiguator for dependent names.
|
||||
* #4314: For PDF 'howto' documents, numbering of code-blocks differs from the
|
||||
one of figures and tables
|
||||
* #4330: PDF 'howto' documents have an incoherent default LaTeX tocdepth counter
|
||||
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
|
||||
--------
|
||||
|
||||
* 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
|
||||
@ -102,15 +163,50 @@ Deprecated
|
||||
Features added
|
||||
--------------
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
Release 1.6.6 (released Jan 08, 2018)
|
||||
=====================================
|
||||
|
||||
Features added
|
||||
--------------
|
||||
|
||||
* #4181: autodoc: Sort dictionary keys when possible
|
||||
* ``VerbatimHighlightColor`` is a new
|
||||
:ref:`LaTeX 'sphinxsetup' <latexsphinxsetup>` key (refs: #4285)
|
||||
* 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
|
||||
----------
|
||||
|
||||
* #4334: sphinx-apidoc: Don't generate references to non-existing files in TOC
|
||||
* #4206: latex: reST label between paragraphs loses paragraph break
|
||||
|
||||
Testing
|
||||
--------
|
||||
* #4231: html: Apply fixFirefoxAnchorBug only under Firefox
|
||||
* #4221: napoleon depends on autodoc, but users need to load it manually
|
||||
* #2298: automodule fails to document a class attribute
|
||||
* #4099: C++: properly link class reference to class from inside constructor
|
||||
* #4267: PDF build broken by Unicode U+2116 NUMERO SIGN character
|
||||
* #4249: PDF output: Pygments error highlighting increases line spacing in
|
||||
code blocks
|
||||
* #1238: Support ``:emphasize-lines:`` in PDF output
|
||||
* #4279: Sphinx crashes with pickling error when run with multiple processes and
|
||||
remote image
|
||||
* #1421: Respect the quiet flag in sphinx-quickstart
|
||||
* #4281: Race conditions when creating output directory
|
||||
* #4315: For PDF 'howto' documents, ``latex_toplevel_sectioning='part'`` generates
|
||||
``\chapter`` commands
|
||||
* #4214: Two todolist directives break sphinx-1.6.5
|
||||
* Fix links to external option docs with intersphinx (refs: #3769)
|
||||
* #4091: Private members not documented without :undoc-members:
|
||||
|
||||
Release 1.6.5 (released Oct 23, 2017)
|
||||
=====================================
|
||||
|
@ -33,10 +33,10 @@ Bug Reports and Feature Requests
|
||||
|
||||
If you have encountered a problem with Sphinx or have an idea for a new
|
||||
feature, please submit it to the `issue tracker`_ on GitHub or discuss it
|
||||
on the sphinx-dev mailing list.
|
||||
on the `sphinx-dev`_ mailing list.
|
||||
|
||||
For bug reports, please include the output produced during the build process
|
||||
and also the log file Sphinx creates after it encounters an un-handled
|
||||
and also the log file Sphinx creates after it encounters an unhandled
|
||||
exception. The location of this file should be shown towards the end of the
|
||||
error message.
|
||||
|
||||
@ -45,6 +45,7 @@ issue. If possible, try to create a minimal project that produces the error
|
||||
and post that instead.
|
||||
|
||||
.. _`issue tracker`: https://github.com/sphinx-doc/sphinx/issues
|
||||
.. _`sphinx-dev`: mailto:sphinx-dev@googlegroups.com
|
||||
|
||||
|
||||
Contributing to Sphinx
|
||||
@ -58,7 +59,7 @@ of the core developers before it is merged into the main repository.
|
||||
#. Check for open issues or open a fresh issue to start a discussion around a
|
||||
feature idea or a bug.
|
||||
#. If you feel uncomfortable or uncertain about an issue or your changes, feel
|
||||
free to email sphinx-dev@googlegroups.com.
|
||||
free to email the *sphinx-dev* mailing list.
|
||||
#. Fork `the repository`_ on GitHub to start making your changes to the
|
||||
**master** branch for next major version, or **stable** branch for next
|
||||
minor version.
|
||||
@ -98,10 +99,14 @@ These are the basic steps needed to start developing on Sphinx.
|
||||
For new features or other substantial changes that should wait until the
|
||||
next major release, use the ``master`` branch.
|
||||
|
||||
#. Optional: setup a virtual environment. ::
|
||||
#. Setup a virtual environment.
|
||||
|
||||
virtualenv ~/sphinxenv
|
||||
. ~/sphinxenv/bin/activate
|
||||
This is not necessary for unit testing, thanks to ``tox``, but it is
|
||||
necessary if you wish to run ``sphinx-build`` locally or run unit tests
|
||||
without the help of ``tox``. ::
|
||||
|
||||
virtualenv ~/.venv
|
||||
. ~/.venv/bin/activate
|
||||
pip install -e .
|
||||
|
||||
#. Create a new working branch. Choose any name you like. ::
|
||||
@ -112,44 +117,53 @@ These are the basic steps needed to start developing on Sphinx.
|
||||
|
||||
For tips on working with the code, see the `Coding Guide`_.
|
||||
|
||||
#. Test, test, test. Possible steps:
|
||||
#. Test, test, test.
|
||||
|
||||
* Run the unit tests::
|
||||
Testing is best done through ``tox``, which provides a number of targets and
|
||||
allows testing against multiple different Python environments:
|
||||
|
||||
pip install .[test,websupport]
|
||||
make test
|
||||
* To list all possible targets::
|
||||
|
||||
* Again, it's useful to turn on deprecation warnings on so they're shown in
|
||||
the test output::
|
||||
tox -av
|
||||
|
||||
PYTHONWARNINGS=all make test
|
||||
* To run unit tests for a specific Python version, such as 3.6::
|
||||
|
||||
* Arguments to pytest can be passed via tox, e.g. in order to run a
|
||||
tox -e py36
|
||||
|
||||
* To run unit tests for a specific Python version and turn on deprecation
|
||||
warnings on so they're shown in the test output::
|
||||
|
||||
PYTHONWARNINGS=all tox -e py36
|
||||
|
||||
* To run code style and type checks::
|
||||
|
||||
tox -e mypy
|
||||
tox -e flake8
|
||||
|
||||
* Arguments to ``pytest`` can be passed via ``tox``, e.g. in order to run a
|
||||
particular test::
|
||||
|
||||
tox -e py27 tests/test_module.py::test_new_feature
|
||||
tox -e py36 tests/test_module.py::test_new_feature
|
||||
|
||||
* Build the documentation and check the output for different builders::
|
||||
* To build the documentation::
|
||||
|
||||
make docs target="clean html latexpdf"
|
||||
tox -e docs
|
||||
|
||||
* Run code style checks and type checks (type checks require mypy)::
|
||||
* To build the documentation in multiple formats::
|
||||
|
||||
make style-check
|
||||
make type-check
|
||||
tox -e docs -- -b html,latexpdf
|
||||
|
||||
* Run the unit tests under different Python environments using
|
||||
:program:`tox`::
|
||||
You can also test by installing dependencies in your local environment. ::
|
||||
|
||||
pip install tox
|
||||
tox -v
|
||||
pip install .[test]
|
||||
|
||||
* Add a new unit test in the ``tests`` directory if you can.
|
||||
New unit tests should be included in the ``tests`` directory where
|
||||
necessary:
|
||||
|
||||
* For bug fixes, first add a test that fails without your changes and passes
|
||||
after they are applied.
|
||||
|
||||
* Tests that need a sphinx-build run should be integrated in one of the
|
||||
* Tests that need a ``sphinx-build`` run should be integrated in one of the
|
||||
existing test modules if possible. New tests that to ``@with_app`` and
|
||||
then ``build_all`` for a few assertions are not good since *the test suite
|
||||
should not take more than a minute to run*.
|
||||
@ -266,7 +280,7 @@ Debugging Tips
|
||||
code by running the command ``make clean`` or using the
|
||||
:option:`sphinx-build -E` option.
|
||||
|
||||
* Use the :option:`sphinx-build -P` option to run Pdb on exceptions.
|
||||
* Use the :option:`sphinx-build -P` option to run ``pdb`` on exceptions.
|
||||
|
||||
* Use ``node.pformat()`` and ``node.asdom().toxml()`` to generate a printable
|
||||
representation of the document structure.
|
||||
@ -303,14 +317,17 @@ There are a couple reasons that code in Sphinx might be deprecated:
|
||||
no longer needs to support the older version of Python that doesn't include
|
||||
the library, the library will be deprecated in Sphinx.
|
||||
|
||||
As the :ref:`deprecation-policy` describes,
|
||||
the first release of Sphinx that deprecates a feature (``A.B``) should raise a
|
||||
``RemovedInSphinxXXWarning`` (where XX is the Sphinx version where the feature
|
||||
will be removed) when the deprecated feature is invoked. Assuming we have good
|
||||
test coverage, these warnings are converted to errors when running the test
|
||||
suite with warnings enabled: ``python -Wall tests/run.py``. Thus, when adding
|
||||
a ``RemovedInSphinxXXWarning`` you need to eliminate or silence any warnings
|
||||
generated when running the tests.
|
||||
As the :ref:`deprecation-policy` describes, the first release of Sphinx that
|
||||
deprecates a feature (``A.B``) should raise a ``RemovedInSphinxXXWarning``
|
||||
(where ``XX`` is the Sphinx version where the feature will be removed) when the
|
||||
deprecated feature is invoked. Assuming we have good test coverage, these
|
||||
warnings are converted to errors when running the test suite with warnings
|
||||
enabled::
|
||||
|
||||
pytest -Wall
|
||||
|
||||
Thus, when adding a ``RemovedInSphinxXXWarning`` you need to eliminate or
|
||||
silence any warnings generated when running the tests.
|
||||
|
||||
.. _deprecation-policy:
|
||||
|
||||
|
31
EXAMPLES
31
EXAMPLES
@ -34,6 +34,8 @@ Documentation using the alabaster theme
|
||||
* pytest: https://docs.pytest.org/ (customized)
|
||||
* python-apt: https://apt.alioth.debian.org/python-apt-doc/
|
||||
* PyVisfile: https://documen.tician.de/pyvisfile/
|
||||
* Requests: http://www.python-requests.org/
|
||||
* searx: https://asciimoo.github.io/searx/
|
||||
* Tablib: http://docs.python-tablib.org/
|
||||
* urllib3: https://urllib3.readthedocs.io/ (customized)
|
||||
* Werkzeug: http://werkzeug.pocoo.org/docs/ (customized)
|
||||
@ -46,6 +48,7 @@ Documentation using the classic theme
|
||||
* APSW: https://rogerbinns.github.io/apsw/
|
||||
* Arb: http://arblib.org/
|
||||
* Bazaar: http://doc.bazaar.canonical.com/ (customized)
|
||||
* Beautiful Soup: https://www.crummy.com/software/BeautifulSoup/bs4/doc/
|
||||
* Blender: https://docs.blender.org/api/current/
|
||||
* Bugzilla: https://bugzilla.readthedocs.io/
|
||||
* Buildbot: https://docs.buildbot.net/latest/
|
||||
@ -79,6 +82,8 @@ Documentation using the classic theme
|
||||
* Pyevolve: http://pyevolve.sourceforge.net/
|
||||
* Pygame: https://www.pygame.org/docs/ (customized)
|
||||
* PyMQI: https://pythonhosted.org/pymqi/
|
||||
* PyQt4: http://pyqt.sourceforge.net/Docs/PyQt4/ (customized)
|
||||
* PyQt5: http://pyqt.sourceforge.net/Docs/PyQt5/ (customized)
|
||||
* Python 2: https://docs.python.org/2/
|
||||
* Python 3: https://docs.python.org/3/ (customized)
|
||||
* Python Packaging Authority: https://www.pypa.io/ (customized)
|
||||
@ -88,7 +93,7 @@ Documentation using the classic theme
|
||||
* simuPOP: http://simupop.sourceforge.net/manual_release/build/userGuide.html (customized)
|
||||
* Sprox: http://sprox.org/ (customized)
|
||||
* SymPy: http://docs.sympy.org/
|
||||
* TurboGears: https://turbogears.readthedocs.org/ (customized)
|
||||
* TurboGears: https://turbogears.readthedocs.io/ (customized)
|
||||
* tvtk: http://docs.enthought.com/mayavi/tvtk/
|
||||
* Varnish: https://www.varnish-cache.org/docs/ (customized, alabaster for index)
|
||||
* Waf: https://waf.io/apidocs/
|
||||
@ -121,18 +126,25 @@ Documentation using the nature theme
|
||||
|
||||
* Alembic: http://alembic.zzzcomputing.com/
|
||||
* Cython: http://docs.cython.org/
|
||||
* easybuild: https://easybuild.readthedocs.io/
|
||||
* jsFiddle: http://doc.jsfiddle.net/
|
||||
* libLAS: https://www.liblas.org/ (customized)
|
||||
* Lmod: https://lmod.readthedocs.io/
|
||||
* MapServer: http://mapserver.org/ (customized)
|
||||
* Pandas: https://pandas.pydata.org/pandas-docs/stable/
|
||||
* pyglet: https://pyglet.readthedocs.io/ (customized)
|
||||
* Setuptools: https://setuptools.readthedocs.io/
|
||||
* Spring Python: https://docs.spring.io/spring-python/1.2.x/sphinx/html/
|
||||
* StatsModels: http://www.statsmodels.org/ (customized)
|
||||
* Sylli: http://sylli.sourceforge.net/
|
||||
|
||||
Documentation using another builtin theme
|
||||
-----------------------------------------
|
||||
|
||||
* Arcade: http://arcade.academy/ (sphinx_rtd_theme)
|
||||
* Breathe: https://breathe.readthedocs.io/ (haiku)
|
||||
* MPipe: https://vmlaker.github.io/mpipe/ (sphinx13)
|
||||
* NLTK: http://www.nltk.org/ (agogo)
|
||||
* Programmieren mit PyGTK und Glade (German):
|
||||
http://www.florian-diesch.de/doc/python-und-glade/online/ (agogo, customized)
|
||||
* PyPubSub: https://pypubsub.readthedocs.io/ (bizstyle)
|
||||
@ -150,8 +162,10 @@ Documentation using sphinx_rtd_theme
|
||||
* ASE: https://wiki.fysik.dtu.dk/ase/
|
||||
* Autofac: http://docs.autofac.org/
|
||||
* BigchainDB: https://docs.bigchaindb.com/
|
||||
* Blocks: https://blocks.readthedocs.io/
|
||||
* bootstrap-datepicker: https://bootstrap-datepicker.readthedocs.io/
|
||||
* Certbot: https://letsencrypt.readthedocs.io/
|
||||
* Chainer: https://docs.chainer.org/ (customized)
|
||||
* CherryPy: http://docs.cherrypy.org/
|
||||
* Chainer: https://docs.chainer.org/
|
||||
* CodeIgniter: https://www.codeigniter.com/user_guide/
|
||||
@ -178,14 +192,18 @@ Documentation using sphinx_rtd_theme
|
||||
* Idris: http://docs.idris-lang.org/
|
||||
* javasphinx: https://bronto-javasphinx.readthedocs.io/
|
||||
* Julia: https://julia.readthedocs.io/
|
||||
* Jupyter Notebook: https://jupyter-notebook.readthedocs.io/
|
||||
* Lasagne: https://lasagne.readthedocs.io/
|
||||
* Linguistica: https://linguistica-uchicago.github.io/lxa5/
|
||||
* Linux kernel: https://www.kernel.org/doc/html/latest/index.html
|
||||
* MathJax: https://docs.mathjax.org/
|
||||
* MDTraj: http://mdtraj.org/latest/ (customized)
|
||||
* MICrobial Community Analysis (micca): http://micca.org/docs/latest/
|
||||
* MicroPython: https://docs.micropython.org/
|
||||
* Minds: https://www.minds.org/docs/ (customized)
|
||||
* Mink: http://mink.behat.org/
|
||||
* Mockery: http://docs.mockery.io/
|
||||
* mod_wsgi: https://modwsgi.readthedocs.io/
|
||||
* MoinMoin: https://moin-20.readthedocs.io/
|
||||
* Mopidy: https://docs.mopidy.com/
|
||||
* MyHDL: http://docs.myhdl.org/
|
||||
@ -224,13 +242,16 @@ Documentation using sphinx_rtd_theme
|
||||
* Sylius: http://docs.sylius.org/
|
||||
* Tango Controls: https://tango-controls.readthedocs.io/ (customized)
|
||||
* Topshelf: http://docs.topshelf-project.com/
|
||||
* Theano: http://www.deeplearning.net/software/theano/
|
||||
* ThreatConnect: https://docs.threatconnect.com/
|
||||
* Tuleap: https://tuleap.net/doc/en/
|
||||
* TYPO3: https://docs.typo3.org/ (customized)
|
||||
* uWSGI: https://uwsgi-docs.readthedocs.io/
|
||||
* Wagtail: http://docs.wagtail.io/
|
||||
* Web Application Attack and Audit Framework (w3af): http://docs.w3af.org/
|
||||
* Weblate: https://docs.weblate.org/
|
||||
* x265: https://x265.readthedocs.io/
|
||||
* ZeroNet: https://zeronet.readthedocs.io/
|
||||
|
||||
Documentation using sphinx_bootstrap_theme
|
||||
------------------------------------------
|
||||
@ -238,19 +259,21 @@ Documentation using sphinx_bootstrap_theme
|
||||
* Bootstrap Theme: https://ryan-roemer.github.io/sphinx-bootstrap-theme/
|
||||
* C/C++ Software Development with Eclipse: http://eclipsebook.in/
|
||||
* Dataverse: http://guides.dataverse.org/
|
||||
* e-cidadania: http://e-cidadania.readthedocs.org/
|
||||
* e-cidadania: https://e-cidadania.readthedocs.io/
|
||||
* Hangfire: http://docs.hangfire.io/
|
||||
* Hedge: https://documen.tician.de/hedge/
|
||||
* ObsPy: https://docs.obspy.org/
|
||||
* Open Dylan: https://opendylan.org/documentation/
|
||||
* Pootle: http://docs.translatehouse.org/projects/pootle/
|
||||
* PyUblas: https://documen.tician.de/pyublas/
|
||||
* seaborn: https://seaborn.pydata.org/
|
||||
|
||||
Documentation using a custom theme or integrated in a website
|
||||
-------------------------------------------------------------
|
||||
|
||||
* Apache Cassandra: https://cassandra.apache.org/doc/
|
||||
* Astropy: http://docs.astropy.org/
|
||||
* Bokeh: https://bokeh.pydata.org/
|
||||
* Boto 3: https://boto3.readthedocs.io/
|
||||
* CakePHP: https://book.cakephp.org/
|
||||
* CasperJS: http://docs.casperjs.org/
|
||||
@ -263,6 +286,7 @@ Documentation using a custom theme or integrated in a website
|
||||
* Enterprise Toolkit for Acrobat products:
|
||||
https://www.adobe.com/devnet-docs/acrobatetk/
|
||||
* Gameduino: http://excamera.com/sphinx/gameduino/
|
||||
* gensim: https://radimrehurek.com/gensim/
|
||||
* GeoServer: http://docs.geoserver.org/
|
||||
* gevent: http://www.gevent.org/
|
||||
* GHC - Glasgow Haskell Compiler: http://downloads.haskell.org/~ghc/master/users-guide/
|
||||
@ -307,6 +331,7 @@ Documentation using a custom theme or integrated in a website
|
||||
* Sulu: http://docs.sulu.io/
|
||||
* SQLAlchemy: https://docs.sqlalchemy.org/
|
||||
* tinyTiM: http://tinytim.sourceforge.net/docs/2.0/
|
||||
* Twisted: http://twistedmatrix.com/documents/current/
|
||||
* Ubuntu Packaging Guide: http://packaging.ubuntu.com/html/
|
||||
* WebFaction: https://docs.webfaction.com/
|
||||
* WTForms: https://wtforms.readthedocs.io/
|
||||
@ -320,8 +345,10 @@ Homepages and other non-documentation sites
|
||||
* Benoit Boissinot: https://bboissin.appspot.com/ (classic, customized)
|
||||
* Computer Networks, Parallelization, and Simulation Laboratory (CNPSLab):
|
||||
https://lab.miletic.net/ (sphinx_rtd_theme)
|
||||
* Deep Learning Tutorials: http://www.deeplearning.net/tutorial/ (sphinxdoc)
|
||||
* Loyola University Chicago COMP 339-439 Distributed Systems course:
|
||||
http://books.cs.luc.edu/distributedsystems/ (sphinx_bootstrap_theme)
|
||||
* Pylearn2: http://www.deeplearning.net/software/pylearn2/ (sphinxdoc, customized)
|
||||
* SciPy Cookbook: https://scipy-cookbook.readthedocs.io/ (sphinx_rtd_theme)
|
||||
* The Wine Cellar Book: https://www.thewinecellarbook.com/doc/en/ (sphinxdoc)
|
||||
* Thomas Cokelaer's Python, Sphinx and reStructuredText tutorials:
|
||||
|
2
LICENSE
2
LICENSE
@ -1,7 +1,7 @@
|
||||
License for Sphinx
|
||||
==================
|
||||
|
||||
Copyright (c) 2007-2017 by the Sphinx team (see AUTHORS file).
|
||||
Copyright (c) 2007-2018 by the Sphinx team (see AUTHORS file).
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
|
6
Makefile
6
Makefile
@ -69,15 +69,15 @@ reindent:
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
@cd tests; $(PYTHON) run.py --ignore py35 -v $(TEST)
|
||||
@$(PYTHON) -m pytest -v $(TEST)
|
||||
|
||||
.PHONY: test-async
|
||||
test-async:
|
||||
@cd tests; $(PYTHON) run.py -v $(TEST)
|
||||
@echo "This target no longer does anything and will be removed imminently"
|
||||
|
||||
.PHONY: covertest
|
||||
covertest:
|
||||
@cd tests; $(PYTHON) run.py -v --cov=sphinx --junitxml=.junit.xml $(TEST)
|
||||
@$(PYTHON) -m pytest -v --cov=sphinx --junitxml=.junit.xml $(TEST)
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
|
127
README.rst
127
README.rst
@ -1,45 +1,106 @@
|
||||
========
|
||||
Sphinx
|
||||
========
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/sphinx.svg
|
||||
:target: https://pypi.python.org/pypi/Sphinx
|
||||
:alt: Package on PyPi
|
||||
|
||||
.. image:: https://readthedocs.org/projects/sphinx/badge/
|
||||
:target: http://www.sphinx-doc.org/
|
||||
:alt: Documentation Status
|
||||
|
||||
.. image:: https://travis-ci.org/sphinx-doc/sphinx.svg?branch=master
|
||||
:target: https://travis-ci.org/sphinx-doc/sphinx
|
||||
:alt: Build Status (Travis CI)
|
||||
|
||||
=================
|
||||
README for Sphinx
|
||||
=================
|
||||
.. image:: https://ci.appveyor.com/api/projects/status/github/sphinx-doc/sphinx?branch=master&svg=true
|
||||
:target: https://ci.appveyor.com/project/sphinxdoc/sphinx
|
||||
:alt: Build Status (AppVeyor)
|
||||
|
||||
This is the Sphinx documentation generator, see http://www.sphinx-doc.org/.
|
||||
.. image:: https://circleci.com/gh/sphinx-doc/sphinx.svg?style=shield
|
||||
:target: https://circleci.com/gh/sphinx-doc/sphinx
|
||||
:alt: Build Status (CircleCI)
|
||||
|
||||
.. image:: https://codecov.io/gh/sphinx-doc/sphinx/branch/master/graph/badge.svg
|
||||
:target: https://codecov.io/gh/sphinx-doc/sphinx
|
||||
:alt: Code Coverage Status (Codecov)
|
||||
|
||||
Installing
|
||||
==========
|
||||
Sphinx is a tool that makes it easy to create intelligent and beautiful
|
||||
documentation for Python projects (or other documents consisting of multiple
|
||||
reStructuredText sources), written by Georg Brandl. It was originally created
|
||||
for the new Python documentation, and has excellent facilities for Python
|
||||
project documentation, but C/C++ is supported as well, and more languages are
|
||||
planned.
|
||||
|
||||
Install from PyPI to use stable version::
|
||||
Sphinx uses reStructuredText as its markup language, and many of its strengths
|
||||
come from the power and straightforwardness of reStructuredText and its parsing
|
||||
and translating suite, the Docutils.
|
||||
|
||||
Among its features are the following:
|
||||
|
||||
* Output formats: HTML (including derivative formats such as HTML Help, Epub
|
||||
and Qt Help), plain text, manual pages and LaTeX or direct PDF output
|
||||
using rst2pdf
|
||||
* Extensive cross-references: semantic markup and automatic links
|
||||
for functions, classes, glossary terms and similar pieces of information
|
||||
* Hierarchical structure: easy definition of a document tree, with automatic
|
||||
links to siblings, parents and children
|
||||
* Automatic indices: general index as well as a module index
|
||||
* Code handling: automatic highlighting using the Pygments highlighter
|
||||
* Flexible HTML output using the Jinja 2 templating engine
|
||||
* Various extensions are available, e.g. for automatic testing of snippets
|
||||
and inclusion of appropriately formatted docstrings
|
||||
* Setuptools integration
|
||||
|
||||
For more information, refer to the `the documentation`__.
|
||||
|
||||
.. __: http://www.sphinx-doc.org/
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
Sphinx is published on `PyPI`__ and can be installed from there::
|
||||
|
||||
pip install -U sphinx
|
||||
|
||||
Install from PyPI to use beta version::
|
||||
We also publish beta releases::
|
||||
|
||||
pip install -U --pre sphinx
|
||||
|
||||
Install from newest dev version in stable branch::
|
||||
If you wish to install `Sphinx` for development purposes, refer to `the
|
||||
contributors guide`__.
|
||||
|
||||
pip install git+https://github.com/sphinx-doc/sphinx@stable
|
||||
__ https://pypi.python.org/pypi/Sphinx
|
||||
__ CONTRIBUTING.rst
|
||||
|
||||
Install from newest dev version in master branch::
|
||||
Documentation
|
||||
=============
|
||||
|
||||
pip install git+https://github.com/sphinx-doc/sphinx
|
||||
Documentation is available from `sphinx-doc.org`__.
|
||||
|
||||
Install from cloned source::
|
||||
__ http://www.sphinx-doc.org/
|
||||
|
||||
pip install .
|
||||
Testing
|
||||
=======
|
||||
|
||||
Install from cloned source as editable::
|
||||
Continuous testing is provided by `Travis`__ (for unit tests and style checks
|
||||
on Linux), `AppVeyor`__ (for unit tests on Windows), and `CircleCI`__ (for
|
||||
large processes like TeX compilation).
|
||||
|
||||
pip install -e .
|
||||
For information on running tests locally, refer to `the contributors guide`__.
|
||||
|
||||
__ https://travis-ci.org/sphinx-doc/sphinx
|
||||
__ https://ci.appveyor.com/project/sphinxdoc/sphinx
|
||||
__ https://circleci.com/gh/sphinx-doc/sphinx
|
||||
__ CONTRIBUTING.rst
|
||||
|
||||
Contributing
|
||||
============
|
||||
|
||||
Refer to `the contributors guide`__.
|
||||
|
||||
__ CONTRIBUTING.rst
|
||||
|
||||
Release signatures
|
||||
==================
|
||||
@ -48,37 +109,3 @@ Releases are signed with following keys:
|
||||
|
||||
* `498D6B9E <https://pgp.mit.edu/pks/lookup?op=vindex&search=0x102C2C17498D6B9E>`_
|
||||
* `5EBA0E07 <https://pgp.mit.edu/pks/lookup?op=vindex&search=0x1425F8CE5EBA0E07>`_
|
||||
|
||||
Reading the docs
|
||||
================
|
||||
|
||||
You can read them online at <http://www.sphinx-doc.org/>.
|
||||
|
||||
Or, after installing::
|
||||
|
||||
cd doc
|
||||
make html
|
||||
|
||||
Then, direct your browser to ``_build/html/index.html``.
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
To run the tests with the interpreter available as ``python``, use::
|
||||
|
||||
make test
|
||||
|
||||
If you want to use a different interpreter, e.g. ``python3``, use::
|
||||
|
||||
PYTHON=python3 make test
|
||||
|
||||
Continuous testing runs on travis: https://travis-ci.org/sphinx-doc/sphinx
|
||||
|
||||
|
||||
Contributing
|
||||
============
|
||||
|
||||
See `CONTRIBUTING.rst`__
|
||||
|
||||
.. __: CONTRIBUTING.rst
|
||||
|
||||
|
6
doc/_templates/index.html
vendored
6
doc/_templates/index.html
vendored
@ -74,9 +74,9 @@
|
||||
|
||||
<p>{%trans%}
|
||||
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
|
||||
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%}
|
||||
</p>
|
||||
|
||||
@ -106,7 +106,7 @@
|
||||
<h2>{%trans%}Hosting{%endtrans%}</h2>
|
||||
|
||||
<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
|
||||
powerful built-in search that exceeds the possibilities of Sphinx' JavaScript-based
|
||||
offline search.{%endtrans%}</p>
|
||||
|
10
doc/_templates/indexsidebar.html
vendored
10
doc/_templates/indexsidebar.html
vendored
@ -20,12 +20,14 @@ Index</a>, or install it with:{%endtrans%}</p>
|
||||
<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>
|
||||
<div class="subscribeformwrapper">
|
||||
<form action="http://groups.google.com/group/sphinx-users/boxsubscribe"
|
||||
style="padding-left: 0.5em">
|
||||
<input type="text" name="email" value="your@email" style="font-size: 90%; width: 120px"
|
||||
onfocus="$(this).val('');"/>
|
||||
<input type="submit" name="sub" value="Subscribe" style="font-size: 90%; width: 70px"/>
|
||||
class="subscribeform">
|
||||
<input type="text" name="email" value="your@email"
|
||||
onfocus="$(this).val('');" />
|
||||
<input type="submit" name="sub" value="Subscribe" />
|
||||
</form>
|
||||
</div>
|
||||
<p>{%trans%}or come to the <tt>#sphinx-doc</tt> channel on FreeNode.{%endtrans%}</p>
|
||||
<p>{%trans%}You can also open an issue at the
|
||||
<a href="https://github.com/sphinx-doc/sphinx/issues">tracker</a>.{%endtrans%}</p>
|
||||
|
2
doc/_themes/sphinx13/layout.html
vendored
2
doc/_themes/sphinx13/layout.html
vendored
@ -4,7 +4,7 @@
|
||||
|
||||
Sphinx layout template for the sphinxdoc theme.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
#}
|
||||
{%- extends "basic/layout.html" %}
|
||||
|
32
doc/_themes/sphinx13/static/sphinx13.css
vendored
32
doc/_themes/sphinx13/static/sphinx13.css
vendored
@ -4,7 +4,7 @@
|
||||
*
|
||||
* Sphinx stylesheet -- sphinx13 theme.
|
||||
*
|
||||
* :copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
* :copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
* :license: BSD, see LICENSE for details.
|
||||
*
|
||||
*/
|
||||
@ -140,11 +140,37 @@ div.sphinxsidebar .logo img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
div.subscribeformwrapper {
|
||||
display: block;
|
||||
overflow: auto;
|
||||
margin-bottom: 1.2em;
|
||||
}
|
||||
|
||||
div.sphinxsidebar input {
|
||||
border: 1px solid #aaa;
|
||||
font-family: 'Open Sans', 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
|
||||
'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 {
|
||||
@ -281,7 +307,7 @@ tt {
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 2px;
|
||||
color: #333;
|
||||
padding: 1px;
|
||||
padding: 1px 0.2em;
|
||||
}
|
||||
|
||||
tt.descname, tt.descclassname, tt.xref {
|
||||
|
@ -15,7 +15,7 @@ templates_path = ['_templates']
|
||||
exclude_patterns = ['_build']
|
||||
|
||||
project = 'Sphinx'
|
||||
copyright = '2007-2017, Georg Brandl and the Sphinx team'
|
||||
copyright = '2007-2018, Georg Brandl and the Sphinx team'
|
||||
version = sphinx.__display_version__
|
||||
release = version
|
||||
show_authors = True
|
||||
|
124
doc/config.rst
124
doc/config.rst
@ -138,12 +138,10 @@ General configuration
|
||||
|
||||
- ``'library/xml.rst'`` -- ignores the ``library/xml.rst`` file (replaces
|
||||
entry in :confval:`unused_docs`)
|
||||
- ``'library/xml'`` -- ignores the ``library/xml`` directory (replaces entry
|
||||
in :confval:`exclude_trees`)
|
||||
- ``'library/xml'`` -- ignores the ``library/xml`` directory
|
||||
- ``'library/xml*'`` -- ignores all files and directories starting with
|
||||
``library/xml``
|
||||
- ``'**/.svn'`` -- ignores all ``.svn`` directories (replaces entry in
|
||||
:confval:`exclude_dirnames`)
|
||||
- ``'**/.svn'`` -- ignores all ``.svn`` directories
|
||||
|
||||
:confval:`exclude_patterns` is also consulted when looking for static files
|
||||
in :confval:`html_static_path` and :confval:`html_extra_path`.
|
||||
@ -295,6 +293,24 @@ General configuration
|
||||
|
||||
.. 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
|
||||
|
||||
If true, Sphinx will warn about *all* references where the target cannot be
|
||||
@ -315,8 +331,8 @@ General configuration
|
||||
.. confval:: numfig
|
||||
|
||||
If true, figures, tables and code-blocks are automatically numbered if they
|
||||
have a caption. At same time, the `numref` role is enabled. For now, it
|
||||
works only with the HTML builder and LaTeX builder. Default is ``False``.
|
||||
have a caption. The :rst:role:`numref` role is enabled.
|
||||
Obeyed so far only by HTML and LaTeX builders. Default is ``False``.
|
||||
|
||||
.. note::
|
||||
|
||||
@ -339,13 +355,80 @@ General configuration
|
||||
|
||||
.. confval:: numfig_secnum_depth
|
||||
|
||||
The scope of figure numbers, that is, the numfig feature numbers figures
|
||||
in which scope. ``0`` means "whole document". ``1`` means "in a section".
|
||||
Sphinx numbers like x.1, x.2, x.3... ``2`` means "in a subsection". Sphinx
|
||||
numbers like x.x.1, x.x.2, x.x.3..., and so on. Default is ``1``.
|
||||
- if set to ``0``, figures, tables and code-blocks are continuously numbered
|
||||
starting at ``1``.
|
||||
- if ``1`` (default) numbers will be ``x.1``, ``x.2``, ... with ``x``
|
||||
the section number (top level sectioning; no ``x.`` if no section).
|
||||
This naturally applies only if section numbering has been activated via
|
||||
the ``:numbered:`` option of the :rst:dir:`toctree` directive.
|
||||
- ``2`` means that numbers will be ``x.y.1``, ``x.y.2``, ... if located in
|
||||
a sub-section (but still ``x.1``, ``x.2``, ... if located directly under a
|
||||
section and ``1``, ``2``, ... if not in any top level section.)
|
||||
- etc...
|
||||
|
||||
.. versionadded:: 1.3
|
||||
|
||||
.. versionchanged:: 1.7
|
||||
The LaTeX builder obeys this setting (if :confval:`numfig` is set to
|
||||
``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
|
||||
|
||||
If true, Sphinx verifies server certifications. Default is ``True``.
|
||||
@ -777,15 +860,11 @@ that use Sphinx's HTMLWriter class.
|
||||
|
||||
.. confval:: html_use_smartypants
|
||||
|
||||
If true, `SmartyPants <https://daringfireball.net/projects/smartypants/>`_
|
||||
will be used to convert quotes and dashes to typographically correct
|
||||
If true, quotes and dashes are converted to typographically correct
|
||||
entities. Default: ``True``.
|
||||
|
||||
.. deprecated:: 1.6
|
||||
To disable or customize smart quotes, use the Docutils configuration file
|
||||
(``docutils.conf``) instead to set there its `smart_quotes option`_.
|
||||
|
||||
.. _`smart_quotes option`: http://docutils.sourceforge.net/docs/user/config.html#smart-quotes
|
||||
To disable smart quotes, use rather :confval:`smartquotes`.
|
||||
|
||||
.. confval:: html_add_permalinks
|
||||
|
||||
@ -1450,10 +1529,6 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
|
||||
a chapter, but can be confusing because it mixes entries of different
|
||||
depth in one list. The default value is ``True``.
|
||||
|
||||
.. note::
|
||||
|
||||
``epub3`` builder ignores ``epub_tocdup`` option(always ``False``)
|
||||
|
||||
.. confval:: epub_tocscope
|
||||
|
||||
This setting control the scope of the epub table of contents. The setting
|
||||
@ -1615,10 +1690,15 @@ These options influence LaTeX output. See further :doc:`latex`.
|
||||
.. confval:: latex_toplevel_sectioning
|
||||
|
||||
This value determines the topmost sectioning unit. It should be chosen from
|
||||
``part``, ``chapter`` or ``section``. The default is ``None``; the topmost
|
||||
sectioning unit is switched by documentclass. ``section`` is used if
|
||||
``'part'``, ``'chapter'`` or ``'section'``. The default is ``None``;
|
||||
the topmost
|
||||
sectioning unit is switched by documentclass: ``section`` is used if
|
||||
documentclass will be ``howto``, otherwise ``chapter`` will be used.
|
||||
|
||||
Note that if LaTeX uses ``\part`` command, then the numbering of sectioning
|
||||
units one level deep gets off-sync with HTML numbering, because LaTeX
|
||||
numbers continuously ``\chapter`` (or ``\section`` for ``howto``.)
|
||||
|
||||
.. versionadded:: 1.4
|
||||
|
||||
.. confval:: latex_appendices
|
||||
|
@ -138,7 +138,7 @@ own extensions.
|
||||
.. _cmakedomain: https://bitbucket.org/klorenz/sphinxcontrib-cmakedomain
|
||||
.. _GNU Make: http://www.gnu.org/software/make/
|
||||
.. _makedomain: https://bitbucket.org/klorenz/sphinxcontrib-makedomain
|
||||
.. _inlinesyntaxhighlight: http://sphinxcontrib-inlinesyntaxhighlight.readthedocs.org
|
||||
.. _inlinesyntaxhighlight: https://sphinxcontrib-inlinesyntaxhighlight.readthedocs.io/
|
||||
.. _CMake: https://cmake.org
|
||||
.. _domaintools: https://bitbucket.org/klorenz/sphinxcontrib-domaintools
|
||||
.. _restbuilder: https://pypi.python.org/pypi/sphinxcontrib-restbuilder
|
||||
|
@ -720,13 +720,13 @@ a visibility statement (``public``, ``private`` or ``protected``).
|
||||
|
||||
|
||||
.. rst:directive:: .. cpp:concept:: template-parameter-list name
|
||||
.. cpp:concept:: template-parameter-list name()
|
||||
|
||||
.. warning:: The support for concepts is experimental. It is based on the
|
||||
Concepts Technical Specification, and the features may change as the TS evolves.
|
||||
current draft standard and the Concepts Technical Specification.
|
||||
The features may change as they evolve.
|
||||
|
||||
Describe a variable concept or a function concept. Both must have exactly 1
|
||||
template parameter list. The name may be a nested name. Examples::
|
||||
Describe a concept. It must have exactly 1 template parameter list. The name may be a
|
||||
nested name. Example::
|
||||
|
||||
.. cpp:concept:: template<typename It> std::Iterator
|
||||
|
||||
@ -744,12 +744,7 @@ a visibility statement (``public``, ``private`` or ``protected``).
|
||||
- :cpp:expr:`*r`, when :cpp:expr:`r` is dereferenceable.
|
||||
- :cpp:expr:`++r`, with return type :cpp:expr:`It&`, when :cpp:expr:`r` is incrementable.
|
||||
|
||||
.. cpp:concept:: template<typename Cont> std::Container()
|
||||
|
||||
Holder of elements, to which it can provide access via
|
||||
:cpp:concept:`Iterator` s.
|
||||
|
||||
They will render as follows:
|
||||
This will render as follows:
|
||||
|
||||
.. cpp:concept:: template<typename It> std::Iterator
|
||||
|
||||
@ -767,11 +762,6 @@ a visibility statement (``public``, ``private`` or ``protected``).
|
||||
- :cpp:expr:`*r`, when :cpp:expr:`r` is dereferenceable.
|
||||
- :cpp:expr:`++r`, with return type :cpp:expr:`It&`, when :cpp:expr:`r` is incrementable.
|
||||
|
||||
.. cpp:concept:: template<typename Cont> std::Container()
|
||||
|
||||
Holder of elements, to which it can provide access via
|
||||
:cpp:concept:`Iterator` s.
|
||||
|
||||
Options
|
||||
.......
|
||||
|
||||
@ -785,8 +775,9 @@ Some directives support options:
|
||||
Constrained Templates
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. warning:: The support for constrained templates is experimental. It is based on the
|
||||
Concepts Technical Specification, and the features may change as the TS evolves.
|
||||
.. warning:: The support for concepts is experimental. It is based on the
|
||||
current draft standard and the Concepts Technical Specification.
|
||||
The features may change as they evolve.
|
||||
|
||||
.. note:: Sphinx does not currently support ``requires`` clauses.
|
||||
|
||||
|
@ -103,8 +103,10 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
|
||||
will document all non-private member functions and properties (that is,
|
||||
those whose name doesn't start with ``_``).
|
||||
|
||||
For modules, ``__all__`` will be respected when looking for members; the
|
||||
order of the members will also be the order in ``__all__``.
|
||||
For modules, ``__all__`` will be respected when looking for members unless
|
||||
you give the ``ignore-module-all`` flag option. Without
|
||||
``ignore-module-all``, the order of the members will also be the order in
|
||||
``__all__``.
|
||||
|
||||
You can also give an explicit list of members; only these will then be
|
||||
documented::
|
||||
@ -339,7 +341,7 @@ There are also new config values that you can set:
|
||||
This value is a list of autodoc directive flags that should be automatically
|
||||
applied to all autodoc directives. The supported flags are ``'members'``,
|
||||
``'undoc-members'``, ``'private-members'``, ``'special-members'``,
|
||||
``'inherited-members'`` and ``'show-inheritance'``.
|
||||
``'inherited-members'``, ``'show-inheritance'`` and ``'ignore-module-all'``.
|
||||
|
||||
If you set one of these flags in this config value, you can use a negated
|
||||
form, :samp:`'no-{flag}'`, in an autodoc directive, to disable it once.
|
||||
|
@ -80,12 +80,24 @@ a comma-separated list of group names.
|
||||
.. doctest::
|
||||
:pyversion: > 3.3
|
||||
|
||||
The supported operands are ``<``, ``<=``, ``==``, ``>=``, ``>``, and
|
||||
comparison is performed by `distutils.version.LooseVersion
|
||||
<https://www.python.org/dev/peps/pep-0386/#distutils>`__.
|
||||
The following operands are supported:
|
||||
|
||||
* ``~=``: 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
|
||||
|
||||
.. versionchanged:: 1.7
|
||||
|
||||
Supported PEP-440 operands and notations
|
||||
|
||||
Note that like with standard doctests, you have to use ``<BLANKLINE>`` to
|
||||
signal a blank line in the expected output. The ``<BLANKLINE>`` is removed
|
||||
when building presentation output (HTML, LaTeX etc.).
|
||||
|
@ -42,6 +42,54 @@ It adds this directive:
|
||||
.. versionchanged:: 1.5
|
||||
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:
|
||||
|
||||
|
@ -44,6 +44,15 @@ or use Python raw strings (``r"raw"``).
|
||||
|
||||
Example: ``'Eq.{number}'`` is rendered as ``Eq.10``
|
||||
|
||||
.. confval:: math_numfig
|
||||
|
||||
If ``True``, displayed math equations are numbered across pages when
|
||||
:confval:`numfig` is enabled. The :confval:`numfig_secnum_depth` setting
|
||||
is respected. The :rst:role:`eq`, not :rst:role:`numref`, role
|
||||
must be used to reference equation numbers. Default is ``True``.
|
||||
|
||||
.. versionadded:: 1.7
|
||||
|
||||
:mod:`.mathbase` defines these new markup elements:
|
||||
|
||||
.. rst:role:: math
|
||||
@ -85,7 +94,7 @@ or use Python raw strings (``r"raw"``).
|
||||
Normally, equations are not numbered. If you want your equation to get a
|
||||
number, use the ``label`` option. When given, it selects an internal label
|
||||
for the equation, by which it can be cross-referenced, and causes an equation
|
||||
number to be issued. See :rst:role:`eqref` for an example. The numbering
|
||||
number to be issued. See :rst:role:`eq` for an example. The numbering
|
||||
style depends on the output format.
|
||||
|
||||
There is also an option ``nowrap`` that prevents any wrapping of the given
|
||||
@ -102,8 +111,7 @@ or use Python raw strings (``r"raw"``).
|
||||
|
||||
.. rst:role:: eq
|
||||
|
||||
Role for cross-referencing equations via their label. This currently works
|
||||
only within the same document. Example::
|
||||
Role for cross-referencing equations via their label. Example::
|
||||
|
||||
.. math:: e^{i\pi} + 1 = 0
|
||||
:label: euler
|
||||
|
@ -68,8 +68,8 @@ Getting Started
|
||||
|
||||
# conf.py
|
||||
|
||||
# Add autodoc and napoleon to the extensions list
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon']
|
||||
# Add napoleon to the extensions list
|
||||
extensions = ['sphinx.ext.napoleon']
|
||||
|
||||
2. Use `sphinx-apidoc` to build your API documentation::
|
||||
|
||||
@ -246,13 +246,12 @@ Configuration
|
||||
|
||||
Listed below are all the settings used by napoleon and their default
|
||||
values. These settings can be changed in the Sphinx `conf.py` file. Make
|
||||
sure that both "sphinx.ext.autodoc" and "sphinx.ext.napoleon" are
|
||||
enabled in `conf.py`::
|
||||
sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
|
||||
|
||||
# conf.py
|
||||
|
||||
# Add any Sphinx extension module names here, as strings
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon']
|
||||
extensions = ['sphinx.ext.napoleon']
|
||||
|
||||
# Napoleon settings
|
||||
napoleon_google_docstring = True
|
||||
|
@ -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.
|
||||
|
||||
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.
|
||||
|
||||
If you write an extension that you think others will find useful or you think
|
||||
|
@ -15,6 +15,7 @@ Builder API
|
||||
|
||||
.. autoattribute:: name
|
||||
.. autoattribute:: format
|
||||
.. autoattribute:: epilog
|
||||
.. autoattribute:: supported_image_types
|
||||
|
||||
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()
|
||||
# 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)
|
||||
# or
|
||||
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
|
||||
return ``node.children`` from the Directive.
|
||||
|
||||
|
@ -58,7 +58,7 @@ Read the Docs
|
||||
Sphinx. They will host sphinx documentation, along with supporting a number
|
||||
of other features including version support, PDF generation, and more. The
|
||||
`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.
|
||||
|
||||
Epydoc
|
||||
|
@ -3,7 +3,7 @@ Introduction
|
||||
|
||||
This is the documentation for the Sphinx documentation builder. Sphinx is a
|
||||
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
|
||||
possibly subdirectories of docs in there as well), Sphinx can generate a
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
.. _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.
|
||||
|
||||
* 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
|
||||
to Sphinx: `odt2sphinx <https://pypi.python.org/pypi/odt2sphinx/>`_.
|
||||
|
@ -267,6 +267,16 @@ The available styling options
|
||||
``VerbatimBorderColor``
|
||||
default ``{rgb}{0,0,0}``. The frame color, defaults to black.
|
||||
|
||||
``VerbatimHighlightColor``
|
||||
default ``{rgb}{0.878,1,1}``. The color for highlighted lines.
|
||||
|
||||
.. versionadded:: 1.6.6
|
||||
|
||||
.. note::
|
||||
|
||||
Starting with this colour key, and for all others coming next, the actual
|
||||
names declared to "color" or "xcolor" are prefixed with "sphinx".
|
||||
|
||||
``verbatimsep``
|
||||
default ``\fboxsep``. The separation between code lines and the frame.
|
||||
|
||||
@ -288,11 +298,6 @@ The available styling options
|
||||
default ``{rgb}{0,0,0}`` (black). The colour for the two horizontal rules
|
||||
used by Sphinx in LaTeX for styling a :dudir:`note` type admonition.
|
||||
|
||||
.. note::
|
||||
|
||||
The actual colour names declared to "color" or "xcolor" are prefixed with
|
||||
"sphinx".
|
||||
|
||||
``noteborder``, ``hintborder``, ``importantborder``, ``tipborder``
|
||||
default ``0.5pt``. The width of the two horizontal rules.
|
||||
|
||||
@ -441,6 +446,11 @@ Environments
|
||||
.. versionadded:: 1.5
|
||||
options ``verbatimwithframe``, ``verbatimwrapslines``,
|
||||
``verbatimsep``, ``verbatimborder``.
|
||||
.. versionadded:: 1.6.6
|
||||
support for ``:emphasize-lines:`` option
|
||||
.. versionadded:: 1.6.6
|
||||
easier customizability of the formatting via exposed to user LaTeX macros
|
||||
such as ``\sphinxVerbatimHighlightLine``.
|
||||
- the bibliography uses ``sphinxthebibliography`` and the Python Module index
|
||||
as well as the general index both use ``sphinxtheindex``; these environments
|
||||
are wrappers of the ``thebibliography`` and respectively ``theindex``
|
||||
|
@ -91,7 +91,7 @@ Options
|
||||
|
||||
Interpret paths recursively according to PEP-0420.
|
||||
|
||||
.. option:: -M
|
||||
.. option:: -M, --module-first
|
||||
|
||||
Put module documentation before submodule documentation.
|
||||
|
||||
@ -118,6 +118,14 @@ These options are used when :option:`--full` is specified:
|
||||
|
||||
Sets the project release to put in generated files (see :confval:`release`).
|
||||
|
||||
Environment
|
||||
-----------
|
||||
|
||||
.. envvar:: SPHINX_APIDOC_OPTIONS
|
||||
|
||||
A comma-separated list of option to append to generated ``automodule``
|
||||
directives. Defaults to ``members,undoc-members,show-inheritance``.
|
||||
|
||||
See also
|
||||
--------
|
||||
|
||||
|
@ -99,17 +99,16 @@ Options
|
||||
:ref:`builders <builders>`, the following build pipelines are available:
|
||||
|
||||
**latexpdf**
|
||||
Build LaTeX files and run them through :program:`pdflatex`.
|
||||
|
||||
**latexpdfja**
|
||||
Build LaTeX files and run them through :program:`platex/dvipdfmx`.
|
||||
We recommend using ``latexpdf`` instead.
|
||||
Build LaTeX files and run them through :program:`pdflatex`, or as per
|
||||
:confval:`latex_engine` setting.
|
||||
If :confval:`language` is set to ``'ja'``, will use automatically
|
||||
the :program:`platex/dvipdfmx` latex to PDF pipeline.
|
||||
|
||||
**info**
|
||||
Build Texinfo files and run them through :program:`makeinfo`.
|
||||
|
||||
.. important::
|
||||
Sphinx only recognizes the ``-M`` option if it is placed first.
|
||||
Sphinx only recognizes the ``-M`` option if it is placed first.
|
||||
|
||||
.. versionadded:: 1.2.1
|
||||
|
||||
|
@ -121,6 +121,8 @@ emphasize particular lines::
|
||||
.. versionchanged:: 1.3
|
||||
``lineno-start`` has been added.
|
||||
|
||||
.. versionchanged:: 1.6.6
|
||||
LaTeX supports the ``emphasize-lines`` option.
|
||||
|
||||
Includes
|
||||
^^^^^^^^
|
||||
@ -188,8 +190,8 @@ Includes
|
||||
``lines``, the first allowed line having by convention the line number ``1``.
|
||||
|
||||
When lines have been selected in any of the ways described above, the
|
||||
line numbers in ``emphasize-lines`` also refer to the selection, with the
|
||||
first selected line having number ``1``.
|
||||
line numbers in ``emphasize-lines`` refer to those selected lines, counted
|
||||
consecutively starting at ``1``.
|
||||
|
||||
When specifying particular parts of a file to display, it can be useful to
|
||||
display the original line numbers. This can be done using the
|
||||
|
@ -63,7 +63,7 @@ Cross-referencing anything
|
||||
by :rst:role:`doc`, :rst:role:`ref` or :rst:role:`option`.
|
||||
|
||||
Custom objects added to the standard domain by extensions (see
|
||||
:meth:`.add_object_type`) are also searched.
|
||||
:meth:`Sphinx.add_object_type`) are also searched.
|
||||
|
||||
* Then, it looks for objects (targets) in all loaded domains. It is up to
|
||||
the domains how specific a match must be. For example, in the Python
|
||||
@ -227,15 +227,15 @@ Cross-referencing figures by figure number
|
||||
reST labels are used. When you use this role, it will insert a reference to
|
||||
the figure with link text by its figure number like "Fig. 1.1".
|
||||
|
||||
If an explicit link text is given (like usual: ``:numref:`Image of Sphinx (Fig.
|
||||
%s) <my-figure>```), the link caption will be the title of the reference.
|
||||
As a special character, `%s` and `{number}` will be replaced to figure
|
||||
number. `{name}` will be replaced to figure caption.
|
||||
If no explicit link text is given, the value of :confval:`numfig_format` is
|
||||
used to default value of link text.
|
||||
If an explicit link text is given (as usual: ``:numref:`Image of Sphinx (Fig.
|
||||
%s) <my-figure>```), the link caption will serve as title of the reference.
|
||||
As placeholders, `%s` and `{number}` get replaced by the figure
|
||||
number and `{name}` by the figure caption.
|
||||
If no explicit link text is given, the :confval:`numfig_format` setting is
|
||||
used as fall-back default.
|
||||
|
||||
If :confval:`numfig` is ``False``, figures are not numbered.
|
||||
so this role inserts not a reference but labels or link text.
|
||||
If :confval:`numfig` is ``False``, figures are not numbered,
|
||||
so this role inserts not a reference but the label or the link text.
|
||||
|
||||
Cross-referencing other items of interest
|
||||
-----------------------------------------
|
||||
@ -355,7 +355,8 @@ in a different style:
|
||||
.. rst:role:: manpage
|
||||
|
||||
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
|
||||
|
||||
|
@ -323,6 +323,11 @@ following directive exists:
|
||||
Sphinx's merged cells interact well with ``p{width}``, ``\X{a}{b}``, ``Y{f}``
|
||||
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
|
||||
----
|
||||
|
||||
|
34
setup.cfg
34
setup.cfg
@ -1,11 +1,20 @@
|
||||
[metadata]
|
||||
license_file = LICENSE
|
||||
|
||||
[egg_info]
|
||||
tag_build = .dev
|
||||
tag_date = true
|
||||
|
||||
[bdist_wheel]
|
||||
universal = 1
|
||||
|
||||
[aliases]
|
||||
release = egg_info -Db ''
|
||||
upload = upload --sign --identity=36580288
|
||||
|
||||
[build_sphinx]
|
||||
warning-is-error = 1
|
||||
|
||||
[extract_messages]
|
||||
mapping_file = babel.cfg
|
||||
output_file = sphinx/locale/sphinx.pot
|
||||
@ -20,12 +29,6 @@ output_dir = sphinx/locale/
|
||||
domain = sphinx
|
||||
directory = sphinx/locale/
|
||||
|
||||
[bdist_wheel]
|
||||
universal = 1
|
||||
|
||||
[metadata]
|
||||
license_file = LICENSE
|
||||
|
||||
[flake8]
|
||||
max-line-length = 95
|
||||
ignore = E116,E241,E251,E741
|
||||
@ -41,5 +44,20 @@ incremental = True
|
||||
check_untyped_defs = True
|
||||
warn_unused_ignores = True
|
||||
|
||||
[build_sphinx]
|
||||
warning-is-error = 1
|
||||
[tool:pytest]
|
||||
filterwarnings =
|
||||
ignore::DeprecationWarning:docutils.io
|
||||
|
||||
[coverage:run]
|
||||
branch = True
|
||||
source = sphinx
|
||||
|
||||
[coverage:report]
|
||||
exclude_lines =
|
||||
# Have to re-enable the standard pragma
|
||||
pragma: no cover
|
||||
# Don't complain if tests don't hit defensive assertion code:
|
||||
raise NotImplementedError
|
||||
# Don't complain if non-runnable code isn't run:
|
||||
if __name__ == .__main__.:
|
||||
ignore_errors = True
|
||||
|
34
setup.py
34
setup.py
@ -8,34 +8,8 @@ from distutils.cmd import Command
|
||||
|
||||
import sphinx
|
||||
|
||||
long_desc = '''
|
||||
Sphinx is a tool that makes it easy to create intelligent and beautiful
|
||||
documentation for Python projects (or other documents consisting of multiple
|
||||
reStructuredText sources), written by Georg Brandl. It was originally created
|
||||
for the new Python documentation, and has excellent facilities for Python
|
||||
project documentation, but C/C++ is supported as well, and more languages are
|
||||
planned.
|
||||
|
||||
Sphinx uses reStructuredText as its markup language, and many of its strengths
|
||||
come from the power and straightforwardness of reStructuredText and its parsing
|
||||
and translating suite, the Docutils.
|
||||
|
||||
Among its features are the following:
|
||||
|
||||
* Output formats: HTML (including derivative formats such as HTML Help, Epub
|
||||
and Qt Help), plain text, manual pages and LaTeX or direct PDF output
|
||||
using rst2pdf
|
||||
* Extensive cross-references: semantic markup and automatic links
|
||||
for functions, classes, glossary terms and similar pieces of information
|
||||
* Hierarchical structure: easy definition of a document tree, with automatic
|
||||
links to siblings, parents and children
|
||||
* Automatic indices: general index as well as a module index
|
||||
* Code handling: automatic highlighting using the Pygments highlighter
|
||||
* Flexible HTML output using the Jinja 2 templating engine
|
||||
* Various extensions are available, e.g. for automatic testing of snippets
|
||||
and inclusion of appropriately formatted docstrings
|
||||
* Setuptools integration
|
||||
'''
|
||||
with open('README.rst') as f:
|
||||
long_desc = f.read()
|
||||
|
||||
if sys.version_info < (2, 7) or (3, 0) <= sys.version_info < (3, 4):
|
||||
print('ERROR: Sphinx requires at least Python 2.7 or 3.4 to run.')
|
||||
@ -52,6 +26,7 @@ requires = [
|
||||
'imagesize',
|
||||
'requests>=2.0.0',
|
||||
'setuptools',
|
||||
'packaging',
|
||||
'sphinxcontrib-websupport',
|
||||
]
|
||||
|
||||
@ -68,13 +43,14 @@ extras_require = {
|
||||
'whoosh>=2.0',
|
||||
],
|
||||
'test': [
|
||||
'mock',
|
||||
'pytest',
|
||||
'pytest-cov',
|
||||
'html5lib',
|
||||
'flake8',
|
||||
],
|
||||
'test:python_version<"3"': [
|
||||
'enum34',
|
||||
'mock',
|
||||
],
|
||||
'test:python_version>="3"': [
|
||||
'mypy',
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
The Sphinx documentation toolchain.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
The Sphinx documentation toolchain.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
import sys
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Additional docutils nodes.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
This file has moved to :py:mod:`sphinx.ext.apidoc`.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
Gracefully adapted from the TextPress system by Armin.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
@ -19,7 +19,7 @@ import posixpath
|
||||
from os import path
|
||||
from collections import deque
|
||||
|
||||
from six import iteritems
|
||||
from six import iteritems, itervalues
|
||||
from six.moves import cStringIO
|
||||
|
||||
from docutils import nodes
|
||||
@ -33,14 +33,13 @@ from sphinx.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.environment import BuildEnvironment
|
||||
from sphinx.events import EventManager
|
||||
from sphinx.extension import verify_required_extensions
|
||||
from sphinx.io import SphinxStandaloneReader
|
||||
from sphinx.locale import __
|
||||
from sphinx.registry import SphinxComponentRegistry
|
||||
from sphinx.util import pycompat # noqa: F401
|
||||
from sphinx.util import import_object
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.tags import Tags
|
||||
from sphinx.util.osutil import ENOENT
|
||||
from sphinx.util.osutil import ENOENT, ensuredir
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.docutils import is_html5_writer_available, directive_helper
|
||||
from sphinx.util.i18n import find_catalog_source_files
|
||||
@ -54,7 +53,9 @@ if False:
|
||||
from sphinx.domains import Domain, Index # NOQA
|
||||
from sphinx.environment.collectors import EnvironmentCollector # NOQA
|
||||
from sphinx.extension import Extension # NOQA
|
||||
from sphinx.roles import XRefRole # NOQA
|
||||
from sphinx.theming import Theme # NOQA
|
||||
from sphinx.util.typing import RoleFunction # NOQA
|
||||
|
||||
builtin_extensions = (
|
||||
'sphinx.builders.applehelp',
|
||||
@ -83,6 +84,7 @@ builtin_extensions = (
|
||||
'sphinx.directives.code',
|
||||
'sphinx.directives.other',
|
||||
'sphinx.directives.patches',
|
||||
'sphinx.io',
|
||||
'sphinx.parsers',
|
||||
'sphinx.roles',
|
||||
'sphinx.transforms.post_transforms',
|
||||
@ -119,7 +121,6 @@ class Sphinx(object):
|
||||
self.env = None # type: BuildEnvironment
|
||||
self.registry = SphinxComponentRegistry()
|
||||
self.enumerable_nodes = {} # type: Dict[nodes.Node, Tuple[unicode, Callable]] # NOQA
|
||||
self.post_transforms = [] # type: List[Transform]
|
||||
self.html_themes = {} # type: Dict[unicode, unicode]
|
||||
|
||||
self.srcdir = srcdir
|
||||
@ -156,10 +157,6 @@ class Sphinx(object):
|
||||
# status code for command-line application
|
||||
self.statuscode = 0
|
||||
|
||||
if not path.isdir(outdir):
|
||||
logger.info('making output directory...')
|
||||
os.makedirs(outdir)
|
||||
|
||||
# read config
|
||||
self.tags = Tags(tags)
|
||||
self.config = Config(confdir, CONFIG_FILENAME,
|
||||
@ -196,6 +193,10 @@ class Sphinx(object):
|
||||
# preload builder module (before init config values)
|
||||
self.preload_builder(buildername)
|
||||
|
||||
if not path.isdir(outdir):
|
||||
logger.info('making output directory...')
|
||||
ensuredir(outdir)
|
||||
|
||||
# the config file itself can be an extension
|
||||
if self.config.setup:
|
||||
self._setting_up_extension = ['conf.py']
|
||||
@ -337,6 +338,13 @@ class Sphinx(object):
|
||||
(status, self._warncount)))
|
||||
else:
|
||||
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:
|
||||
# delete the saved env to force a fresh build next time
|
||||
envfile = path.join(self.doctreedir, ENV_PICKLE_FILENAME)
|
||||
@ -443,7 +451,6 @@ class Sphinx(object):
|
||||
|
||||
def add_builder(self, builder):
|
||||
# type: (Type[Builder]) -> None
|
||||
logger.debug('[app] adding builder: %r', builder)
|
||||
self.registry.add_builder(builder)
|
||||
|
||||
def add_config_value(self, name, default, rebuild, types=()):
|
||||
@ -463,7 +470,6 @@ class Sphinx(object):
|
||||
|
||||
def set_translator(self, name, translator_class):
|
||||
# type: (unicode, Type[nodes.NodeVisitor]) -> None
|
||||
logger.info(bold(__('Change of translator for the %s builder.') % name))
|
||||
self.registry.add_translator(name, translator_class)
|
||||
|
||||
def add_node(self, node, **kwds):
|
||||
@ -552,39 +558,30 @@ class Sphinx(object):
|
||||
|
||||
def add_domain(self, domain):
|
||||
# type: (Type[Domain]) -> None
|
||||
logger.debug('[app] adding domain: %r', domain)
|
||||
self.registry.add_domain(domain)
|
||||
|
||||
def override_domain(self, domain):
|
||||
# type: (Type[Domain]) -> None
|
||||
logger.debug('[app] overriding domain: %r', domain)
|
||||
self.registry.override_domain(domain)
|
||||
|
||||
def add_directive_to_domain(self, domain, name, obj,
|
||||
has_content=None, argument_spec=None, **option_spec):
|
||||
# type: (unicode, unicode, Any, bool, Any, Any) -> None
|
||||
logger.debug('[app] adding directive to domain: %r',
|
||||
(domain, name, obj, has_content, argument_spec, option_spec))
|
||||
self.registry.add_directive_to_domain(domain, name, obj,
|
||||
has_content, argument_spec, **option_spec)
|
||||
|
||||
def add_role_to_domain(self, domain, name, role):
|
||||
# type: (unicode, unicode, Any) -> None
|
||||
logger.debug('[app] adding role to domain: %r', (domain, name, role))
|
||||
# type: (unicode, unicode, Union[RoleFunction, XRefRole]) -> None
|
||||
self.registry.add_role_to_domain(domain, name, role)
|
||||
|
||||
def add_index_to_domain(self, domain, index):
|
||||
# type: (unicode, Type[Index]) -> None
|
||||
logger.debug('[app] adding index to domain: %r', (domain, index))
|
||||
self.registry.add_index_to_domain(domain, index)
|
||||
|
||||
def add_object_type(self, directivename, rolename, indextemplate='',
|
||||
parse_node=None, ref_nodeclass=None, objname='',
|
||||
doc_field_types=[]):
|
||||
# type: (unicode, unicode, unicode, Callable, nodes.Node, unicode, List) -> None
|
||||
logger.debug('[app] adding object type: %r',
|
||||
(directivename, rolename, indextemplate, parse_node,
|
||||
ref_nodeclass, objname, doc_field_types))
|
||||
self.registry.add_object_type(directivename, rolename, indextemplate, parse_node,
|
||||
ref_nodeclass, objname, doc_field_types)
|
||||
|
||||
@ -601,21 +598,16 @@ class Sphinx(object):
|
||||
def add_crossref_type(self, directivename, rolename, indextemplate='',
|
||||
ref_nodeclass=None, objname=''):
|
||||
# type: (unicode, unicode, unicode, nodes.Node, unicode) -> None
|
||||
logger.debug('[app] adding crossref type: %r',
|
||||
(directivename, rolename, indextemplate, ref_nodeclass,
|
||||
objname))
|
||||
self.registry.add_crossref_type(directivename, rolename,
|
||||
indextemplate, ref_nodeclass, objname)
|
||||
|
||||
def add_transform(self, transform):
|
||||
# type: (Type[Transform]) -> None
|
||||
logger.debug('[app] adding transform: %r', transform)
|
||||
SphinxStandaloneReader.transforms.append(transform)
|
||||
self.registry.add_transform(transform)
|
||||
|
||||
def add_post_transform(self, transform):
|
||||
# type: (Type[Transform]) -> None
|
||||
logger.debug('[app] adding post transform: %r', transform)
|
||||
self.post_transforms.append(transform)
|
||||
self.registry.add_post_transform(transform)
|
||||
|
||||
def add_javascript(self, filename):
|
||||
# type: (unicode) -> None
|
||||
@ -657,15 +649,14 @@ class Sphinx(object):
|
||||
def add_autodocumenter(self, cls):
|
||||
# type: (Any) -> None
|
||||
logger.debug('[app] adding autodocumenter: %r', cls)
|
||||
from sphinx.ext import autodoc
|
||||
autodoc.add_documenter(cls)
|
||||
self.add_directive('auto' + cls.objtype, autodoc.AutoDirective)
|
||||
from sphinx.ext.autodoc.directive import AutodocDirective
|
||||
self.registry.add_documenter(cls.objtype, cls)
|
||||
self.add_directive('auto' + cls.objtype, AutodocDirective)
|
||||
|
||||
def add_autodoc_attrgetter(self, type, getter):
|
||||
# type: (Any, Callable) -> None
|
||||
logger.debug('[app] adding autodoc attrgetter: %r', (type, getter))
|
||||
from sphinx.ext import autodoc
|
||||
autodoc.AutoDirective._special_attrgetters[type] = getter
|
||||
def add_autodoc_attrgetter(self, typ, getter):
|
||||
# type: (Type, Callable[[Any, unicode, Any], Any]) -> None
|
||||
logger.debug('[app] adding autodoc attrgetter: %r', (typ, getter))
|
||||
self.registry.add_autodoc_attrgetter(typ, getter)
|
||||
|
||||
def add_search_language(self, cls):
|
||||
# type: (Any) -> None
|
||||
@ -676,7 +667,6 @@ class Sphinx(object):
|
||||
|
||||
def add_source_parser(self, suffix, parser):
|
||||
# type: (unicode, Parser) -> None
|
||||
logger.debug('[app] adding search source_parser: %r, %r', suffix, parser)
|
||||
self.registry.add_source_parser(suffix, parser)
|
||||
|
||||
def add_env_collector(self, collector):
|
||||
@ -689,6 +679,34 @@ class Sphinx(object):
|
||||
logger.debug('[app] adding HTML theme: %r, %r', name, theme_path)
|
||||
self.html_themes[name] = theme_path
|
||||
|
||||
# ---- other methods -------------------------------------------------
|
||||
def is_parallel_allowed(self, typ):
|
||||
# type: (unicode) -> bool
|
||||
"""Check parallel processing is allowed or not.
|
||||
|
||||
``typ`` is a type of processing; ``'read'`` or ``'write'``.
|
||||
"""
|
||||
if typ == 'read':
|
||||
attrname = 'parallel_read_safe'
|
||||
elif typ == 'write':
|
||||
attrname = 'parallel_write_safe'
|
||||
else:
|
||||
raise ValueError('parallel type %s is not supported' % typ)
|
||||
|
||||
for ext in itervalues(self.extensions):
|
||||
allowed = getattr(ext, attrname, None)
|
||||
if allowed is None:
|
||||
logger.warning(__("the %s extension does not declare if it is safe "
|
||||
"for parallel %sing, assuming it isn't - please "
|
||||
"ask the extension author to check and make it "
|
||||
"explicit"), ext.name, typ)
|
||||
logger.warning('doing serial %s', typ)
|
||||
return False
|
||||
elif not allowed:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class TemplateBridge(object):
|
||||
"""
|
||||
|
@ -5,11 +5,10 @@
|
||||
|
||||
Builder superclass for all builders.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import os
|
||||
from os import path
|
||||
import warnings
|
||||
|
||||
@ -18,13 +17,12 @@ try:
|
||||
except ImportError:
|
||||
multiprocessing = None
|
||||
|
||||
from six import itervalues
|
||||
from docutils import nodes
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.environment.adapters.asset import ImageAdapter
|
||||
from sphinx.util import i18n, path_stabilize, logging, status_iterator
|
||||
from sphinx.util.osutil import SEP, relative_uri
|
||||
from sphinx.util.osutil import SEP, ensuredir, relative_uri
|
||||
from sphinx.util.i18n import find_catalog
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.parallel import ParallelTasks, SerialTasks, make_chunks, \
|
||||
@ -56,6 +54,11 @@ class Builder(object):
|
||||
name = '' # type: unicode
|
||||
#: The builder's output format, or '' if no document output is produced.
|
||||
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
|
||||
# ``app.set_translator()``.
|
||||
default_translator_class = None # type: nodes.NodeVisitor
|
||||
@ -79,8 +82,7 @@ class Builder(object):
|
||||
self.confdir = app.confdir
|
||||
self.outdir = app.outdir
|
||||
self.doctreedir = app.doctreedir
|
||||
if not path.isdir(self.doctreedir):
|
||||
os.makedirs(self.doctreedir)
|
||||
ensuredir(self.doctreedir)
|
||||
|
||||
self.app = app # type: Sphinx
|
||||
self.env = None # type: BuildEnvironment
|
||||
@ -373,15 +375,10 @@ class Builder(object):
|
||||
docnames = set(docnames) & self.env.found_docs
|
||||
|
||||
# determine if we can write in parallel
|
||||
self.parallel_ok = False
|
||||
if parallel_available and self.app.parallel > 1 and self.allow_parallel:
|
||||
self.parallel_ok = True
|
||||
for extension in itervalues(self.app.extensions):
|
||||
if not extension.parallel_write_safe:
|
||||
logger.warning('the %s extension is not safe for parallel '
|
||||
'writing, doing serial write', extension.name)
|
||||
self.parallel_ok = False
|
||||
break
|
||||
self.parallel_ok = self.app.is_parallel_allowed('write')
|
||||
else:
|
||||
self.parallel_ok = False
|
||||
|
||||
# create a task executor to use for misc. "finish-up" tasks
|
||||
# if self.parallel_ok:
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Base class of epub2/epub3 builders.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Build Apple help books.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
@ -75,6 +75,10 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
|
||||
on the ``hiutil`` command line tool.
|
||||
"""
|
||||
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
|
||||
copysource = False
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Changelog builder.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -38,6 +38,7 @@ class ChangesBuilder(Builder):
|
||||
Write a summary with all versionadded/changed directives.
|
||||
"""
|
||||
name = 'changes'
|
||||
epilog = 'The overview file is in %(outdir)s.'
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
.. _Devhelp: http://live.gnome.org/devhelp
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
@ -43,6 +43,10 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
|
||||
Builder that also outputs GNOME Devhelp file.
|
||||
"""
|
||||
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
|
||||
copysource = False
|
||||
|
@ -21,6 +21,8 @@ if False:
|
||||
|
||||
class DummyBuilder(Builder):
|
||||
name = 'dummy'
|
||||
epilog = 'The dummy builder generates no files.'
|
||||
|
||||
allow_parallel = True
|
||||
|
||||
def init(self):
|
||||
|
@ -63,6 +63,7 @@ class Epub3Builder(_epub_base.EpubBuilder):
|
||||
an epub file.
|
||||
"""
|
||||
name = 'epub'
|
||||
epilog = 'The ePub file is in %(outdir)s.'
|
||||
|
||||
supported_remote_images = False
|
||||
template_dir = path.join(package_dir, 'templates', 'epub3')
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
The MessageCatalogBuilder class.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -214,6 +214,7 @@ class MessageCatalogBuilder(I18nBuilder):
|
||||
Builds gettext-style message catalogs (.pot files).
|
||||
"""
|
||||
name = 'gettext'
|
||||
epilog = 'The message catalogs are in %(outdir)s.'
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Several HTML builders.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -153,6 +153,8 @@ class StandaloneHTMLBuilder(Builder):
|
||||
"""
|
||||
name = 'html'
|
||||
format = 'html'
|
||||
epilog = 'The HTML pages are in %(outdir)s.'
|
||||
|
||||
copysource = True
|
||||
allow_parallel = True
|
||||
out_suffix = '.html'
|
||||
@ -274,7 +276,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
# type: () -> Iterator[unicode]
|
||||
cfgdict = dict((confval.name, confval.value) for confval in self.config.filter('html'))
|
||||
self.config_hash = get_stable_hash(cfgdict)
|
||||
self.tags_hash = get_stable_hash(sorted(self.tags)) # type: ignore
|
||||
self.tags_hash = get_stable_hash(sorted(self.tags))
|
||||
old_config_hash = old_tags_hash = ''
|
||||
try:
|
||||
with open(path.join(self.outdir, '.buildinfo')) as fp:
|
||||
@ -1066,6 +1068,8 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
HTML page.
|
||||
"""
|
||||
name = 'singlehtml'
|
||||
epilog = 'The HTML page is in %(outdir)s.'
|
||||
|
||||
copysource = False
|
||||
|
||||
def get_outdated_docs(self): # type: ignore
|
||||
@ -1328,12 +1332,14 @@ class PickleHTMLBuilder(SerializingHTMLBuilder):
|
||||
"""
|
||||
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_dumps_unicode = False
|
||||
additional_dump_args = (pickle.HIGHEST_PROTOCOL,)
|
||||
indexer_format = pickle
|
||||
indexer_dumps_unicode = False
|
||||
name = 'pickle'
|
||||
out_suffix = '.fpickle'
|
||||
globalcontext_filename = 'globalcontext.pickle'
|
||||
searchindex_filename = 'searchindex.pickle'
|
||||
@ -1347,11 +1353,13 @@ class JSONHTMLBuilder(SerializingHTMLBuilder):
|
||||
"""
|
||||
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_dumps_unicode = True
|
||||
indexer_format = jsonimpl
|
||||
indexer_dumps_unicode = True
|
||||
name = 'json'
|
||||
out_suffix = '.fjson'
|
||||
globalcontext_filename = 'globalcontext.json'
|
||||
searchindex_filename = 'searchindex.json'
|
||||
|
@ -6,7 +6,7 @@
|
||||
Build HTML help support files.
|
||||
Parts adapted from Python's Doc/tools/prechm.py.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
@ -174,6 +174,8 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
|
||||
index files. Adapted from the original Doc/tools/prechm.py.
|
||||
"""
|
||||
name = 'htmlhelp'
|
||||
epilog = ('You can now run HTML Help Workshop with the .htp file in '
|
||||
'%(outdir)s.')
|
||||
|
||||
# don't copy the reST source
|
||||
copysource = False
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
LaTeX builder.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -49,6 +49,12 @@ class LaTeXBuilder(Builder):
|
||||
"""
|
||||
name = '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_remote_images = False
|
||||
default_translator_class = LaTeXTranslator
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
The CheckExternalLinksBuilder class.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -90,6 +90,8 @@ class CheckExternalLinksBuilder(Builder):
|
||||
Checks for broken external links.
|
||||
"""
|
||||
name = 'linkcheck'
|
||||
epilog = ('Look for any errors in the above output or in '
|
||||
'%(outdir)s/output.txt')
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Manual pages builder.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -40,6 +40,8 @@ class ManualPageBuilder(Builder):
|
||||
"""
|
||||
name = 'man'
|
||||
format = 'man'
|
||||
epilog = 'The manual pages are in %(outdir)s.'
|
||||
|
||||
default_translator_class = ManualPageTranslator
|
||||
supported_image_types = [] # type: List[unicode]
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Build input files for the Qt collection generator.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -108,6 +108,11 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
|
||||
Builder that also outputs Qt help project, contents and index files.
|
||||
"""
|
||||
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
|
||||
copysource = False
|
||||
@ -269,7 +274,7 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
|
||||
link = node['refuri']
|
||||
title = htmlescape(node.astext()).replace('"', '"')
|
||||
item = section_template % {'title': title, 'ref': link}
|
||||
item = u' ' * 4 * indentlevel + item # type: ignore
|
||||
item = u' ' * 4 * indentlevel + item
|
||||
parts.append(item.encode('ascii', 'xmlcharrefreplace'))
|
||||
elif isinstance(node, nodes.bullet_list):
|
||||
for subnode in node:
|
||||
|
@ -5,10 +5,11 @@
|
||||
|
||||
Texinfo builder.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import os
|
||||
from os import path
|
||||
|
||||
from docutils import nodes
|
||||
@ -97,6 +98,12 @@ class TexinfoBuilder(Builder):
|
||||
"""
|
||||
name = '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',
|
||||
'image/gif']
|
||||
default_translator_class = TexinfoTranslator
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Plain-text Sphinx builder.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -31,6 +31,8 @@ logger = logging.getLogger(__name__)
|
||||
class TextBuilder(Builder):
|
||||
name = 'text'
|
||||
format = 'text'
|
||||
epilog = 'The text files are in %(outdir)s.'
|
||||
|
||||
out_suffix = '.txt'
|
||||
allow_parallel = True
|
||||
default_translator_class = TextTranslator
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Builder for the web support package.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Docutils-native XML and pseudo-XML builders.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -35,6 +35,8 @@ class XMLBuilder(Builder):
|
||||
"""
|
||||
name = 'xml'
|
||||
format = 'xml'
|
||||
epilog = 'The XML files are in %(outdir)s.'
|
||||
|
||||
out_suffix = '.xml'
|
||||
allow_parallel = True
|
||||
|
||||
@ -108,6 +110,8 @@ class PseudoXMLBuilder(XMLBuilder):
|
||||
"""
|
||||
name = 'pseudoxml'
|
||||
format = 'pseudoxml'
|
||||
epilog = 'The pseudo-XML files are in %(outdir)s.'
|
||||
|
||||
out_suffix = '.pseudoxml'
|
||||
|
||||
_writer_class = PseudoXMLWriter
|
||||
|
@ -5,6 +5,6 @@
|
||||
|
||||
Modules for command line executables.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Build documentation from a provided source.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Quickly setup documentation source to work with Sphinx.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
@ -16,6 +16,7 @@ import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
from collections import OrderedDict
|
||||
from io import open
|
||||
from os import path
|
||||
|
||||
@ -35,7 +36,7 @@ from six.moves.urllib.parse import quote as urlquote
|
||||
from docutils.utils import column_width
|
||||
|
||||
from sphinx import __display_version__, package_dir
|
||||
from sphinx.util.osutil import make_filename
|
||||
from sphinx.util.osutil import ensuredir, make_filename
|
||||
from sphinx.util.console import ( # type: ignore
|
||||
purple, bold, red, turquoise, nocolor, color_terminal
|
||||
)
|
||||
@ -48,7 +49,22 @@ if False:
|
||||
|
||||
TERM_ENCODING = getattr(sys.stdin, 'encoding', None)
|
||||
|
||||
DEFAULT_VALUE = {
|
||||
EXTENSIONS = OrderedDict([
|
||||
('autodoc', 'automatically insert docstrings from modules'),
|
||||
('doctest', 'automatically test code snippets in doctest blocks'),
|
||||
('intersphinx', 'link between Sphinx documentation of different projects'),
|
||||
('todo', 'write "todo" entries that can be shown or hidden on build'),
|
||||
('coverage', 'checks for documentation coverage'),
|
||||
('imgmath', 'include math, rendered as PNG or SVG images'),
|
||||
('mathjax', 'include math, rendered in the browser by MathJax'),
|
||||
('ifconfig', 'conditional inclusion of content based on config values'),
|
||||
('viewcode',
|
||||
'include links to the source code of documented Python objects'),
|
||||
('githubpages',
|
||||
'create .nojekyll file to publish the document on GitHub pages'),
|
||||
])
|
||||
|
||||
DEFAULTS = {
|
||||
'path': '.',
|
||||
'sep': False,
|
||||
'dot': '_',
|
||||
@ -56,26 +72,13 @@ DEFAULT_VALUE = {
|
||||
'suffix': '.rst',
|
||||
'master': 'index',
|
||||
'epub': False,
|
||||
'ext_autodoc': False,
|
||||
'ext_doctest': False,
|
||||
'ext_todo': False,
|
||||
'makefile': True,
|
||||
'batchfile': True,
|
||||
}
|
||||
|
||||
EXTENSIONS = ('autodoc', 'doctest', 'intersphinx', 'todo', 'coverage',
|
||||
'imgmath', 'mathjax', 'ifconfig', 'viewcode', 'githubpages')
|
||||
|
||||
PROMPT_PREFIX = '> '
|
||||
|
||||
|
||||
def mkdir_p(dir):
|
||||
# type: (unicode) -> None
|
||||
if path.isdir(dir):
|
||||
return
|
||||
os.makedirs(dir)
|
||||
|
||||
|
||||
# function to get input from terminal -- overridden by the test suite
|
||||
def term_input(prompt):
|
||||
# type: (unicode) -> unicode
|
||||
@ -159,8 +162,8 @@ def term_decode(text):
|
||||
return text.decode('latin1')
|
||||
|
||||
|
||||
def do_prompt(d, key, text, default=None, validator=nonempty):
|
||||
# type: (Dict, unicode, unicode, unicode, Callable[[unicode], Any]) -> None
|
||||
def do_prompt(text, default=None, validator=nonempty):
|
||||
# type: (unicode, unicode, Callable[[unicode], Any]) -> Union[unicode, bool]
|
||||
while True:
|
||||
if default is not None:
|
||||
prompt = PROMPT_PREFIX + '%s [%s]: ' % (text, default) # type: unicode
|
||||
@ -191,7 +194,7 @@ def do_prompt(d, key, text, default=None, validator=nonempty):
|
||||
print(red('* ' + str(err)))
|
||||
continue
|
||||
break
|
||||
d[key] = x
|
||||
return x
|
||||
|
||||
|
||||
def convert_python_source(source, rex=re.compile(r"[uU]('.*?')")):
|
||||
@ -235,7 +238,7 @@ def ask_user(d):
|
||||
* suffix: source file suffix
|
||||
* master: master document name
|
||||
* epub: use epub (bool)
|
||||
* ext_*: extensions to use (bools)
|
||||
* extensions: extensions to use (list)
|
||||
* makefile: make Makefile
|
||||
* batchfile: make command file
|
||||
"""
|
||||
@ -251,7 +254,7 @@ Selected root path: %s''' % d['path']))
|
||||
else:
|
||||
print('''
|
||||
Enter the root path for documentation.''')
|
||||
do_prompt(d, 'path', 'Root path for the documentation', '.', is_path)
|
||||
d['path'] = do_prompt('Root path for the documentation', '.', is_path)
|
||||
|
||||
while path.isfile(path.join(d['path'], 'conf.py')) or \
|
||||
path.isfile(path.join(d['path'], 'source', 'conf.py')):
|
||||
@ -260,8 +263,8 @@ Enter the root path for documentation.''')
|
||||
'selected root path.'))
|
||||
print('sphinx-quickstart will not overwrite existing Sphinx projects.')
|
||||
print()
|
||||
do_prompt(d, 'path', 'Please enter a new root path (or just Enter '
|
||||
'to exit)', '', is_path)
|
||||
d['path'] = do_prompt('Please enter a new root path (or just Enter '
|
||||
'to exit)', '', is_path)
|
||||
if not d['path']:
|
||||
sys.exit(1)
|
||||
|
||||
@ -270,22 +273,22 @@ Enter the root path for documentation.''')
|
||||
You have two options for placing the build directory for Sphinx output.
|
||||
Either, you use a directory "_build" within the root path, or you separate
|
||||
"source" and "build" directories within the root path.''')
|
||||
do_prompt(d, 'sep', 'Separate source and build directories (y/n)', 'n',
|
||||
boolean)
|
||||
d['sep'] = do_prompt('Separate source and build directories (y/n)',
|
||||
'n', boolean)
|
||||
|
||||
if 'dot' not in d:
|
||||
print('''
|
||||
Inside the root directory, two more directories will be created; "_templates"
|
||||
for custom HTML templates and "_static" for custom stylesheets and other static
|
||||
files. You can enter another prefix (such as ".") to replace the underscore.''')
|
||||
do_prompt(d, 'dot', 'Name prefix for templates and static dir', '_', ok)
|
||||
d['dot'] = do_prompt('Name prefix for templates and static dir', '_', ok)
|
||||
|
||||
if 'project' not in d:
|
||||
print('''
|
||||
The project name will occur in several places in the built documentation.''')
|
||||
do_prompt(d, 'project', 'Project name')
|
||||
d['project'] = do_prompt('Project name')
|
||||
if 'author' not in d:
|
||||
do_prompt(d, 'author', 'Author name(s)')
|
||||
d['author'] = do_prompt('Author name(s)')
|
||||
|
||||
if 'version' not in d:
|
||||
print('''
|
||||
@ -294,9 +297,9 @@ software. Each version can have multiple releases. For example, for
|
||||
Python the version is something like 2.5 or 3.0, while the release is
|
||||
something like 2.5.1 or 3.0a1. If you don't need this dual structure,
|
||||
just set both to the same value.''')
|
||||
do_prompt(d, 'version', 'Project version', '', allow_empty)
|
||||
d['version'] = do_prompt('Project version', '', allow_empty)
|
||||
if 'release' not in d:
|
||||
do_prompt(d, 'release', 'Project release', d['version'], allow_empty)
|
||||
d['release'] = do_prompt('Project release', d['version'], allow_empty)
|
||||
|
||||
if 'language' not in d:
|
||||
print('''
|
||||
@ -306,7 +309,7 @@ translate text that it generates into that language.
|
||||
|
||||
For a list of supported codes, see
|
||||
http://sphinx-doc.org/config.html#confval-language.''')
|
||||
do_prompt(d, 'language', 'Project language', 'en')
|
||||
d['language'] = do_prompt('Project language', 'en')
|
||||
if d['language'] == 'en':
|
||||
d['language'] = None
|
||||
|
||||
@ -314,7 +317,7 @@ http://sphinx-doc.org/config.html#confval-language.''')
|
||||
print('''
|
||||
The file name suffix for source files. Commonly, this is either ".txt"
|
||||
or ".rst". Only files with this suffix are considered documents.''')
|
||||
do_prompt(d, 'suffix', 'Source file suffix', '.rst', suffix)
|
||||
d['suffix'] = do_prompt('Source file suffix', '.rst', suffix)
|
||||
|
||||
if 'master' not in d:
|
||||
print('''
|
||||
@ -322,8 +325,8 @@ One document is special in that it is considered the top node of the
|
||||
"contents tree", that is, it is the root of the hierarchical structure
|
||||
of the documents. Normally, this is "index", but if your "index"
|
||||
document is a custom template, you can also set this to another filename.''')
|
||||
do_prompt(d, 'master', 'Name of your master document (without suffix)',
|
||||
'index')
|
||||
d['master'] = do_prompt('Name of your master document (without suffix)',
|
||||
'index')
|
||||
|
||||
while path.isfile(path.join(d['path'], d['master'] + d['suffix'])) or \
|
||||
path.isfile(path.join(d['path'], 'source', d['master'] + d['suffix'])):
|
||||
@ -332,65 +335,40 @@ document is a custom template, you can also set this to another filename.''')
|
||||
'selected root path.' % (d['master'] + d['suffix'])))
|
||||
print('sphinx-quickstart will not overwrite the existing file.')
|
||||
print()
|
||||
do_prompt(d, 'master', 'Please enter a new file name, or rename the '
|
||||
'existing file and press Enter', d['master'])
|
||||
d['master'] = do_prompt('Please enter a new file name, or rename the '
|
||||
'existing file and press Enter', d['master'])
|
||||
|
||||
if 'epub' not in d:
|
||||
print('''
|
||||
Sphinx can also add configuration for epub output:''')
|
||||
do_prompt(d, 'epub', 'Do you want to use the epub builder (y/n)',
|
||||
'n', boolean)
|
||||
d['epub'] = do_prompt('Do you want to use the epub builder (y/n)',
|
||||
'n', boolean)
|
||||
|
||||
if 'ext_autodoc' not in d:
|
||||
print('''
|
||||
Please indicate if you want to use one of the following Sphinx extensions:''')
|
||||
do_prompt(d, 'ext_autodoc', 'autodoc: automatically insert docstrings '
|
||||
'from modules (y/n)', 'n', boolean)
|
||||
if 'ext_doctest' not in d:
|
||||
do_prompt(d, 'ext_doctest', 'doctest: automatically test code snippets '
|
||||
'in doctest blocks (y/n)', 'n', boolean)
|
||||
if 'ext_intersphinx' not in d:
|
||||
do_prompt(d, 'ext_intersphinx', 'intersphinx: link between Sphinx '
|
||||
'documentation of different projects (y/n)', 'n', boolean)
|
||||
if 'ext_todo' not in d:
|
||||
do_prompt(d, 'ext_todo', 'todo: write "todo" entries '
|
||||
'that can be shown or hidden on build (y/n)', 'n', boolean)
|
||||
if 'ext_coverage' not in d:
|
||||
do_prompt(d, 'ext_coverage', 'coverage: checks for documentation '
|
||||
'coverage (y/n)', 'n', boolean)
|
||||
if 'ext_imgmath' not in d:
|
||||
do_prompt(d, 'ext_imgmath', 'imgmath: include math, rendered '
|
||||
'as PNG or SVG images (y/n)', 'n', boolean)
|
||||
if 'ext_mathjax' not in d:
|
||||
do_prompt(d, 'ext_mathjax', 'mathjax: include math, rendered in the '
|
||||
'browser by MathJax (y/n)', 'n', boolean)
|
||||
if d['ext_imgmath'] and d['ext_mathjax']:
|
||||
print('''Note: imgmath and mathjax cannot be enabled at the same time.
|
||||
imgmath has been deselected.''')
|
||||
d['ext_imgmath'] = False
|
||||
if 'ext_ifconfig' not in d:
|
||||
do_prompt(d, 'ext_ifconfig', 'ifconfig: conditional inclusion of '
|
||||
'content based on config values (y/n)', 'n', boolean)
|
||||
if 'ext_viewcode' not in d:
|
||||
do_prompt(d, 'ext_viewcode', 'viewcode: include links to the source '
|
||||
'code of documented Python objects (y/n)', 'n', boolean)
|
||||
if 'ext_githubpages' not in d:
|
||||
do_prompt(d, 'ext_githubpages', 'githubpages: create .nojekyll file '
|
||||
'to publish the document on GitHub pages (y/n)', 'n', boolean)
|
||||
if 'extensions' not in d:
|
||||
print('Indicate which of the following Sphinx extensions should be '
|
||||
'enabled:')
|
||||
d['extensions'] = []
|
||||
for name, description in EXTENSIONS.items():
|
||||
if do_prompt('%s: %s (y/n)' % (name, description), 'n', boolean):
|
||||
d['extensions'].append('sphinx.ext.%s' % name)
|
||||
|
||||
if 'no_makefile' in d:
|
||||
d['makefile'] = False
|
||||
elif 'makefile' not in d:
|
||||
# Handle conflicting options
|
||||
if set(['sphinx.ext.imgmath', 'sphinx.ext.mathjax']).issubset(
|
||||
d['extensions']):
|
||||
print('Note: imgmath and mathjax cannot be enabled at the same '
|
||||
'time. imgmath has been deselected.')
|
||||
d['extensions'].remove('sphinx.ext.imgmath')
|
||||
|
||||
if 'makefile' not in d:
|
||||
print('''
|
||||
A Makefile and a Windows command file can be generated for you so that you
|
||||
only have to run e.g. `make html' instead of invoking sphinx-build
|
||||
directly.''')
|
||||
do_prompt(d, 'makefile', 'Create Makefile? (y/n)', 'y', boolean)
|
||||
if 'no_batchfile' in d:
|
||||
d['batchfile'] = False
|
||||
elif 'batchfile' not in d:
|
||||
do_prompt(d, 'batchfile', 'Create Windows command file? (y/n)',
|
||||
'y', boolean)
|
||||
d['makefile'] = do_prompt('Create Makefile? (y/n)', 'y', boolean)
|
||||
|
||||
if 'batchfile' not in d:
|
||||
d['batchfile'] = do_prompt('Create Windows command file? (y/n)',
|
||||
'y', boolean)
|
||||
print()
|
||||
|
||||
|
||||
@ -400,7 +378,6 @@ def generate(d, overwrite=True, silent=False, templatedir=None):
|
||||
template = QuickstartRenderer(templatedir=templatedir)
|
||||
|
||||
texescape.init()
|
||||
indent = ' ' * 4
|
||||
|
||||
if 'mastertoctree' not in d:
|
||||
d['mastertoctree'] = ''
|
||||
@ -414,10 +391,6 @@ def generate(d, overwrite=True, silent=False, templatedir=None):
|
||||
d['now'] = time.asctime()
|
||||
d['project_underline'] = column_width(d['project']) * '='
|
||||
d.setdefault('extensions', [])
|
||||
for name in EXTENSIONS:
|
||||
if d.get('ext_' + name):
|
||||
d['extensions'].append('sphinx.ext.' + name)
|
||||
d['extensions'] = (',\n' + indent).join(repr(name) for name in d['extensions'])
|
||||
d['copyright'] = time.strftime('%Y') + ', ' + d['author']
|
||||
d['author_texescaped'] = text_type(d['author']).\
|
||||
translate(texescape.tex_escape_map)
|
||||
@ -433,11 +406,11 @@ def generate(d, overwrite=True, silent=False, templatedir=None):
|
||||
d[key + '_str'] = d[key].replace('\\', '\\\\').replace("'", "\\'")
|
||||
|
||||
if not path.isdir(d['path']):
|
||||
mkdir_p(d['path'])
|
||||
ensuredir(d['path'])
|
||||
|
||||
srcdir = d['sep'] and path.join(d['path'], 'source') or d['path']
|
||||
|
||||
mkdir_p(srcdir)
|
||||
ensuredir(srcdir)
|
||||
if d['sep']:
|
||||
builddir = path.join(d['path'], 'build')
|
||||
d['exclude_patterns'] = ''
|
||||
@ -448,18 +421,20 @@ def generate(d, overwrite=True, silent=False, templatedir=None):
|
||||
'Thumbs.db', '.DS_Store',
|
||||
])
|
||||
d['exclude_patterns'] = ', '.join(exclude_patterns)
|
||||
mkdir_p(builddir)
|
||||
mkdir_p(path.join(srcdir, d['dot'] + 'templates'))
|
||||
mkdir_p(path.join(srcdir, d['dot'] + 'static'))
|
||||
ensuredir(builddir)
|
||||
ensuredir(path.join(srcdir, d['dot'] + 'templates'))
|
||||
ensuredir(path.join(srcdir, d['dot'] + 'static'))
|
||||
|
||||
def write_file(fpath, content, newline=None):
|
||||
# type: (unicode, unicode, unicode) -> None
|
||||
if overwrite or not path.isfile(fpath):
|
||||
print('Creating file %s.' % fpath)
|
||||
if 'quiet' not in d:
|
||||
print('Creating file %s.' % fpath)
|
||||
with open(fpath, 'wt', encoding='utf-8', newline=newline) as f:
|
||||
f.write(content)
|
||||
else:
|
||||
print('File %s already exists, skipping.' % fpath)
|
||||
if 'quiet' not in d:
|
||||
print('File %s already exists, skipping.' % fpath)
|
||||
|
||||
conf_path = os.path.join(templatedir, 'conf.py_t') if templatedir else None
|
||||
if not conf_path or not path.isfile(conf_path):
|
||||
@ -587,28 +562,28 @@ Makefile to be used with sphinx-build.
|
||||
|
||||
group = parser.add_argument_group('Extension options')
|
||||
for ext in EXTENSIONS:
|
||||
group.add_argument('--ext-' + ext, action='store_true',
|
||||
dest='ext_' + ext, default=False,
|
||||
group.add_argument('--ext-%s' % ext, action='append_const',
|
||||
const='sphinx.ext.%s' % ext, dest='extensions',
|
||||
help='enable %s extension' % ext)
|
||||
group.add_argument('--extensions', metavar='EXTENSIONS', dest='extensions',
|
||||
action='append', help='enable extensions')
|
||||
action='append', help='enable arbitrary extensions')
|
||||
|
||||
# TODO(stephenfin): Consider using mutually exclusive groups here
|
||||
group = parser.add_argument_group('Makefile and Batchfile creation')
|
||||
group.add_argument('--makefile', action='store_true', default=False,
|
||||
group.add_argument('--makefile', action='store_true', dest='makefile',
|
||||
help='create makefile')
|
||||
group.add_argument('--no-makefile', action='store_true', default=False,
|
||||
help='not create makefile')
|
||||
group.add_argument('--batchfile', action='store_true', default=False,
|
||||
group.add_argument('--no-makefile', action='store_false', dest='makefile',
|
||||
help='do not create makefile')
|
||||
group.add_argument('--batchfile', action='store_true', dest='batchfile',
|
||||
help='create batchfile')
|
||||
group.add_argument('--no-batchfile', action='store_true', default=False,
|
||||
help='not create batchfile')
|
||||
group.add_argument('-M', '--no-use-make-mode', action='store_false',
|
||||
dest='make_mode', default=False,
|
||||
help='not use make-mode for Makefile/make.bat')
|
||||
group.add_argument('--no-batchfile', action='store_false',
|
||||
dest='batchfile',
|
||||
help='do not create batchfile')
|
||||
group.add_argument('-m', '--use-make-mode', action='store_true',
|
||||
dest='make_mode', default=True,
|
||||
help='use make-mode for Makefile/make.bat')
|
||||
group.add_argument('-M', '--no-use-make-mode', action='store_false',
|
||||
dest='make_mode',
|
||||
help='do not use make-mode for Makefile/make.bat')
|
||||
|
||||
group = parser.add_argument_group('Project templating')
|
||||
group.add_argument('-t', '--templatedir', metavar='TEMPLATEDIR',
|
||||
@ -648,14 +623,9 @@ def main(argv=sys.argv[1:]):
|
||||
# quiet mode with all required params satisfied, use default
|
||||
d.setdefault('version', '')
|
||||
d.setdefault('release', d['version'])
|
||||
d2 = DEFAULT_VALUE.copy()
|
||||
d2.update(dict(("ext_" + ext, False) for ext in EXTENSIONS))
|
||||
d2 = DEFAULTS.copy()
|
||||
d2.update(d)
|
||||
d = d2
|
||||
if 'no_makefile' in d:
|
||||
d['makefile'] = False
|
||||
if 'no_batchfile' in d:
|
||||
d['batchfile'] = False
|
||||
|
||||
if not valid_dir(d):
|
||||
print()
|
||||
@ -676,13 +646,12 @@ def main(argv=sys.argv[1:]):
|
||||
if isinstance(value, binary_type):
|
||||
d[key] = term_decode(value)
|
||||
|
||||
# parse extensions list
|
||||
# handle use of CSV-style extension values
|
||||
d.setdefault('extensions', [])
|
||||
for ext in d['extensions'][:]:
|
||||
if ',' in ext:
|
||||
d['extensions'].remove(ext)
|
||||
for modname in ext.split(','):
|
||||
d['extensions'].append(modname)
|
||||
d['extensions'].extend(ext.split(','))
|
||||
|
||||
for variable in d.get('variables', []):
|
||||
try:
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
sphinx-build command-line handling.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
@ -182,11 +182,7 @@ def main(argv=sys.argv[1:]): # type: ignore
|
||||
# type: (List[unicode]) -> int
|
||||
|
||||
parser = get_parser()
|
||||
# parse options
|
||||
try:
|
||||
args = parser.parse_args(argv)
|
||||
except SystemExit as err:
|
||||
return err.code
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
# get paths (first and second positional argument)
|
||||
try:
|
||||
@ -194,34 +190,28 @@ def main(argv=sys.argv[1:]): # type: ignore
|
||||
confdir = abspath(args.confdir or srcdir)
|
||||
if args.noconfig:
|
||||
confdir = None
|
||||
|
||||
if not path.isdir(srcdir):
|
||||
print('Error: Cannot find source directory `%s\'.' % srcdir,
|
||||
file=sys.stderr)
|
||||
return 1
|
||||
parser.error('cannot find source directory (%s)' % srcdir)
|
||||
if not args.noconfig and not path.isfile(path.join(confdir, 'conf.py')):
|
||||
print('Error: Config directory doesn\'t contain a conf.py file.',
|
||||
file=sys.stderr)
|
||||
return 1
|
||||
parser.error("config directory doesn't contain a conf.py file "
|
||||
"(%s)" % confdir)
|
||||
|
||||
outdir = abspath(args.outputdir)
|
||||
if srcdir == outdir:
|
||||
print('Error: source directory and destination directory are same.',
|
||||
file=sys.stderr)
|
||||
return 1
|
||||
parser.error('source directory and destination directory are same')
|
||||
except UnicodeError:
|
||||
print(
|
||||
'Error: Multibyte filename not supported on this filesystem '
|
||||
'encoding (%r).' % fs_encoding, file=sys.stderr)
|
||||
return 1
|
||||
parser.error('multibyte filename not supported on this filesystem '
|
||||
'encoding (%r)' % fs_encoding)
|
||||
|
||||
# handle remaining filename arguments
|
||||
filenames = args.filenames
|
||||
errored = False
|
||||
missing_files = []
|
||||
for filename in filenames:
|
||||
if not path.isfile(filename):
|
||||
print('Error: Cannot find file %r.' % filename, file=sys.stderr)
|
||||
errored = True
|
||||
if errored:
|
||||
return 1
|
||||
missing_files.append(filename)
|
||||
if missing_files:
|
||||
parser.error('cannot find files %r' % missing_files)
|
||||
|
||||
# likely encoding used for command-line arguments
|
||||
try:
|
||||
@ -231,8 +221,7 @@ def main(argv=sys.argv[1:]): # type: ignore
|
||||
likely_encoding = None
|
||||
|
||||
if args.force_all and filenames:
|
||||
print('Error: Cannot combine -a option and filenames.', file=sys.stderr)
|
||||
return 1
|
||||
parser.error('cannot combine -a option and filenames')
|
||||
|
||||
if args.color == 'no' or (args.color == 'auto' and not color_terminal()):
|
||||
nocolor()
|
||||
@ -245,15 +234,16 @@ def main(argv=sys.argv[1:]): # type: ignore
|
||||
|
||||
if args.quiet:
|
||||
status = None
|
||||
|
||||
if args.really_quiet:
|
||||
status = warning = None
|
||||
|
||||
if warning and args.warnfile:
|
||||
try:
|
||||
warnfp = open(args.warnfile, 'w')
|
||||
except Exception as exc:
|
||||
print('Error: Cannot open warning file %r: %s' %
|
||||
(args.warnfile, exc), file=sys.stderr)
|
||||
sys.exit(1)
|
||||
parser.error('cannot open warning file %r: %s' % (
|
||||
args.warnfile, exc))
|
||||
warning = Tee(warning, warnfp) # type: ignore
|
||||
error = warning
|
||||
|
||||
@ -262,9 +252,7 @@ def main(argv=sys.argv[1:]): # type: ignore
|
||||
try:
|
||||
key, val = val.split('=', 1)
|
||||
except ValueError:
|
||||
print('Error: -D option argument must be in the form name=value.',
|
||||
file=sys.stderr)
|
||||
return 1
|
||||
parser.error('-D option argument must be in the form name=value')
|
||||
if likely_encoding and isinstance(val, binary_type):
|
||||
try:
|
||||
val = val.decode(likely_encoding)
|
||||
@ -276,9 +264,7 @@ def main(argv=sys.argv[1:]): # type: ignore
|
||||
try:
|
||||
key, val = val.split('=')
|
||||
except ValueError:
|
||||
print('Error: -A option argument must be in the form name=value.',
|
||||
file=sys.stderr)
|
||||
return 1
|
||||
parser.error('-A option argument must be in the form name=value')
|
||||
try:
|
||||
val = int(val)
|
||||
except ValueError:
|
||||
@ -302,4 +288,4 @@ def main(argv=sys.argv[1:]): # type: ignore
|
||||
return app.statuscode
|
||||
except (Exception, KeyboardInterrupt) as exc:
|
||||
handle_exception(app, args, exc, error)
|
||||
return 1
|
||||
return 2
|
||||
|
@ -5,11 +5,12 @@
|
||||
|
||||
Build configuration file handling.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import re
|
||||
import traceback
|
||||
from os import path, getenv
|
||||
|
||||
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"
|
||||
if PY3:
|
||||
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) " \
|
||||
"called sys.exit()"
|
||||
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]),
|
||||
needs_sphinx = (None, None, string_classes),
|
||||
needs_extensions = ({}, None),
|
||||
manpages_url = (None, 'env'),
|
||||
nitpicky = (False, None),
|
||||
nitpick_ignore = ([], None),
|
||||
numfig = (False, 'env'),
|
||||
@ -135,6 +138,11 @@ class Config(object):
|
||||
|
||||
tls_verify = (True, 'env'),
|
||||
tls_cacerts = (None, 'env'),
|
||||
smartquotes = (True, 'env'),
|
||||
smartquotes_action = ('qDe', 'env'),
|
||||
smartquotes_excludes = ({'languages': ['ja'],
|
||||
'builders': ['man', 'text']},
|
||||
'env'),
|
||||
) # type: Dict[unicode, Tuple]
|
||||
|
||||
def __init__(self, dirname, filename, overrides, tags):
|
||||
@ -155,6 +163,8 @@ class Config(object):
|
||||
raise ConfigError(CONFIG_SYNTAX_ERROR % err)
|
||||
except SystemExit:
|
||||
raise ConfigError(CONFIG_EXIT_ERROR)
|
||||
except Exception:
|
||||
raise ConfigError(CONFIG_ERROR % traceback.format_exc())
|
||||
|
||||
self._raw_config = config
|
||||
# these two must be preinitialized because extensions can add their
|
||||
@ -291,7 +301,7 @@ class Config(object):
|
||||
logger.warning("%s", exc)
|
||||
for name in config:
|
||||
if name in self.values:
|
||||
self.__dict__[name] = config[name]
|
||||
self.__dict__[name] = config[name] # type: ignore
|
||||
if isinstance(self.source_suffix, string_types): # type: ignore
|
||||
self.source_suffix = [self.source_suffix] # type: ignore
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Sphinx deprecation classes and utilities.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Handlers for additional ReST directives.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
sphinx.directives.code
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
sphinx.directives.other
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
sphinx.directives.patches
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
Support for domains, which are groupings of description directives
|
||||
and roles describing e.g. constructs of one programming language.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -141,7 +141,7 @@ class Domain(object):
|
||||
#: domain label: longer, more descriptive (used in messages)
|
||||
label = ''
|
||||
#: type (usually directive) name -> ObjType instance
|
||||
object_types = {} # type: Dict[unicode, Any]
|
||||
object_types = {} # type: Dict[unicode, ObjType]
|
||||
#: directive name -> directive class
|
||||
directives = {} # type: Dict[unicode, Any]
|
||||
#: role name -> role callable
|
||||
@ -161,6 +161,17 @@ class Domain(object):
|
||||
def __init__(self, env):
|
||||
# type: (BuildEnvironment) -> None
|
||||
self.env = env # type: BuildEnvironment
|
||||
self._role_cache = {} # type: Dict[unicode, Callable]
|
||||
self._directive_cache = {} # type: Dict[unicode, Callable]
|
||||
self._role2type = {} # type: Dict[unicode, List[unicode]]
|
||||
self._type2role = {} # type: Dict[unicode, unicode]
|
||||
|
||||
# convert class variables to instance one (to enhance through API)
|
||||
self.object_types = dict(self.object_types)
|
||||
self.directives = dict(self.directives)
|
||||
self.roles = dict(self.roles)
|
||||
self.indices = list(self.indices)
|
||||
|
||||
if self.name not in env.domaindata:
|
||||
assert isinstance(self.initial_data, dict)
|
||||
new_data = copy.deepcopy(self.initial_data)
|
||||
@ -170,10 +181,6 @@ class Domain(object):
|
||||
self.data = env.domaindata[self.name]
|
||||
if self.data['version'] != self.data_version:
|
||||
raise IOError('data of %r domain out of date' % self.label)
|
||||
self._role_cache = {} # type: Dict[unicode, Callable]
|
||||
self._directive_cache = {} # type: Dict[unicode, Callable]
|
||||
self._role2type = {} # type: Dict[unicode, List[unicode]]
|
||||
self._type2role = {} # type: Dict[unicode, unicode]
|
||||
for name, obj in iteritems(self.object_types):
|
||||
for rolename in obj.roles:
|
||||
self._role2type.setdefault(rolename, []).append(name)
|
||||
@ -181,6 +188,18 @@ class Domain(object):
|
||||
self.objtypes_for_role = self._role2type.get # type: Callable[[unicode], List[unicode]] # NOQA
|
||||
self.role_for_objtype = self._type2role.get # type: Callable[[unicode], unicode]
|
||||
|
||||
def add_object_type(self, name, objtype):
|
||||
# type: (unicode, ObjType) -> None
|
||||
"""Add an object type."""
|
||||
self.object_types[name] = objtype
|
||||
if objtype.roles:
|
||||
self._type2role[name] = objtype.roles[0]
|
||||
else:
|
||||
self._type2role[name] = ''
|
||||
|
||||
for role in objtype.roles:
|
||||
self._role2type.setdefault(role, []).append(name)
|
||||
|
||||
def role(self, name):
|
||||
# type: (unicode) -> Callable
|
||||
"""Return a role adapter function that always gives the registered
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
The C language domain.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,7 @@
|
||||
|
||||
The JavaScript domain.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
The Python domain.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
The reStructuredText domain.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
The standard domain.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -959,12 +959,18 @@ class StandardDomain(Domain):
|
||||
|
||||
def get_full_qualified_name(self, node):
|
||||
# type: (nodes.Node) -> unicode
|
||||
progname = node.get('std:program')
|
||||
target = node.get('reftarget')
|
||||
if progname is None or target is None:
|
||||
return None
|
||||
if node.get('reftype') == 'option':
|
||||
progname = node.get('std:program')
|
||||
command = ws_re.split(node.get('reftarget'))
|
||||
if progname:
|
||||
command.insert(0, progname)
|
||||
option = command.pop()
|
||||
if command:
|
||||
return '.'.join(['-'.join(command), option])
|
||||
else:
|
||||
return None
|
||||
else:
|
||||
return '.'.join([progname, target])
|
||||
return None
|
||||
|
||||
|
||||
def setup(app):
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Global creation environment.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -14,27 +14,23 @@ import os
|
||||
import sys
|
||||
import time
|
||||
import types
|
||||
import codecs
|
||||
import fnmatch
|
||||
import warnings
|
||||
from os import path
|
||||
from copy import copy
|
||||
from collections import defaultdict
|
||||
from contextlib import contextmanager
|
||||
|
||||
from six import BytesIO, itervalues, class_types, next
|
||||
from six import BytesIO, itervalues, class_types, next, iteritems
|
||||
from six.moves import cPickle as pickle
|
||||
|
||||
from docutils.io import NullOutput
|
||||
from docutils.core import Publisher
|
||||
from docutils.utils import Reporter, get_source_line, normalize_language_tag
|
||||
from docutils.utils.smartquotes import smartchars
|
||||
from docutils.parsers.rst import roles
|
||||
from docutils.parsers.rst.languages import en as english
|
||||
from docutils.frontend import OptionParser
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.io import SphinxStandaloneReader, SphinxDummyWriter, SphinxFileInput
|
||||
from sphinx.util import logging
|
||||
from sphinx import addnodes, versioning
|
||||
from sphinx.io import read_doc
|
||||
from sphinx.util import logging, rst
|
||||
from sphinx.util import get_matching_docs, FilenameUniqDict, status_iterator
|
||||
from sphinx.util.nodes import is_translatable
|
||||
from sphinx.util.osutil import SEP, ensuredir
|
||||
@ -45,16 +41,14 @@ from sphinx.util.matching import compile_matchers
|
||||
from sphinx.util.parallel import ParallelTasks, parallel_available, make_chunks
|
||||
from sphinx.util.websupport import is_commentable
|
||||
from sphinx.errors import SphinxError, ExtensionError
|
||||
from sphinx.locale import __
|
||||
from sphinx.transforms import SphinxTransformer
|
||||
from sphinx.versioning import add_uids, merge_doctrees
|
||||
from sphinx.transforms import SphinxTransformer, SphinxSmartQuotes
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.environment.adapters.indexentries import IndexEntries
|
||||
from sphinx.environment.adapters.toctree import TocTree
|
||||
|
||||
if False:
|
||||
# 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 sphinx.application import Sphinx # NOQA
|
||||
from sphinx.builders import Builder # NOQA
|
||||
@ -73,6 +67,7 @@ default_settings = {
|
||||
'sectsubtitle_xform': False,
|
||||
'halt_level': 5,
|
||||
'file_insertion_enabled': True,
|
||||
'smartquotes_locales': [],
|
||||
}
|
||||
|
||||
# This is increased every time an environment attribute is added
|
||||
@ -82,8 +77,6 @@ default_settings = {
|
||||
ENV_VERSION = 52 + (sys.version_info[0] - 2)
|
||||
|
||||
|
||||
dummy_reporter = Reporter('', 4, 4)
|
||||
|
||||
versioning_conditions = {
|
||||
'none': False,
|
||||
'text': is_translatable,
|
||||
@ -91,6 +84,22 @@ versioning_conditions = {
|
||||
} # type: Dict[unicode, Union[bool, Callable]]
|
||||
|
||||
|
||||
@contextmanager
|
||||
def sphinx_smartquotes_action(env):
|
||||
# type: (BuildEnvironment) -> Generator
|
||||
if not hasattr(SphinxSmartQuotes, 'smartquotes_action'):
|
||||
# less than docutils-0.14
|
||||
yield
|
||||
else:
|
||||
# docutils-0.14 or above
|
||||
try:
|
||||
original = SphinxSmartQuotes.smartquotes_action
|
||||
SphinxSmartQuotes.smartquotes_action = env.config.smartquotes_action
|
||||
yield
|
||||
finally:
|
||||
SphinxSmartQuotes.smartquotes_action = original
|
||||
|
||||
|
||||
class NoUri(Exception):
|
||||
"""Raised by get_relative_uri if there is no URI available."""
|
||||
pass
|
||||
@ -566,21 +575,10 @@ class BuildEnvironment(object):
|
||||
self.app.emit('env-before-read-docs', self, docnames)
|
||||
|
||||
# check if we should do parallel or serial read
|
||||
par_ok = False
|
||||
if parallel_available and len(docnames) > 5 and self.app.parallel > 1:
|
||||
for ext in itervalues(self.app.extensions):
|
||||
if ext.parallel_read_safe is None:
|
||||
logger.warning(__('the %s extension does not declare if it is safe '
|
||||
'for parallel reading, assuming it isn\'t - please '
|
||||
'ask the extension author to check and make it '
|
||||
'explicit'), ext.name)
|
||||
logger.warning('doing serial read')
|
||||
break
|
||||
elif ext.parallel_read_safe is False:
|
||||
break
|
||||
else:
|
||||
# all extensions support parallel-read
|
||||
par_ok = True
|
||||
par_ok = self.app.is_parallel_allowed('read')
|
||||
else:
|
||||
par_ok = False
|
||||
|
||||
if par_ok:
|
||||
self._read_parallel(docnames, self.app, nproc=self.app.parallel)
|
||||
@ -604,7 +602,8 @@ class BuildEnvironment(object):
|
||||
# remove all inventory entries for that file
|
||||
app.emit('env-purge-doc', self, docname)
|
||||
self.clear_doc(docname)
|
||||
self.read_doc(docname, app)
|
||||
with sphinx_smartquotes_action(self):
|
||||
self.read_doc(docname, app)
|
||||
|
||||
def _read_parallel(self, docnames, app, nproc):
|
||||
# type: (List[unicode], Sphinx, int) -> None
|
||||
@ -616,8 +615,9 @@ class BuildEnvironment(object):
|
||||
def read_process(docs):
|
||||
# type: (List[unicode]) -> unicode
|
||||
self.app = app
|
||||
for docname in docs:
|
||||
self.read_doc(docname, app)
|
||||
with sphinx_smartquotes_action(self):
|
||||
for docname in docs:
|
||||
self.read_doc(docname, app)
|
||||
# allow pickling self to send it back
|
||||
return BuildEnvironment.dumps(self)
|
||||
|
||||
@ -648,25 +648,9 @@ class BuildEnvironment(object):
|
||||
|
||||
# --------- SINGLE FILE READING --------------------------------------------
|
||||
|
||||
def warn_and_replace(self, error):
|
||||
# type: (Any) -> Tuple
|
||||
"""Custom decoding error handler that warns and replaces."""
|
||||
linestart = error.object.rfind(b'\n', 0, error.start)
|
||||
lineend = error.object.find(b'\n', error.start)
|
||||
if lineend == -1:
|
||||
lineend = len(error.object)
|
||||
lineno = error.object.count(b'\n', 0, error.start) + 1
|
||||
logger.warning('undecodable source characters, replacing with "?": %r',
|
||||
(error.object[linestart + 1:error.start] + b'>>>' +
|
||||
error.object[error.start:error.end] + b'<<<' +
|
||||
error.object[error.end:lineend]),
|
||||
location=(self.docname, lineno))
|
||||
return (u'?', error.end)
|
||||
|
||||
def read_doc(self, docname, app=None):
|
||||
# type: (unicode, Sphinx) -> None
|
||||
"""Parse a file and add/update inventory entries for the doctree."""
|
||||
|
||||
def prepare_settings(self, docname):
|
||||
# type: (unicode) -> None
|
||||
"""Prepare to set up environment for reading."""
|
||||
self.temp_data['docname'] = docname
|
||||
# defaults to the global default, but can be re-set in a document
|
||||
self.temp_data['default_role'] = self.config.default_role
|
||||
@ -681,7 +665,19 @@ class BuildEnvironment(object):
|
||||
language = self.config.language or 'en'
|
||||
self.settings['language_code'] = language
|
||||
if 'smart_quotes' not in self.settings:
|
||||
self.settings['smart_quotes'] = True
|
||||
self.settings['smart_quotes'] = self.config.smartquotes
|
||||
|
||||
# some conditions exclude smart quotes, overriding smart_quotes
|
||||
for valname, vallist in iteritems(self.config.smartquotes_excludes):
|
||||
if valname == 'builders':
|
||||
# this will work only for checking first build target
|
||||
if self.app.builder.name in vallist:
|
||||
self.settings['smart_quotes'] = False
|
||||
break
|
||||
elif valname == 'languages':
|
||||
if self.config.language in vallist:
|
||||
self.settings['smart_quotes'] = False
|
||||
break
|
||||
|
||||
# confirm selected language supports smart_quotes or not
|
||||
for tag in normalize_language_tag(language):
|
||||
@ -690,40 +686,19 @@ class BuildEnvironment(object):
|
||||
else:
|
||||
self.settings['smart_quotes'] = False
|
||||
|
||||
def read_doc(self, docname, app=None):
|
||||
# type: (unicode, Sphinx) -> None
|
||||
"""Parse a file and add/update inventory entries for the doctree."""
|
||||
self.prepare_settings(docname)
|
||||
|
||||
docutilsconf = path.join(self.srcdir, 'docutils.conf')
|
||||
# read docutils.conf from source dir, not from current dir
|
||||
OptionParser.standard_config_files[1] = docutilsconf
|
||||
if path.isfile(docutilsconf):
|
||||
self.note_dependency(docutilsconf)
|
||||
|
||||
with sphinx_domains(self):
|
||||
if self.config.default_role:
|
||||
role_fn, messages = roles.role(self.config.default_role, english,
|
||||
0, dummy_reporter)
|
||||
if role_fn:
|
||||
roles._roles[''] = role_fn
|
||||
else:
|
||||
logger.warning('default role %s not found', self.config.default_role,
|
||||
location=docname)
|
||||
|
||||
codecs.register_error('sphinx', self.warn_and_replace) # type: ignore
|
||||
|
||||
# publish manually
|
||||
reader = SphinxStandaloneReader(self.app,
|
||||
parsers=self.app.registry.get_source_parsers())
|
||||
pub = Publisher(reader=reader,
|
||||
writer=SphinxDummyWriter(),
|
||||
destination_class=NullOutput)
|
||||
pub.set_components(None, 'restructuredtext', None)
|
||||
pub.process_programmatic_settings(None, self.settings, None)
|
||||
src_path = self.doc2path(docname)
|
||||
source = SphinxFileInput(app, self, source=None, source_path=src_path,
|
||||
encoding=self.config.source_encoding)
|
||||
pub.source = source
|
||||
pub.settings._source = src_path
|
||||
pub.set_destination(None, None)
|
||||
pub.publish()
|
||||
doctree = pub.document
|
||||
with sphinx_domains(self), rst.default_role(docname, self.config.default_role):
|
||||
doctree = read_doc(self.app, self, self.doc2path(docname))
|
||||
|
||||
# post-processing
|
||||
for domain in itervalues(self.domains):
|
||||
@ -741,41 +716,14 @@ class BuildEnvironment(object):
|
||||
time.time(), path.getmtime(self.doc2path(docname)))
|
||||
|
||||
if self.versioning_condition:
|
||||
old_doctree = None
|
||||
if self.versioning_compare:
|
||||
# get old doctree
|
||||
try:
|
||||
with open(self.doc2path(docname,
|
||||
self.doctreedir, '.doctree'), 'rb') as f:
|
||||
old_doctree = pickle.load(f)
|
||||
except EnvironmentError:
|
||||
pass
|
||||
|
||||
# add uids for versioning
|
||||
if not self.versioning_compare or old_doctree is None:
|
||||
list(add_uids(doctree, self.versioning_condition))
|
||||
else:
|
||||
list(merge_doctrees(
|
||||
old_doctree, doctree, self.versioning_condition))
|
||||
|
||||
# make it picklable
|
||||
doctree.reporter = None
|
||||
doctree.transformer = None
|
||||
doctree.settings.warning_stream = None
|
||||
doctree.settings.env = None
|
||||
doctree.settings.record_dependencies = None
|
||||
versioning.prepare(doctree)
|
||||
|
||||
# cleanup
|
||||
self.temp_data.clear()
|
||||
self.ref_context.clear()
|
||||
roles._roles.pop('', None) # if a document has set a local default role
|
||||
|
||||
# save the parsed doctree
|
||||
doctree_filename = self.doc2path(docname, self.doctreedir,
|
||||
'.doctree')
|
||||
ensuredir(path.dirname(doctree_filename))
|
||||
with open(doctree_filename, 'wb') as f:
|
||||
pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
|
||||
self.write_doctree(docname, doctree)
|
||||
|
||||
# utilities to use while reading a document
|
||||
|
||||
@ -879,6 +827,21 @@ class BuildEnvironment(object):
|
||||
doctree.reporter = Reporter(self.doc2path(docname), 2, 5, stream=WarningStream())
|
||||
return doctree
|
||||
|
||||
def write_doctree(self, docname, doctree):
|
||||
# type: (unicode, nodes.Node) -> None
|
||||
"""Write the doctree to a file."""
|
||||
# make it picklable
|
||||
doctree.reporter = None
|
||||
doctree.transformer = None
|
||||
doctree.settings.warning_stream = None
|
||||
doctree.settings.env = None
|
||||
doctree.settings.record_dependencies = None
|
||||
|
||||
doctree_filename = self.doc2path(docname, self.doctreedir, '.doctree')
|
||||
ensuredir(path.dirname(doctree_filename))
|
||||
with open(doctree_filename, 'wb') as f:
|
||||
pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
|
||||
|
||||
def get_and_resolve_doctree(self, docname, builder, doctree=None,
|
||||
prune_toctrees=True, includehidden=False):
|
||||
# type: (unicode, Builder, nodes.Node, bool, bool) -> nodes.Node
|
||||
@ -935,7 +898,7 @@ class BuildEnvironment(object):
|
||||
|
||||
transformer = SphinxTransformer(doctree)
|
||||
transformer.set_environment(self)
|
||||
transformer.add_transforms(self.app.post_transforms)
|
||||
transformer.add_transforms(self.app.registry.get_post_transforms())
|
||||
transformer.apply_transforms()
|
||||
finally:
|
||||
self.temp_data = backup
|
||||
|
@ -5,6 +5,6 @@
|
||||
|
||||
Sphinx environment adapters
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Assets adapter for sphinx.environment.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Index entries adapters for sphinx.environment.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
import re
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Toctree adapter for sphinx.environment.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
The data collector components for sphinx.environment.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
The image collector for sphinx.environment.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
The dependencies collector components for sphinx.environment.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Index entries collector for sphinx.environment.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
The metadata collector components for sphinx.environment.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
The title collector components for sphinx.environment.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Toctree collector for sphinx.environment.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -262,7 +262,7 @@ class TocTreeCollector(EnvironmentCollector):
|
||||
|
||||
continue
|
||||
|
||||
figtype = env.get_domain('std').get_figtype(subnode) # type: ignore
|
||||
figtype = env.get_domain('std').get_figtype(subnode)
|
||||
if figtype and subnode['ids']:
|
||||
register_fignumber(docname, secnum, figtype, subnode)
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
Contains SphinxError and a few subclasses (in an extra module to avoid
|
||||
circular import problems).
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
Gracefully adapted from the TextPress system by Armin.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
@ -5,6 +5,6 @@
|
||||
|
||||
Contains Sphinx features not activated by default.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
@ -11,7 +11,7 @@
|
||||
Copyright 2008 Société des arts technologiques (SAT),
|
||||
http://www.sat.qc.ca/
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -27,7 +27,7 @@ from fnmatch import fnmatch
|
||||
from sphinx import __display_version__
|
||||
from sphinx.cmd.quickstart import EXTENSIONS
|
||||
from sphinx.util import rst
|
||||
from sphinx.util.osutil import FileAvoidWrite, walk
|
||||
from sphinx.util.osutil import FileAvoidWrite, ensuredir, walk
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
@ -117,7 +117,11 @@ def create_package_file(root, master_package, subroot, py_files, opts, subs, is_
|
||||
text += '\n'
|
||||
|
||||
# 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 subs:
|
||||
text += format_heading(2, 'Subpackages')
|
||||
@ -358,8 +362,8 @@ Note: By default this script will not overwrite already created files.""")
|
||||
|
||||
group = parser.add_argument_group('extension options')
|
||||
for ext in EXTENSIONS:
|
||||
group.add_argument('--ext-' + ext, action='store_true',
|
||||
dest='ext_' + ext, default=False,
|
||||
group.add_argument('--ext-%s' % ext, action='append_const',
|
||||
const='sphinx.ext.%s' % ext, dest='extensions',
|
||||
help='enable %s extension' % ext)
|
||||
|
||||
return parser
|
||||
@ -382,8 +386,8 @@ def main(argv=sys.argv[1:]):
|
||||
if not path.isdir(rootpath):
|
||||
print('%s is not a directory.' % rootpath, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
if not path.isdir(args.destdir) and not args.dryrun:
|
||||
os.makedirs(args.destdir)
|
||||
if not args.dryrun:
|
||||
ensuredir(args.destdir)
|
||||
excludes = [path.abspath(exclude) for exclude in args.exclude_pattern]
|
||||
modules = recurse_tree(rootpath, excludes, args)
|
||||
|
||||
@ -408,20 +412,19 @@ def main(argv=sys.argv[1:]):
|
||||
suffix = '.' + args.suffix,
|
||||
master = 'index',
|
||||
epub = True,
|
||||
ext_autodoc = True,
|
||||
ext_viewcode = True,
|
||||
ext_todo = True,
|
||||
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode',
|
||||
'sphinx.ext.todo'],
|
||||
makefile = True,
|
||||
batchfile = True,
|
||||
make_mode = True,
|
||||
mastertocmaxdepth = args.maxdepth,
|
||||
mastertoctree = text,
|
||||
language = 'en',
|
||||
module_path = rootpath,
|
||||
append_syspath = args.append_syspath,
|
||||
)
|
||||
enabled_exts = {'ext_' + ext: getattr(args, 'ext_' + ext)
|
||||
for ext in EXTENSIONS if getattr(args, 'ext_' + ext)}
|
||||
d.update(enabled_exts)
|
||||
if args.extensions:
|
||||
d['extensions'].extend(args.extensions)
|
||||
|
||||
if isinstance(args.header, binary_type):
|
||||
d['project'] = d['project'].decode('utf-8')
|
||||
|
@ -7,46 +7,46 @@
|
||||
the doctree, thus avoiding duplication between docstrings and documentation
|
||||
for those who like elaborate docstrings.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import re
|
||||
import sys
|
||||
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
|
||||
|
||||
import sphinx
|
||||
from sphinx.ext.autodoc.importer import _MockImporter
|
||||
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.inspector import format_annotation, formatargspec # to keep compatibility # NOQA
|
||||
from sphinx.util import rpartition, force_decode
|
||||
from sphinx.locale import _
|
||||
from sphinx.pycode import ModuleAnalyzer, PycodeError
|
||||
from sphinx.application import ExtensionError
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.nodes import nested_parse_with_titles
|
||||
from sphinx.util.inspect import Signature, isdescriptor, safe_getmembers, \
|
||||
safe_getattr, object_description, is_builtin_class_method, \
|
||||
isenumclass, isenumattribute, getdoc
|
||||
isenumattribute, getdoc
|
||||
from sphinx.util.docstrings import prepare_docstring
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from types import ModuleType # 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 sphinx.application import Sphinx # NOQA
|
||||
from sphinx.ext.autodoc.directive import DocumenterBridge # NOQA
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# This type isn't exposed directly in any modules, but can be found
|
||||
# here in most Python versions
|
||||
MethodDescriptorType = type(type.__subclasses__)
|
||||
@ -63,42 +63,11 @@ py_ext_sig_re = re.compile(
|
||||
''', 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):
|
||||
# type: (Any) -> Any
|
||||
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()
|
||||
INSTANCEATTR = object()
|
||||
|
||||
@ -146,6 +115,9 @@ class AutodocReporter(object):
|
||||
"""
|
||||
def __init__(self, viewlist, reporter):
|
||||
# type: (ViewList, Reporter) -> None
|
||||
warnings.warn('AutodocReporter is now deprecated. '
|
||||
'Use sphinx.util.docutils.switch_source_input() instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
self.viewlist = viewlist
|
||||
self.reporter = reporter
|
||||
|
||||
@ -284,14 +256,10 @@ class Documenter(object):
|
||||
|
||||
option_spec = {'noindex': bool_option} # type: Dict[unicode, Callable]
|
||||
|
||||
@staticmethod
|
||||
def get_attr(obj, name, *defargs):
|
||||
def get_attr(self, obj, name, *defargs):
|
||||
# type: (Any, unicode, Any) -> Any
|
||||
"""getattr() override for types such as Zope interfaces."""
|
||||
for typ, func in iteritems(AutoDirective._special_attrgetters):
|
||||
if isinstance(obj, typ):
|
||||
return func(obj, name, *defargs)
|
||||
return safe_getattr(obj, name, *defargs)
|
||||
return autodoc_attrgetter(self.env.app, obj, name, *defargs)
|
||||
|
||||
@classmethod
|
||||
def can_document_member(cls, member, membername, isattr, parent):
|
||||
@ -300,7 +268,7 @@ class Documenter(object):
|
||||
raise NotImplementedError('must be implemented in subclasses')
|
||||
|
||||
def __init__(self, directive, name, indent=u''):
|
||||
# type: (Directive, unicode, unicode) -> None
|
||||
# type: (DocumenterBridge, unicode, unicode) -> None
|
||||
self.directive = directive
|
||||
self.env = directive.env
|
||||
self.options = directive.genopt
|
||||
@ -324,6 +292,12 @@ class Documenter(object):
|
||||
# the module analyzer to get at attribute docs, or None
|
||||
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):
|
||||
# type: (unicode, unicode, int) -> None
|
||||
"""Append one line of generated reST to the output."""
|
||||
@ -354,8 +328,7 @@ class Documenter(object):
|
||||
explicit_modname, path, base, args, retann = \
|
||||
py_ext_sig_re.match(self.name).groups() # type: ignore
|
||||
except AttributeError:
|
||||
self.directive.warn('invalid signature for auto%s (%r)' %
|
||||
(self.objtype, self.name))
|
||||
logger.warning('invalid signature for auto%s (%r)' % (self.objtype, self.name))
|
||||
return False
|
||||
|
||||
# support explicit module and class name separation via ::
|
||||
@ -384,53 +357,17 @@ class Documenter(object):
|
||||
|
||||
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
|
||||
import_hook = _MockImporter(self.env.config.autodoc_mock_imports)
|
||||
try:
|
||||
logger.debug('[autodoc] import %s', self.modname)
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings("ignore", category=ImportWarning)
|
||||
with logging.skip_warningiserror(not self.env.config.autodoc_warningiserror):
|
||||
__import__(self.modname)
|
||||
parent = None
|
||||
obj = self.module = sys.modules[self.modname]
|
||||
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
|
||||
# this used to only catch SyntaxError, ImportError and AttributeError,
|
||||
# but importing modules with side effects can raise all kinds of errors
|
||||
except (Exception, SystemExit) as e:
|
||||
if self.objpath:
|
||||
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(e, SystemExit):
|
||||
errmsg += ('; the module executes module level statement ' +
|
||||
'and it might call sys.exit().')
|
||||
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()
|
||||
return False
|
||||
finally:
|
||||
import_hook.disable()
|
||||
with mock(self.env.config.autodoc_mock_imports):
|
||||
try:
|
||||
ret = import_object(self.modname, self.objpath, self.objtype,
|
||||
attrgetter=self.get_attr,
|
||||
warningiserror=self.env.config.autodoc_warningiserror)
|
||||
self.module, self.parent, self.object_name, self.object = ret
|
||||
return True
|
||||
except ImportError as exc:
|
||||
logger.warning(exc.args[0])
|
||||
self.env.note_reread()
|
||||
return False
|
||||
|
||||
def get_real_modname(self):
|
||||
# type: () -> str
|
||||
@ -488,8 +425,8 @@ class Documenter(object):
|
||||
try:
|
||||
args = self.format_args()
|
||||
except Exception as err:
|
||||
self.directive.warn('error while formatting arguments for '
|
||||
'%s: %s' % (self.fullname, err))
|
||||
logger.warning('error while formatting arguments for %s: %s' %
|
||||
(self.fullname, err))
|
||||
args = None
|
||||
|
||||
retann = self.retann
|
||||
@ -601,57 +538,24 @@ class Documenter(object):
|
||||
If *want_all* is True, return all members. Else, only return those
|
||||
members given by *self.options.members* (which may also be none).
|
||||
"""
|
||||
analyzed_member_names = set()
|
||||
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])
|
||||
members = get_object_members(self.object, self.objpath, self.get_attr, self.analyzer)
|
||||
if not want_all:
|
||||
if not self.options.members:
|
||||
return False, []
|
||||
# specific members given
|
||||
members = []
|
||||
for mname in self.options.members:
|
||||
try:
|
||||
members.append((mname, self.get_attr(self.object, mname)))
|
||||
except AttributeError:
|
||||
if mname not in analyzed_member_names:
|
||||
self.directive.warn('missing attribute %s in object %s'
|
||||
% (mname, self.fullname))
|
||||
selected = []
|
||||
for name in self.options.members:
|
||||
if name in members:
|
||||
selected.append((name, members[name].value))
|
||||
else:
|
||||
logger.warning('missing attribute %s in object %s' %
|
||||
(name, self.fullname))
|
||||
return False, sorted(selected)
|
||||
elif self.options.inherited_members:
|
||||
# safe_getmembers() uses dir() which pulls in members from all
|
||||
# base classes
|
||||
members = safe_getmembers(self.object, attr_getter=self.get_attr)
|
||||
return False, sorted((m.name, m.value) for m in itervalues(members))
|
||||
else:
|
||||
# __dict__ contains only the members directly defined in
|
||||
# the class (but get them via getattr anyway, to e.g. get
|
||||
# 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)
|
||||
return False, sorted((m.name, m.value) for m in itervalues(members)
|
||||
if m.directly_defined)
|
||||
|
||||
def filter_members(self, members, want_all):
|
||||
# type: (List[Tuple[unicode, Any]], bool) -> List[Tuple[unicode, Any, bool]]
|
||||
@ -710,8 +614,7 @@ class Documenter(object):
|
||||
elif (namespace, membername) in attr_docs:
|
||||
if want_all and membername.startswith('_'):
|
||||
# ignore members whose name starts with _ by default
|
||||
keep = self.options.private_members and \
|
||||
(has_doc or self.options.undoc_members)
|
||||
keep = self.options.private_members
|
||||
else:
|
||||
# keep documented attributes
|
||||
keep = True
|
||||
@ -764,7 +667,7 @@ class Documenter(object):
|
||||
# document non-skipped members
|
||||
memberdocumenters = [] # type: List[Tuple[Documenter, bool]]
|
||||
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 not classes:
|
||||
# don't know how to document this member
|
||||
@ -815,11 +718,11 @@ class Documenter(object):
|
||||
"""
|
||||
if not self.parse_name():
|
||||
# need a module to import
|
||||
self.directive.warn(
|
||||
logger.warning(
|
||||
'don\'t know which module to import for autodocumenting '
|
||||
'%r (try placing a "module" or "currentmodule" directive '
|
||||
'in the document, or giving an explicit module name)'
|
||||
% self.name)
|
||||
'in the document, or giving an explicit module name)' %
|
||||
self.name)
|
||||
return
|
||||
|
||||
# now, import the module and get object to document
|
||||
@ -893,7 +796,7 @@ class ModuleDocumenter(Documenter):
|
||||
'platform': identity, 'deprecated': bool_option,
|
||||
'member-order': identity, 'exclude-members': members_set_option,
|
||||
'private-members': bool_option, 'special-members': members_option,
|
||||
'imported-members': bool_option,
|
||||
'imported-members': bool_option, 'ignore-module-all': bool_option
|
||||
} # type: Dict[unicode, Callable]
|
||||
|
||||
@classmethod
|
||||
@ -905,15 +808,15 @@ class ModuleDocumenter(Documenter):
|
||||
def resolve_name(self, modname, parents, path, base):
|
||||
# type: (str, Any, str, Any) -> Tuple[str, List[unicode]]
|
||||
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, []
|
||||
|
||||
def parse_name(self):
|
||||
# type: () -> bool
|
||||
ret = Documenter.parse_name(self)
|
||||
if self.args or self.retann:
|
||||
self.directive.warn('signature arguments or return annotation '
|
||||
'given for automodule %s' % self.fullname)
|
||||
logger.warning('signature arguments or return annotation '
|
||||
'given for automodule %s' % self.fullname)
|
||||
return ret
|
||||
|
||||
def add_directive_header(self, sig):
|
||||
@ -935,7 +838,8 @@ class ModuleDocumenter(Documenter):
|
||||
def get_object_members(self, want_all):
|
||||
# type: (bool) -> Tuple[bool, List[Tuple[unicode, object]]]
|
||||
if want_all:
|
||||
if not hasattr(self.object, '__all__'):
|
||||
if (self.options.ignore_module_all or not
|
||||
hasattr(self.object, '__all__')):
|
||||
# for implicit module members, check __module__ to avoid
|
||||
# documenting imported objects
|
||||
return True, safe_getmembers(self.object)
|
||||
@ -944,7 +848,7 @@ class ModuleDocumenter(Documenter):
|
||||
# Sometimes __all__ is broken...
|
||||
if not isinstance(memberlist, (list, tuple)) or not \
|
||||
all(isinstance(entry, string_types) for entry in memberlist):
|
||||
self.directive.warn(
|
||||
logger.warning(
|
||||
'__all__ should be a list of strings, not %r '
|
||||
'(in module %s) -- ignoring __all__' %
|
||||
(memberlist, self.fullname))
|
||||
@ -957,10 +861,10 @@ class ModuleDocumenter(Documenter):
|
||||
try:
|
||||
ret.append((mname, safe_getattr(self.object, mname)))
|
||||
except AttributeError:
|
||||
self.directive.warn(
|
||||
logger.warning(
|
||||
'missing attribute mentioned in :members: or __all__: '
|
||||
'module %s, attribute %s' % (
|
||||
safe_getattr(self.object, '__name__', '???'), mname))
|
||||
'module %s, attribute %s' %
|
||||
(safe_getattr(self.object, '__name__', '???'), mname))
|
||||
return False, ret
|
||||
|
||||
|
||||
@ -1269,6 +1173,17 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
||||
return
|
||||
ModuleLevelDocumenter.document_members(self, all_members)
|
||||
|
||||
def generate(self, more_content=None, real_modname=None,
|
||||
check_module=False, all_members=False):
|
||||
# Do not pass real_modname and use the name from the __module__
|
||||
# attribute of the class.
|
||||
# If a class gets imported into the module real_modname
|
||||
# the analyzer won't find the source of the class, if
|
||||
# it looks in real_modname.
|
||||
return super(ClassDocumenter, self).generate(more_content=more_content,
|
||||
check_module=check_module,
|
||||
all_members=all_members)
|
||||
|
||||
|
||||
class ExceptionDocumenter(ClassDocumenter):
|
||||
"""
|
||||
@ -1488,118 +1403,56 @@ class InstanceAttributeDocumenter(AttributeDocumenter):
|
||||
AttributeDocumenter.add_content(self, more_content, no_docstring=True)
|
||||
|
||||
|
||||
class AutoDirective(Directive):
|
||||
"""
|
||||
The AutoDirective class is used for all autodoc directives. It dispatches
|
||||
most of the work to one of the Documenters, which it selects through its
|
||||
*_registry* dictionary.
|
||||
class DeprecatedDict(dict):
|
||||
def __init__(self, message):
|
||||
self.message = message
|
||||
super(DeprecatedDict, self).__init__()
|
||||
|
||||
The *_special_attrgetters* attribute is used to customize ``getattr()``
|
||||
calls that the Documenters make; its entries are of the form ``type:
|
||||
getattr_function``.
|
||||
def __setitem__(self, key, value):
|
||||
warnings.warn(self.message, RemovedInSphinx20Warning)
|
||||
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
|
||||
accessed using the descendant's *_special_attrgetters*, thus this
|
||||
dictionary should include all necessary functions for accessing
|
||||
attributes of the parents.
|
||||
"""
|
||||
# a registry of objtype -> documenter class
|
||||
_registry = {} # type: Dict[unicode, Type[Documenter]]
|
||||
# a registry of objtype -> documenter class (Deprecated)
|
||||
_registry = DeprecatedDict(
|
||||
'AutoDirective._registry has been deprecated. '
|
||||
'Please use app.add_autodocumenter() instead.'
|
||||
) # type: Dict[unicode, Type[Documenter]]
|
||||
|
||||
# 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',
|
||||
])
|
||||
|
||||
# standard docutils directive settings
|
||||
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
|
||||
AutoDirective = AutodocRegistry # for backward compatibility
|
||||
|
||||
|
||||
def add_documenter(cls):
|
||||
# type: (Type[Documenter]) -> None
|
||||
"""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):
|
||||
raise ExtensionError('autodoc documenter %r must be a subclass '
|
||||
'of Documenter' % cls)
|
||||
@ -1610,6 +1463,29 @@ def add_documenter(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):
|
||||
# type: (Sphinx) -> Dict[unicode, Any]
|
||||
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
|
@ -5,18 +5,25 @@
|
||||
|
||||
Importer utilities for autodoc
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import warnings
|
||||
import traceback
|
||||
import contextlib
|
||||
from collections import namedtuple
|
||||
from types import FunctionType, MethodType, ModuleType
|
||||
|
||||
from six import PY2
|
||||
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.inspect import isenumclass, safe_getattr
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, List, Set # NOQA
|
||||
from typing import Any, Callable, Dict, Generator, List, Optional # NOQA
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -75,16 +82,9 @@ class _MockModule(ModuleType):
|
||||
|
||||
|
||||
class _MockImporter(object):
|
||||
|
||||
def __init__(self, names):
|
||||
# type: (List[str]) -> None
|
||||
self.base_packages = set() # type: Set[str]
|
||||
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.names = names
|
||||
self.mocked_modules = [] # type: List[str]
|
||||
# enable hook by adding itself to meta_path
|
||||
sys.meta_path = sys.meta_path + [self]
|
||||
@ -100,9 +100,10 @@ class _MockImporter(object):
|
||||
|
||||
def find_module(self, name, path=None):
|
||||
# type: (str, str) -> Any
|
||||
base_package = name.split('.')[0]
|
||||
if base_package in self.base_packages:
|
||||
return self
|
||||
# check if name is (or is a descendant of) one of our base_packages
|
||||
for n in self.names:
|
||||
if n == name or name.startswith(n + '.'):
|
||||
return self
|
||||
return None
|
||||
|
||||
def load_module(self, name):
|
||||
@ -116,3 +117,112 @@ class _MockImporter(object):
|
||||
sys.modules[name] = module
|
||||
self.mocked_modules.append(name)
|
||||
return module
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def mock(names):
|
||||
# type: (List[str]) -> Generator
|
||||
try:
|
||||
importer = _MockImporter(names)
|
||||
yield
|
||||
finally:
|
||||
importer.disable()
|
||||
|
||||
|
||||
def import_module(modname, warningiserror=False):
|
||||
"""
|
||||
Call __import__(modname), convert exceptions to ImportError
|
||||
"""
|
||||
try:
|
||||
with warnings.catch_warnings():
|
||||
warnings.filterwarnings("ignore", category=ImportWarning)
|
||||
with logging.skip_warningiserror(not warningiserror):
|
||||
__import__(modname)
|
||||
return sys.modules[modname]
|
||||
except BaseException as exc:
|
||||
# Importing modules may cause any side effects, including
|
||||
# SystemExit, so we need to catch all errors.
|
||||
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
|
||||
|
@ -5,14 +5,16 @@
|
||||
|
||||
Inspect utilities for autodoc
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import typing
|
||||
import warnings
|
||||
|
||||
from six import StringIO, string_types
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.util.inspect import object_description
|
||||
|
||||
if False:
|
||||
@ -29,6 +31,9 @@ def format_annotation(annotation):
|
||||
|
||||
Displaying complex types from ``typing`` relies on its private API.
|
||||
"""
|
||||
warnings.warn('format_annotation() is now deprecated. '
|
||||
'Please use sphinx.util.inspect.Signature instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
if isinstance(annotation, typing.TypeVar): # type: ignore
|
||||
return annotation.__name__
|
||||
if annotation == Ellipsis:
|
||||
@ -65,7 +70,7 @@ def format_annotation(annotation):
|
||||
elif (hasattr(typing, 'UnionMeta') and
|
||||
isinstance(annotation, typing.UnionMeta) and # type: ignore
|
||||
hasattr(annotation, '__union_params__')):
|
||||
params = annotation.__union_params__ # type: ignore
|
||||
params = annotation.__union_params__
|
||||
if params is not None:
|
||||
param_str = ', '.join(format_annotation(p) for p in params)
|
||||
return '%s[%s]' % (qualified_name, param_str)
|
||||
@ -74,7 +79,7 @@ def format_annotation(annotation):
|
||||
getattr(annotation, '__args__', None) is not None and
|
||||
hasattr(annotation, '__result__')):
|
||||
# Skipped in the case of plain typing.Callable
|
||||
args = annotation.__args__ # type: ignore
|
||||
args = annotation.__args__
|
||||
if args is None:
|
||||
return qualified_name
|
||||
elif args is Ellipsis:
|
||||
@ -84,15 +89,15 @@ def format_annotation(annotation):
|
||||
args_str = '[%s]' % ', '.join(formatted_args)
|
||||
return '%s[%s, %s]' % (qualified_name,
|
||||
args_str,
|
||||
format_annotation(annotation.__result__)) # type: ignore
|
||||
format_annotation(annotation.__result__))
|
||||
elif (hasattr(typing, 'TupleMeta') and
|
||||
isinstance(annotation, typing.TupleMeta) and # type: ignore
|
||||
hasattr(annotation, '__tuple_params__') and
|
||||
hasattr(annotation, '__tuple_use_ellipsis__')):
|
||||
params = annotation.__tuple_params__ # type: ignore
|
||||
params = annotation.__tuple_params__
|
||||
if params is not None:
|
||||
param_strings = [format_annotation(p) for p in params]
|
||||
if annotation.__tuple_use_ellipsis__: # type: ignore
|
||||
if annotation.__tuple_use_ellipsis__:
|
||||
param_strings.append('...')
|
||||
return '%s[%s]' % (qualified_name,
|
||||
', '.join(param_strings))
|
||||
@ -107,6 +112,9 @@ def formatargspec(function, args, varargs=None, varkw=None, defaults=None,
|
||||
An enhanced version of ``inspect.formatargspec()`` that handles typing
|
||||
annotations better.
|
||||
"""
|
||||
warnings.warn('formatargspec() is now deprecated. '
|
||||
'Please use sphinx.util.inspect.Signature instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
|
||||
def format_arg_with_annotation(name):
|
||||
# type: (str) -> str
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Allow reference sections by :ref: role using its title.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
|
@ -49,7 +49,7 @@
|
||||
resolved to a Python object, and otherwise it becomes simple emphasis.
|
||||
This can be used as the default role to make links 'smart'.
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
@ -72,7 +72,9 @@ from sphinx import addnodes
|
||||
from sphinx.environment.adapters.toctree import TocTree
|
||||
from sphinx.util import import_object, rst, logging
|
||||
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
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
@ -152,13 +154,13 @@ def autosummary_table_visit_html(self, node):
|
||||
|
||||
# -- autodoc integration -------------------------------------------------------
|
||||
|
||||
class FakeDirective(object):
|
||||
env = {} # type: Dict
|
||||
genopt = Options()
|
||||
class FakeDirective(DocumenterBridge):
|
||||
def __init__(self):
|
||||
super(FakeDirective, self).__init__({}, None, Options(), 0) # type: ignore
|
||||
|
||||
|
||||
def get_documenter(obj, parent):
|
||||
# type: (Any, Any) -> Type[Documenter]
|
||||
def get_documenter(app, obj, parent):
|
||||
# type: (Sphinx, Any, Any) -> Type[Documenter]
|
||||
"""Get an autodoc.Documenter class suitable for documenting the given
|
||||
object.
|
||||
|
||||
@ -166,8 +168,7 @@ def get_documenter(obj, parent):
|
||||
another Python object (e.g. a module or a class) to which *obj*
|
||||
belongs to.
|
||||
"""
|
||||
from sphinx.ext.autodoc import AutoDirective, DataDocumenter, \
|
||||
ModuleDocumenter
|
||||
from sphinx.ext.autodoc import DataDocumenter, ModuleDocumenter
|
||||
|
||||
if inspect.ismodule(obj):
|
||||
# ModuleDocumenter.can_document_member always returns False
|
||||
@ -175,7 +176,7 @@ def get_documenter(obj, parent):
|
||||
|
||||
# Construct a fake documenter for *parent*
|
||||
if parent is not None:
|
||||
parent_doc_cls = get_documenter(parent, None)
|
||||
parent_doc_cls = get_documenter(app, parent, None)
|
||||
else:
|
||||
parent_doc_cls = ModuleDocumenter
|
||||
|
||||
@ -185,7 +186,7 @@ def get_documenter(obj, parent):
|
||||
parent_doc = parent_doc_cls(FakeDirective(), "")
|
||||
|
||||
# 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 classes:
|
||||
classes.sort(key=lambda cls: cls.priority)
|
||||
@ -288,7 +289,7 @@ class Autosummary(Directive):
|
||||
full_name = modname + '::' + full_name[len(modname) + 1:]
|
||||
# NB. using full_name here is important, since Documenters
|
||||
# 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():
|
||||
self.warn('failed to parse name %s' % real_name)
|
||||
items.append((display_name, '', '', real_name))
|
||||
@ -324,7 +325,7 @@ class Autosummary(Directive):
|
||||
# -- Grab the summary
|
||||
|
||||
documenter.add_content(None)
|
||||
doc = list(documenter.process_doc([self.result.data]))
|
||||
doc = self.result.data
|
||||
|
||||
while doc and not doc[0].strip():
|
||||
doc.pop(0)
|
||||
@ -512,8 +513,7 @@ def _import_by_name(name):
|
||||
modname = '.'.join(name_parts[:-1])
|
||||
if modname:
|
||||
try:
|
||||
__import__(modname)
|
||||
mod = sys.modules[modname]
|
||||
mod = import_module(modname)
|
||||
return getattr(mod, name_parts[-1]), mod, modname
|
||||
except (ImportError, IndexError, AttributeError):
|
||||
pass
|
||||
@ -525,9 +525,10 @@ def _import_by_name(name):
|
||||
last_j = j
|
||||
modname = '.'.join(name_parts[:j])
|
||||
try:
|
||||
__import__(modname)
|
||||
import_module(modname)
|
||||
except ImportError:
|
||||
continue
|
||||
|
||||
if modname in sys.modules:
|
||||
break
|
||||
|
||||
@ -614,7 +615,8 @@ def process_generate_options(app):
|
||||
|
||||
generate_autosummary_docs(genfiles, builder=app.builder,
|
||||
warn=logger.warning, info=logger.info,
|
||||
suffix=suffix, base_path=app.srcdir)
|
||||
suffix=suffix, base_path=app.srcdir,
|
||||
app=app)
|
||||
|
||||
|
||||
def setup(app):
|
||||
|
@ -14,7 +14,7 @@
|
||||
generate:
|
||||
sphinx-autogen -o source/generated source/*.rst
|
||||
|
||||
:copyright: Copyright 2007-2017 by the Sphinx team, see AUTHORS.
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
from __future__ import print_function
|
||||
@ -33,24 +33,11 @@ from sphinx import __display_version__
|
||||
from sphinx import package_dir
|
||||
from sphinx.ext.autosummary import import_by_name, get_documenter
|
||||
from sphinx.jinja2glue import BuiltinTemplateLoader
|
||||
from sphinx.registry import SphinxComponentRegistry
|
||||
from sphinx.util.osutil import ensuredir
|
||||
from sphinx.util.inspect import safe_getattr
|
||||
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:
|
||||
# For type annotation
|
||||
from typing import Any, Callable, Dict, Tuple, List # NOQA
|
||||
@ -60,6 +47,30 @@ if False:
|
||||
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):
|
||||
# type: (unicode) -> None
|
||||
print(msg)
|
||||
@ -81,8 +92,8 @@ def _underline(title, line='='):
|
||||
def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
|
||||
warn=_simple_warn, info=_simple_info,
|
||||
base_path=None, builder=None, template_dir=None,
|
||||
imported_members=False):
|
||||
# type: (List[unicode], unicode, unicode, Callable, Callable, unicode, Builder, unicode, bool) -> None # NOQA
|
||||
imported_members=False, app=None):
|
||||
# type: (List[unicode], unicode, unicode, Callable, Callable, unicode, Builder, unicode, bool, Any) -> None # NOQA
|
||||
|
||||
showed_sources = list(sorted(sources))
|
||||
if len(showed_sources) > 20:
|
||||
@ -148,7 +159,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
|
||||
new_files.append(fn)
|
||||
|
||||
with open(fn, 'w') as f:
|
||||
doc = get_documenter(obj, parent)
|
||||
doc = get_documenter(app, obj, parent)
|
||||
|
||||
if template_name is not None:
|
||||
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)
|
||||
except AttributeError:
|
||||
continue
|
||||
documenter = get_documenter(value, obj)
|
||||
documenter = get_documenter(app, value, obj)
|
||||
if documenter.objtype == typ:
|
||||
if typ == 'method':
|
||||
items.append(name)
|
||||
@ -392,11 +403,14 @@ The format of the autosummary directive is documented in the
|
||||
|
||||
def main(argv=sys.argv[1:]):
|
||||
# type: (List[str]) -> None
|
||||
app = DummyApplication()
|
||||
setup_documenters(app)
|
||||
args = get_parser().parse_args(argv)
|
||||
generate_autosummary_docs(args.source_file, args.output_dir,
|
||||
'.' + args.suffix,
|
||||
template_dir=args.templates,
|
||||
imported_members=args.imported_members)
|
||||
imported_members=args.imported_members,
|
||||
app=app)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user