mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch 'master' into dont_emit_system_message_on_autodoc_warning
This commit is contained in:
commit
326d7e64ce
@ -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
|
||||
|
31
CHANGES
31
CHANGES
@ -13,6 +13,7 @@ Incompatible changes
|
||||
* #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.
|
||||
|
||||
@ -23,6 +24,12 @@ Deprecated
|
||||
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
|
||||
--------------
|
||||
@ -51,7 +58,13 @@ Features added
|
||||
* 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
|
||||
|
||||
Features removed
|
||||
----------------
|
||||
@ -92,6 +105,14 @@ Bugs fixed
|
||||
* #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
|
||||
|
||||
Testing
|
||||
--------
|
||||
@ -117,10 +138,12 @@ Features added
|
||||
* ``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)
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* #4334: sphinx-apidoc: Don't generate references to non-existing files in TOC
|
||||
* #4206: latex: reST label between paragraphs loses paragraph break
|
||||
* #4231: html: Apply fixFirefoxAnchorBug only under Firefox
|
||||
* #4221: napoleon depends on autodoc, but users need to load it manually
|
||||
@ -133,6 +156,12 @@ Bugs fixed
|
||||
* #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:
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
@ -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:
|
||||
|
||||
|
5
EXAMPLES
5
EXAMPLES
@ -93,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/
|
||||
@ -141,6 +141,7 @@ Documentation using the nature theme
|
||||
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)
|
||||
@ -258,7 +259,7 @@ 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/
|
||||
|
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
|
||||
|
@ -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`.
|
||||
@ -315,8 +313,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 +337,23 @@ 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:: tls_verify
|
||||
|
||||
If true, Sphinx verifies server certifications. Default is ``True``.
|
||||
@ -1450,10 +1458,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 +1619,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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
--------
|
||||
|
||||
|
@ -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
|
||||
-----------------------------------------
|
||||
|
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
|
||||
|
31
setup.py
31
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.')
|
||||
@ -72,6 +46,7 @@ extras_require = {
|
||||
'pytest',
|
||||
'pytest-cov',
|
||||
'html5lib',
|
||||
'flake8',
|
||||
],
|
||||
'test:python_version<"3"': [
|
||||
'enum34',
|
||||
|
@ -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',
|
||||
@ -120,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
|
||||
@ -157,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,
|
||||
@ -197,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']
|
||||
@ -444,7 +444,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=()):
|
||||
@ -464,7 +463,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):
|
||||
@ -553,39 +551,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)
|
||||
|
||||
@ -602,21 +591,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
|
||||
@ -658,15 +642,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
|
||||
@ -677,7 +660,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):
|
||||
@ -690,6 +672,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, \
|
||||
@ -79,8 +77,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 +370,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
|
||||
|
@ -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.
|
||||
"""
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
"""
|
||||
|
||||
|
@ -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.
|
||||
"""
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
"""
|
||||
|
||||
|
@ -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.
|
||||
"""
|
||||
|
||||
|
@ -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.
|
||||
"""
|
||||
|
||||
|
@ -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.
|
||||
"""
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
|
@ -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.
|
||||
"""
|
||||
|
||||
|
@ -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.
|
||||
"""
|
||||
|
||||
|
@ -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
|
||||
@ -36,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
|
||||
)
|
||||
@ -79,13 +79,6 @@ DEFAULTS = {
|
||||
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
|
||||
@ -413,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'] = ''
|
||||
@ -428,9 +421,9 @@ 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
|
||||
|
@ -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
|
||||
|
@ -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}, " \
|
||||
@ -155,6 +157,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
|
||||
|
@ -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.
|
||||
"""
|
||||
|
||||
|
@ -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.
|
||||
"""
|
||||
|
||||
@ -1285,7 +1285,7 @@ class ASTTemplateParamType(ASTBase):
|
||||
def name(self):
|
||||
# type: () -> ASTNestedName
|
||||
id = self.get_identifier()
|
||||
return ASTNestedName([ASTNestedNameElement(id, None)], rooted=False)
|
||||
return ASTNestedName([ASTNestedNameElement(id, None)], [False], rooted=False)
|
||||
|
||||
@property
|
||||
def isPack(self):
|
||||
@ -1314,6 +1314,44 @@ class ASTTemplateParamType(ASTBase):
|
||||
self.data.describe_signature(signode, mode, env, symbol)
|
||||
|
||||
|
||||
class ASTTemplateParamConstrainedTypeWithInit(ASTBase):
|
||||
def __init__(self, type, init):
|
||||
# type: (Any, Any) -> None
|
||||
assert type
|
||||
self.type = type
|
||||
self.init = init
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
# type: () -> ASTNestedName
|
||||
return self.type.name
|
||||
|
||||
def get_id(self, version, objectType=None, symbol=None):
|
||||
# type: (int, unicode, Symbol) -> unicode
|
||||
# this is not part of the normal name mangling in C++
|
||||
assert version >= 2
|
||||
if symbol:
|
||||
# the anchor will be our parent
|
||||
return symbol.parent.declaration.get_id(version, prefixed=False)
|
||||
else:
|
||||
return self.type.get_id(version)
|
||||
|
||||
def __unicode__(self):
|
||||
# type: () -> unicode
|
||||
res = text_type(self.type)
|
||||
if self.init:
|
||||
res += " = "
|
||||
res += text_type(self.init)
|
||||
return res
|
||||
|
||||
def describe_signature(self, signode, mode, env, symbol):
|
||||
# type: (addnodes.desc_signature, unicode, BuildEnvironment, Symbol) -> None
|
||||
self.type.describe_signature(signode, mode, env, symbol)
|
||||
if self.init:
|
||||
signode += nodes.Text(" = ")
|
||||
self.init.describe_signature(signode, mode, env, symbol)
|
||||
|
||||
|
||||
class ASTTemplateParamTemplateType(ASTBase):
|
||||
def __init__(self, nestedParams, data):
|
||||
# type: (Any, Any) -> None
|
||||
@ -1326,7 +1364,7 @@ class ASTTemplateParamTemplateType(ASTBase):
|
||||
def name(self):
|
||||
# type: () -> ASTNestedName
|
||||
id = self.get_identifier()
|
||||
return ASTNestedName([ASTNestedNameElement(id, None)], rooted=False)
|
||||
return ASTNestedName([ASTNestedNameElement(id, None)], [False], rooted=False)
|
||||
|
||||
def get_identifier(self):
|
||||
# type: () -> unicode
|
||||
@ -1363,16 +1401,16 @@ class ASTTemplateParamNonType(ASTBase):
|
||||
def name(self):
|
||||
# type: () -> ASTNestedName
|
||||
id = self.get_identifier()
|
||||
return ASTNestedName([ASTNestedNameElement(id, None)], rooted=False)
|
||||
return ASTNestedName([ASTNestedNameElement(id, None)], [False], rooted=False)
|
||||
|
||||
def get_identifier(self):
|
||||
# type: () -> unicode
|
||||
name = self.param.name
|
||||
if name:
|
||||
assert len(name.names) == 1
|
||||
assert name.names[0].identifier
|
||||
assert name.names[0].identOrOp
|
||||
assert not name.names[0].templateArgs
|
||||
return name.names[0].identifier
|
||||
return name.names[0].identOrOp
|
||||
else:
|
||||
return None
|
||||
|
||||
@ -1456,7 +1494,7 @@ class ASTTemplateIntroductionParameter(ASTBase):
|
||||
def name(self):
|
||||
# type: () -> ASTNestedName
|
||||
id = self.get_identifier()
|
||||
return ASTNestedName([ASTNestedNameElement(id, None)], rooted=False)
|
||||
return ASTNestedName([ASTNestedNameElement(id, None)], [False], rooted=False)
|
||||
|
||||
@property
|
||||
def isPack(self):
|
||||
@ -1612,8 +1650,8 @@ class ASTOperatorBuildIn(ASTBase):
|
||||
else:
|
||||
return u'operator' + self.op
|
||||
|
||||
def describe_signature(self, signode, mode, env, prefix, symbol):
|
||||
# type: (addnodes.desc_signature, unicode, BuildEnvironment, unicode, Symbol) -> None
|
||||
def describe_signature(self, signode, mode, env, prefix, templateArgs, symbol):
|
||||
# type: (addnodes.desc_signature, unicode, Any, unicode, unicode, Symbol) -> None
|
||||
_verify_description_mode(mode)
|
||||
identifier = text_type(self)
|
||||
if mode == 'lastIsName':
|
||||
@ -1646,8 +1684,8 @@ class ASTOperatorType(ASTBase):
|
||||
# type: () -> unicode
|
||||
return text_type(self)
|
||||
|
||||
def describe_signature(self, signode, mode, env, prefix, symbol):
|
||||
# type: (addnodes.desc_signature, unicode, BuildEnvironment, unicode, Symbol) -> None
|
||||
def describe_signature(self, signode, mode, env, prefix, templateArgs, symbol):
|
||||
# type: (addnodes.desc_signature, unicode, Any, unicode, unicode, Symbol) -> None
|
||||
_verify_description_mode(mode)
|
||||
identifier = text_type(self)
|
||||
if mode == 'lastIsName':
|
||||
@ -1676,8 +1714,8 @@ class ASTOperatorLiteral(ASTBase):
|
||||
# type: () -> unicode
|
||||
return u'operator""' + text_type(self.identifier)
|
||||
|
||||
def describe_signature(self, signode, mode, env, prefix, symbol):
|
||||
# type: (addnodes.desc_signature, unicode, BuildEnvironment, unicode, Symbol) -> None
|
||||
def describe_signature(self, signode, mode, env, prefix, templateArgs, symbol):
|
||||
# type: (addnodes.desc_signature, unicode, Any, unicode, unicode, Symbol) -> None
|
||||
_verify_description_mode(mode)
|
||||
identifier = text_type(self)
|
||||
if mode == 'lastIsName':
|
||||
@ -1750,9 +1788,9 @@ class ASTTemplateArgs(ASTBase):
|
||||
|
||||
|
||||
class ASTNestedNameElement(ASTBase):
|
||||
def __init__(self, identifier, templateArgs):
|
||||
def __init__(self, identOrOp, templateArgs):
|
||||
# type: (Any, Any) -> None
|
||||
self.identifier = identifier
|
||||
self.identOrOp = identOrOp
|
||||
self.templateArgs = templateArgs
|
||||
|
||||
def is_operator(self):
|
||||
@ -1761,14 +1799,14 @@ class ASTNestedNameElement(ASTBase):
|
||||
|
||||
def get_id(self, version):
|
||||
# type: (int) -> unicode
|
||||
res = self.identifier.get_id(version)
|
||||
res = self.identOrOp.get_id(version)
|
||||
if self.templateArgs:
|
||||
res += self.templateArgs.get_id(version)
|
||||
return res
|
||||
|
||||
def __unicode__(self):
|
||||
# type: () -> unicode
|
||||
res = text_type(self.identifier)
|
||||
res = text_type(self.identOrOp)
|
||||
if self.templateArgs:
|
||||
res += text_type(self.templateArgs)
|
||||
return res
|
||||
@ -1776,16 +1814,18 @@ class ASTNestedNameElement(ASTBase):
|
||||
def describe_signature(self, signode, mode, env, prefix, symbol):
|
||||
# type: (addnodes.desc_signature, unicode, BuildEnvironment, unicode, Symbol) -> None
|
||||
tArgs = text_type(self.templateArgs) if self.templateArgs is not None else ''
|
||||
self.identifier.describe_signature(signode, mode, env, prefix, tArgs, symbol)
|
||||
self.identOrOp.describe_signature(signode, mode, env, prefix, tArgs, symbol)
|
||||
if self.templateArgs is not None:
|
||||
self.templateArgs.describe_signature(signode, mode, env, symbol)
|
||||
|
||||
|
||||
class ASTNestedName(ASTBase):
|
||||
def __init__(self, names, rooted):
|
||||
# type: (List[Any], bool) -> None
|
||||
def __init__(self, names, templates, rooted):
|
||||
# type: (List[Any], List[bool], bool) -> None
|
||||
assert len(names) > 0
|
||||
self.names = names
|
||||
self.templates = templates
|
||||
assert len(self.names) == len(self.templates)
|
||||
self.rooted = rooted
|
||||
|
||||
@property
|
||||
@ -1826,8 +1866,13 @@ class ASTNestedName(ASTBase):
|
||||
res = [] # type: List[unicode]
|
||||
if self.rooted:
|
||||
res.append('')
|
||||
for n in self.names:
|
||||
res.append(text_type(n))
|
||||
for i in range(len(self.names)):
|
||||
n = self.names[i]
|
||||
t = self.templates[i]
|
||||
if t:
|
||||
res.append("template " + text_type(n))
|
||||
else:
|
||||
res.append(text_type(n))
|
||||
return '::'.join(res)
|
||||
|
||||
def describe_signature(self, signode, mode, env, symbol):
|
||||
@ -1854,10 +1899,14 @@ class ASTNestedName(ASTBase):
|
||||
prefix = '' # type: unicode
|
||||
first = True
|
||||
names = self.names[:-1] if mode == 'lastIsName' else self.names
|
||||
for name in names:
|
||||
for i in range(len(names)):
|
||||
name = names[i]
|
||||
template = self.templates[i]
|
||||
if not first:
|
||||
signode += nodes.Text('::')
|
||||
prefix += '::'
|
||||
if template:
|
||||
signode += nodes.Text("template ")
|
||||
first = False
|
||||
if name != '':
|
||||
if (name.templateArgs and # type: ignore
|
||||
@ -1870,6 +1919,8 @@ class ASTNestedName(ASTBase):
|
||||
if mode == 'lastIsName':
|
||||
if len(self.names) > 1:
|
||||
signode += addnodes.desc_addname('::', '::')
|
||||
if self.templates[-1]:
|
||||
signode += nodes.Text("template ")
|
||||
self.names[-1].describe_signature(signode, mode, env, '', symbol)
|
||||
else:
|
||||
raise Exception('Unknown description mode: %s' % mode)
|
||||
@ -3259,23 +3310,20 @@ class Symbol(object):
|
||||
# type: () -> None
|
||||
if not self.parent:
|
||||
# parent == None means global scope, so declaration means a parent
|
||||
assert not self.identifier
|
||||
assert not self.identOrOp
|
||||
assert not self.templateParams
|
||||
assert not self.templateArgs
|
||||
assert not self.declaration
|
||||
assert not self.docname
|
||||
else:
|
||||
if not self.identifier:
|
||||
# in case it's an operator
|
||||
assert self.declaration
|
||||
if self.declaration:
|
||||
assert self.docname
|
||||
|
||||
def __init__(self, parent, identifier,
|
||||
def __init__(self, parent, identOrOp,
|
||||
templateParams, templateArgs, declaration, docname):
|
||||
# type: (Any, Any, Any, Any, Any, unicode) -> None
|
||||
self.parent = parent
|
||||
self.identifier = identifier
|
||||
self.identOrOp = identOrOp
|
||||
self.templateParams = templateParams # template<templateParams>
|
||||
self.templateArgs = templateArgs # identifier<templateArgs>
|
||||
self.declaration = declaration
|
||||
@ -3300,7 +3348,7 @@ class Symbol(object):
|
||||
else:
|
||||
decl = None
|
||||
nne = ASTNestedNameElement(p.get_identifier(), None)
|
||||
nn = ASTNestedName([nne], rooted=False)
|
||||
nn = ASTNestedName([nne], [False], rooted=False)
|
||||
self._add_symbols(nn, [], decl, docname)
|
||||
# add symbols for function parameters, if any
|
||||
if declaration is not None and declaration.function_params is not None:
|
||||
@ -3314,8 +3362,8 @@ class Symbol(object):
|
||||
decl = ASTDeclaration('functionParam', None, None, p)
|
||||
assert not nn.rooted
|
||||
assert len(nn.names) == 1
|
||||
identifier = nn.names[0].identifier
|
||||
Symbol(parent=self, identifier=identifier,
|
||||
identOrOp = nn.names[0].identOrOp
|
||||
Symbol(parent=self, identOrOp=identOrOp,
|
||||
templateParams=None, templateArgs=None,
|
||||
declaration=decl, docname=docname)
|
||||
|
||||
@ -3339,12 +3387,7 @@ class Symbol(object):
|
||||
if sChild.declaration and sChild.docname == docname:
|
||||
sChild.declaration = None
|
||||
sChild.docname = None
|
||||
# Just remove operators, because there is no identification if
|
||||
# they got removed.
|
||||
# Don't remove other symbols because they may be used in namespace
|
||||
# directives.
|
||||
if sChild.identifier or sChild.declaration:
|
||||
newChildren.append(sChild)
|
||||
newChildren.append(sChild)
|
||||
self.children = newChildren
|
||||
|
||||
def get_all_symbols(self):
|
||||
@ -3364,26 +3407,22 @@ class Symbol(object):
|
||||
symbols.reverse()
|
||||
key = []
|
||||
for s in symbols:
|
||||
if s.identifier:
|
||||
nne = ASTNestedNameElement(s.identifier, s.templateArgs)
|
||||
else:
|
||||
assert s.declaration
|
||||
nne = s.declaration.name.names[-1]
|
||||
nne = ASTNestedNameElement(s.identOrOp, s.templateArgs)
|
||||
key.append((nne, s.templateParams))
|
||||
return key
|
||||
|
||||
def get_full_nested_name(self):
|
||||
# type: () -> ASTNestedName
|
||||
names = []
|
||||
templates = []
|
||||
for nne, templateParams in self.get_lookup_key():
|
||||
names.append(nne)
|
||||
return ASTNestedName(names, rooted=False)
|
||||
templates.append(False)
|
||||
return ASTNestedName(names, templates, rooted=False)
|
||||
|
||||
def _find_named_symbol(self, identifier, templateParams,
|
||||
templateArgs, operator,
|
||||
def _find_named_symbol(self, identOrOp, templateParams, templateArgs,
|
||||
templateShorthand, matchSelf):
|
||||
# type: (Any, Any, Any, Any, Any, bool) -> Symbol
|
||||
assert (identifier is None) != (operator is None)
|
||||
# type: (Any, Any, Any, Any, bool) -> Symbol
|
||||
|
||||
def isSpecialization():
|
||||
# the names of the template parameters must be given exactly as args
|
||||
@ -3411,17 +3450,8 @@ class Symbol(object):
|
||||
templateArgs = None
|
||||
|
||||
def matches(s):
|
||||
if s.identifier != identifier:
|
||||
if s.identOrOp != identOrOp:
|
||||
return False
|
||||
if not s.identifier:
|
||||
if not s.declaration:
|
||||
return False
|
||||
assert operator
|
||||
name = s.declaration.name.names[-1]
|
||||
if not name.is_operator():
|
||||
return False
|
||||
if text_type(name) != text_type(operator):
|
||||
return False
|
||||
if (s.templateParams is None) != (templateParams is None):
|
||||
if templateParams is not None:
|
||||
# we query with params, they must match params
|
||||
@ -3462,10 +3492,7 @@ class Symbol(object):
|
||||
names = nestedName.names
|
||||
iTemplateDecl = 0
|
||||
for name in names[:-1]:
|
||||
# there shouldn't be anything inside an operator
|
||||
# (other than template parameters, which are not added this way, right?)
|
||||
assert not name.is_operator()
|
||||
identifier = name.identifier
|
||||
identOrOp = name.identOrOp
|
||||
templateArgs = name.templateArgs
|
||||
if templateArgs:
|
||||
assert iTemplateDecl < len(templateDecls)
|
||||
@ -3473,27 +3500,20 @@ class Symbol(object):
|
||||
iTemplateDecl += 1
|
||||
else:
|
||||
templateParams = None
|
||||
symbol = parentSymbol._find_named_symbol(identifier,
|
||||
symbol = parentSymbol._find_named_symbol(identOrOp,
|
||||
templateParams,
|
||||
templateArgs,
|
||||
operator=None,
|
||||
templateShorthand=False,
|
||||
matchSelf=False)
|
||||
if symbol is None:
|
||||
symbol = Symbol(parent=parentSymbol, identifier=identifier,
|
||||
symbol = Symbol(parent=parentSymbol, identOrOp=identOrOp,
|
||||
templateParams=templateParams,
|
||||
templateArgs=templateArgs, declaration=None,
|
||||
docname=None)
|
||||
parentSymbol = symbol
|
||||
name = names[-1]
|
||||
if name.is_operator():
|
||||
identifier = None
|
||||
templateArgs = None
|
||||
operator = name
|
||||
else:
|
||||
identifier = name.identifier
|
||||
templateArgs = name.templateArgs
|
||||
operator = None
|
||||
identOrOp = name.identOrOp
|
||||
templateArgs = name.templateArgs
|
||||
if iTemplateDecl < len(templateDecls):
|
||||
if iTemplateDecl + 1 != len(templateDecls):
|
||||
print(text_type(templateDecls))
|
||||
@ -3503,10 +3523,9 @@ class Symbol(object):
|
||||
else:
|
||||
assert iTemplateDecl == len(templateDecls)
|
||||
templateParams = None
|
||||
symbol = parentSymbol._find_named_symbol(identifier,
|
||||
symbol = parentSymbol._find_named_symbol(identOrOp,
|
||||
templateParams,
|
||||
templateArgs,
|
||||
operator,
|
||||
templateShorthand=False,
|
||||
matchSelf=False)
|
||||
if symbol:
|
||||
@ -3523,7 +3542,7 @@ class Symbol(object):
|
||||
return symbol
|
||||
# It may simply be a function overload, so let's compare ids.
|
||||
isRedeclaration = True
|
||||
candSymbol = Symbol(parent=parentSymbol, identifier=identifier,
|
||||
candSymbol = Symbol(parent=parentSymbol, identOrOp=identOrOp,
|
||||
templateParams=templateParams,
|
||||
templateArgs=templateArgs,
|
||||
declaration=declaration,
|
||||
@ -3543,7 +3562,7 @@ class Symbol(object):
|
||||
candSymbol.isRedeclaration = True
|
||||
raise _DuplicateSymbolError(symbol, declaration)
|
||||
else:
|
||||
symbol = Symbol(parent=parentSymbol, identifier=identifier,
|
||||
symbol = Symbol(parent=parentSymbol, identOrOp=identOrOp,
|
||||
templateParams=templateParams,
|
||||
templateArgs=templateArgs,
|
||||
declaration=declaration,
|
||||
@ -3554,22 +3573,9 @@ class Symbol(object):
|
||||
# type: (Any, List[unicode], BuildEnvironment) -> None
|
||||
assert other is not None
|
||||
for otherChild in other.children:
|
||||
if not otherChild.identifier:
|
||||
if not otherChild.declaration:
|
||||
print("Problem in symbol tree merging")
|
||||
print("OtherChild.dump:")
|
||||
print(otherChild.dump(0))
|
||||
print("Other.dump:")
|
||||
print(other.dump(0))
|
||||
assert otherChild.declaration
|
||||
operator = otherChild.declaration.name.names[-1]
|
||||
assert operator.is_operator()
|
||||
else:
|
||||
operator = None
|
||||
ourChild = self._find_named_symbol(otherChild.identifier,
|
||||
ourChild = self._find_named_symbol(otherChild.identOrOp,
|
||||
otherChild.templateParams,
|
||||
otherChild.templateArgs,
|
||||
operator,
|
||||
templateShorthand=False,
|
||||
matchSelf=False)
|
||||
if ourChild is None:
|
||||
@ -3614,12 +3620,12 @@ class Symbol(object):
|
||||
templateDecls = []
|
||||
return self._add_symbols(nestedName, templateDecls, declaration, docname)
|
||||
|
||||
def find_identifier(self, identifier, matchSelf):
|
||||
def find_identifier(self, identOrOp, matchSelf):
|
||||
# type: (Any, bool) -> Symbol
|
||||
if matchSelf and self.identifier and self.identifier == identifier:
|
||||
if matchSelf and self.identOrOp == identOrOp:
|
||||
return self
|
||||
for s in self.children:
|
||||
if s.identifier and s.identifier == identifier:
|
||||
if s.identOrOp == identOrOp:
|
||||
return s
|
||||
return None
|
||||
|
||||
@ -3627,16 +3633,10 @@ class Symbol(object):
|
||||
# type: (List[Tuple[Any, Any]]) -> Symbol
|
||||
s = self
|
||||
for name, templateParams in key:
|
||||
if name.is_operator():
|
||||
identifier = None
|
||||
templateArgs = None
|
||||
operator = name
|
||||
else:
|
||||
identifier = name.identifier
|
||||
templateArgs = name.templateArgs
|
||||
operator = None
|
||||
s = s._find_named_symbol(identifier, templateParams,
|
||||
templateArgs, operator,
|
||||
identOrOp = name.identOrOp
|
||||
templateArgs = name.templateArgs
|
||||
s = s._find_named_symbol(identOrOp,
|
||||
templateParams, templateArgs,
|
||||
templateShorthand=False,
|
||||
matchSelf=False)
|
||||
if not s:
|
||||
@ -3660,13 +3660,13 @@ class Symbol(object):
|
||||
firstName = names[0]
|
||||
if not firstName.is_operator():
|
||||
while parentSymbol.parent:
|
||||
if parentSymbol.find_identifier(firstName.identifier,
|
||||
if parentSymbol.find_identifier(firstName.identOrOp,
|
||||
matchSelf=matchSelf):
|
||||
# if we are in the scope of a constructor but wants to reference the class
|
||||
# we need to walk one extra up
|
||||
if (len(names) == 1 and typ == 'class' and matchSelf and
|
||||
parentSymbol.parent and parentSymbol.parent.identifier and
|
||||
parentSymbol.parent.identifier == firstName.identifier):
|
||||
parentSymbol.parent and
|
||||
parentSymbol.parent.identOrOp == firstName.identOrOp):
|
||||
pass
|
||||
else:
|
||||
break
|
||||
@ -3675,48 +3675,36 @@ class Symbol(object):
|
||||
for iName in range(len(names)):
|
||||
name = names[iName]
|
||||
if iName + 1 == len(names):
|
||||
if name.is_operator():
|
||||
identifier = None
|
||||
templateArgs = None
|
||||
operator = name
|
||||
else:
|
||||
identifier = name.identifier
|
||||
templateArgs = name.templateArgs
|
||||
operator = None
|
||||
identOrOp = name.identOrOp
|
||||
templateArgs = name.templateArgs
|
||||
if iTemplateDecl < len(templateDecls):
|
||||
assert iTemplateDecl + 1 == len(templateDecls)
|
||||
templateParams = templateDecls[iTemplateDecl]
|
||||
else:
|
||||
assert iTemplateDecl == len(templateDecls)
|
||||
templateParams = None
|
||||
symbol = parentSymbol._find_named_symbol(identifier,
|
||||
symbol = parentSymbol._find_named_symbol(identOrOp,
|
||||
templateParams, templateArgs,
|
||||
operator,
|
||||
templateShorthand=templateShorthand,
|
||||
matchSelf=matchSelf)
|
||||
if symbol is not None:
|
||||
return symbol
|
||||
# try without template params and args
|
||||
symbol = parentSymbol._find_named_symbol(identifier,
|
||||
symbol = parentSymbol._find_named_symbol(identOrOp,
|
||||
None, None,
|
||||
operator,
|
||||
templateShorthand=templateShorthand,
|
||||
matchSelf=matchSelf)
|
||||
return symbol
|
||||
else:
|
||||
# there shouldn't be anything inside an operator
|
||||
assert not name.is_operator()
|
||||
identifier = name.identifier
|
||||
identOrOp = name.identOrOp
|
||||
templateArgs = name.templateArgs
|
||||
if templateArgs and iTemplateDecl < len(templateDecls):
|
||||
templateParams = templateDecls[iTemplateDecl]
|
||||
iTemplateDecl += 1
|
||||
else:
|
||||
templateParams = None
|
||||
symbol = parentSymbol._find_named_symbol(identifier,
|
||||
templateParams,
|
||||
templateArgs,
|
||||
operator=None,
|
||||
symbol = parentSymbol._find_named_symbol(identOrOp,
|
||||
templateParams, templateArgs,
|
||||
templateShorthand=templateShorthand,
|
||||
matchSelf=matchSelf)
|
||||
if symbol is None:
|
||||
@ -3739,8 +3727,8 @@ class Symbol(object):
|
||||
res.append(text_type(self.templateParams))
|
||||
res.append('\n')
|
||||
res.append('\t' * indent)
|
||||
if self.identifier:
|
||||
res.append(text_type(self.identifier))
|
||||
if self.identOrOp:
|
||||
res.append(text_type(self.identOrOp))
|
||||
else:
|
||||
res.append(text_type(self.declaration))
|
||||
if self.templateArgs:
|
||||
@ -3781,6 +3769,8 @@ class DefinitionParser(object):
|
||||
self.last_match = None # type: Match
|
||||
self._previous_state = (0, None) # type: Tuple[int, Match]
|
||||
self.otherErrors = [] # type: List[DefinitionError]
|
||||
# in our tests the following is set to False to capture bad parsing
|
||||
self.allowFallbackExpressionParsing = True
|
||||
|
||||
self.warnEnv = warnEnv
|
||||
self.config = config
|
||||
@ -4121,6 +4111,13 @@ class DefinitionParser(object):
|
||||
# TODO: hmm, would we need to try both with operatorCast and with None?
|
||||
prefix = self._parse_type(False, 'operatorCast')
|
||||
prefixType = 'typeOperatorCast'
|
||||
# | simple-type-specifier "(" expression-list [opt] ")"
|
||||
# | simple-type-specifier braced-init-list
|
||||
# | typename-specifier "(" expression-list [opt] ")"
|
||||
# | typename-specifier braced-init-list
|
||||
self.skip_ws()
|
||||
if self.current_char != '(' and self.current_char != '{':
|
||||
self.fail("Expecting '(' or '{' after type in cast expression.")
|
||||
except DefinitionError as eInner:
|
||||
self.pos = pos
|
||||
header = "Error in postfix expression, expected primary expression or type."
|
||||
@ -4361,7 +4358,7 @@ class DefinitionParser(object):
|
||||
# TODO: actually parse the second production
|
||||
return self._parse_assignment_expression(inTemplate=inTemplate)
|
||||
|
||||
def _parse_expression_fallback(self, end, parser):
|
||||
def _parse_expression_fallback(self, end, parser, allow=True):
|
||||
# Stupidly "parse" an expression.
|
||||
# 'end' should be a list of characters which ends the expression.
|
||||
|
||||
@ -4370,6 +4367,10 @@ class DefinitionParser(object):
|
||||
try:
|
||||
return parser()
|
||||
except DefinitionError as e:
|
||||
# some places (e.g., template parameters) we really don't want to use fallback,
|
||||
# and for testing we may want to globally disable it
|
||||
if not allow or not self.allowFallbackExpressionParsing:
|
||||
raise
|
||||
self.warn("Parsing of expression failed. Using fallback parser."
|
||||
" Error was:\n%s" % e.description)
|
||||
self.pos = prevPos
|
||||
@ -4480,7 +4481,8 @@ class DefinitionParser(object):
|
||||
|
||||
def _parse_nested_name(self, memberPointer=False):
|
||||
# type: (bool) -> ASTNestedName
|
||||
names = []
|
||||
names = [] # type: List[Any]
|
||||
templates = [] # type: List[bool]
|
||||
|
||||
self.skip_ws()
|
||||
rooted = False
|
||||
@ -4488,14 +4490,17 @@ class DefinitionParser(object):
|
||||
rooted = True
|
||||
while 1:
|
||||
self.skip_ws()
|
||||
if self.skip_word_and_ws('template'):
|
||||
self.fail("'template' in nested name not implemented.")
|
||||
elif self.skip_word_and_ws('operator'):
|
||||
op = self._parse_operator()
|
||||
names.append(op)
|
||||
if len(names) > 0:
|
||||
template = self.skip_word_and_ws('template')
|
||||
else:
|
||||
template = False
|
||||
templates.append(template)
|
||||
if self.skip_word_and_ws('operator'):
|
||||
identOrOp = self._parse_operator()
|
||||
else:
|
||||
if not self.match(_identifier_re):
|
||||
if memberPointer and len(names) > 0:
|
||||
templates.pop()
|
||||
break
|
||||
self.fail("Expected identifier in nested name.")
|
||||
identifier = self.matched_text
|
||||
@ -4503,24 +4508,24 @@ class DefinitionParser(object):
|
||||
if identifier in _keywords:
|
||||
self.fail("Expected identifier in nested name, "
|
||||
"got keyword: %s" % identifier)
|
||||
# try greedily to get template parameters,
|
||||
# but otherwise a < might be because we are in an expression
|
||||
pos = self.pos
|
||||
try:
|
||||
templateArgs = self._parse_template_argument_list()
|
||||
except DefinitionError as ex:
|
||||
self.pos = pos
|
||||
templateArgs = None
|
||||
self.otherErrors.append(ex)
|
||||
identifier = ASTIdentifier(identifier) # type: ignore
|
||||
names.append(ASTNestedNameElement(identifier, templateArgs))
|
||||
identOrOp = ASTIdentifier(identifier)
|
||||
# try greedily to get template arguments,
|
||||
# but otherwise a < might be because we are in an expression
|
||||
pos = self.pos
|
||||
try:
|
||||
templateArgs = self._parse_template_argument_list()
|
||||
except DefinitionError as ex:
|
||||
self.pos = pos
|
||||
templateArgs = None
|
||||
self.otherErrors.append(ex)
|
||||
names.append(ASTNestedNameElement(identOrOp, templateArgs))
|
||||
|
||||
self.skip_ws()
|
||||
if not self.skip_string('::'):
|
||||
if memberPointer:
|
||||
self.fail("Expected '::' in pointer to member (function).")
|
||||
break
|
||||
return ASTNestedName(names, rooted)
|
||||
return ASTNestedName(names, templates, rooted)
|
||||
|
||||
def _parse_trailing_type_spec(self):
|
||||
# type: () -> Any
|
||||
@ -4598,7 +4603,7 @@ class DefinitionParser(object):
|
||||
self.fail('Expected ")" after "..." in '
|
||||
'parameters_and_qualifiers.')
|
||||
break
|
||||
# note: it seems that function arguments can always sbe named,
|
||||
# note: it seems that function arguments can always be named,
|
||||
# even in function pointers and similar.
|
||||
arg = self._parse_type_with_init(outer=None, named='single')
|
||||
# TODO: parse default parameters # TODO: didn't we just do that?
|
||||
@ -4785,7 +4790,7 @@ class DefinitionParser(object):
|
||||
if self.match(_identifier_re):
|
||||
identifier = ASTIdentifier(self.matched_text)
|
||||
nne = ASTNestedNameElement(identifier, None)
|
||||
declId = ASTNestedName([nne], rooted=False)
|
||||
declId = ASTNestedName([nne], [False], rooted=False)
|
||||
# if it's a member pointer, we may have '::', which should be an error
|
||||
self.skip_ws()
|
||||
if self.current_char == ':':
|
||||
@ -4919,8 +4924,8 @@ class DefinitionParser(object):
|
||||
header = "Error in declarator or parameters and qualifiers"
|
||||
raise self._make_multi_error(prevErrors, header)
|
||||
|
||||
def _parse_initializer(self, outer=None):
|
||||
# type: (unicode) -> ASTInitializer
|
||||
def _parse_initializer(self, outer=None, allowFallback=True):
|
||||
# type: (unicode, bool) -> ASTInitializer
|
||||
self.skip_ws()
|
||||
# TODO: support paren and brace initialization for memberObject
|
||||
if not self.skip_string('='):
|
||||
@ -4929,15 +4934,18 @@ class DefinitionParser(object):
|
||||
if outer == 'member':
|
||||
def parser():
|
||||
return self._parse_assignment_expression(inTemplate=False)
|
||||
value = self._parse_expression_fallback([], parser)
|
||||
value = self._parse_expression_fallback([], parser,
|
||||
allow=allowFallback)
|
||||
elif outer == 'templateParam':
|
||||
def parser():
|
||||
return self._parse_assignment_expression(inTemplate=True)
|
||||
value = self._parse_expression_fallback([',', '>'], parser)
|
||||
value = self._parse_expression_fallback([',', '>'], parser,
|
||||
allow=allowFallback)
|
||||
elif outer is None: # function parameter
|
||||
def parser():
|
||||
return self._parse_assignment_expression(inTemplate=False)
|
||||
value = self._parse_expression_fallback([',', ')'], parser)
|
||||
value = self._parse_expression_fallback([',', ')'], parser,
|
||||
allow=allowFallback)
|
||||
else:
|
||||
self.fail("Internal error, initializer for outer '%s' not "
|
||||
"implemented." % outer)
|
||||
@ -5027,12 +5035,48 @@ class DefinitionParser(object):
|
||||
return ASTType(declSpecs, decl)
|
||||
|
||||
def _parse_type_with_init(self, named, outer):
|
||||
# type: (Union[bool, unicode], unicode) -> ASTTypeWithInit
|
||||
# type: (Union[bool, unicode], unicode) -> Any
|
||||
if outer:
|
||||
assert outer in ('type', 'member', 'function', 'templateParam')
|
||||
type = self._parse_type(outer=outer, named=named)
|
||||
init = self._parse_initializer(outer=outer)
|
||||
return ASTTypeWithInit(type, init)
|
||||
if outer != 'templateParam':
|
||||
init = self._parse_initializer(outer=outer)
|
||||
return ASTTypeWithInit(type, init)
|
||||
# it could also be a constrained type parameter, e.g., C T = int&
|
||||
pos = self.pos
|
||||
eExpr = None
|
||||
try:
|
||||
init = self._parse_initializer(outer=outer, allowFallback=False)
|
||||
# note: init may be None if there is no =
|
||||
if init is None:
|
||||
return ASTTypeWithInit(type, None)
|
||||
# we parsed an expression, so we must have a , or a >,
|
||||
# otherwise the expression didn't get everything
|
||||
self.skip_ws()
|
||||
if self.current_char != ',' and self.current_char != '>':
|
||||
# pretend it didn't happen
|
||||
self.pos = pos
|
||||
init = None
|
||||
else:
|
||||
# we assume that it was indeed an expression
|
||||
return ASTTypeWithInit(type, init)
|
||||
except DefinitionError as e:
|
||||
self.pos = pos
|
||||
eExpr = e
|
||||
if not self.skip_string("="):
|
||||
return ASTTypeWithInit(type, None)
|
||||
try:
|
||||
typeInit = self._parse_type(named=False, outer=None)
|
||||
return ASTTemplateParamConstrainedTypeWithInit(type, typeInit)
|
||||
except DefinitionError as eType:
|
||||
if eExpr is None:
|
||||
raise eType
|
||||
errs = []
|
||||
errs.append((eExpr, "If default is an expression"))
|
||||
errs.append((eType, "If default is a type"))
|
||||
msg = "Error in non-type template parameter"
|
||||
msg += " or constrianted template paramter."
|
||||
raise self._make_multi_error(errs, msg)
|
||||
|
||||
def _parse_type_using(self):
|
||||
# type: () -> ASTTypeUsing
|
||||
@ -5156,13 +5200,14 @@ class DefinitionParser(object):
|
||||
param = ASTTemplateParamType(data)
|
||||
templateParams.append(param)
|
||||
else:
|
||||
# declare a non-type parameter
|
||||
# declare a non-type parameter, or constrained type parameter
|
||||
pos = self.pos
|
||||
try:
|
||||
param = self._parse_type_with_init('maybe', 'templateParam')
|
||||
templateParams.append(ASTTemplateParamNonType(param))
|
||||
except DefinitionError as e:
|
||||
prevErrors.append((e, "If non-type template parameter"))
|
||||
msg = "If non-type template parameter or constrained template parameter"
|
||||
prevErrors.append((e, msg))
|
||||
self.pos = pos
|
||||
self.skip_ws()
|
||||
if self.skip_string('>'):
|
||||
@ -5386,7 +5431,7 @@ class DefinitionParser(object):
|
||||
def _make_phony_error_name():
|
||||
# type: () -> ASTNestedName
|
||||
nne = ASTNestedNameElement(ASTIdentifier("PhonyNameDueToError"), None)
|
||||
return ASTNestedName([nne], rooted=False)
|
||||
return ASTNestedName([nne], [False], rooted=False)
|
||||
|
||||
|
||||
class CPPObject(ObjectDescription):
|
||||
@ -5421,7 +5466,7 @@ class CPPObject(ObjectDescription):
|
||||
# then add the name to the parent scope
|
||||
symbol = ast.symbol
|
||||
assert symbol
|
||||
assert symbol.identifier is not None
|
||||
assert symbol.identOrOp is not None
|
||||
assert symbol.templateParams is None
|
||||
assert symbol.templateArgs is None
|
||||
parentSymbol = symbol.parent
|
||||
@ -5434,7 +5479,7 @@ class CPPObject(ObjectDescription):
|
||||
if parentDecl is None:
|
||||
# the parent is not explicitly declared
|
||||
# TODO: we could warn, but it could be a style to just assume
|
||||
# enumerator parnets to be scoped
|
||||
# enumerator parents to be scoped
|
||||
return
|
||||
if parentDecl.objectType != 'enum':
|
||||
# TODO: maybe issue a warning, enumerators in non-enums is weird,
|
||||
@ -5444,13 +5489,13 @@ class CPPObject(ObjectDescription):
|
||||
return
|
||||
|
||||
targetSymbol = parentSymbol.parent
|
||||
s = targetSymbol.find_identifier(symbol.identifier, matchSelf=False)
|
||||
s = targetSymbol.find_identifier(symbol.identOrOp, matchSelf=False)
|
||||
if s is not None:
|
||||
# something is already declared with that name
|
||||
return
|
||||
declClone = symbol.declaration.clone()
|
||||
declClone.enumeratorScopedSymbol = symbol
|
||||
Symbol(parent=targetSymbol, identifier=symbol.identifier,
|
||||
Symbol(parent=targetSymbol, identOrOp=symbol.identOrOp,
|
||||
templateParams=None, templateArgs=None,
|
||||
declaration=declClone,
|
||||
docname=self.env.docname)
|
||||
|
@ -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.
|
||||
"""
|
||||
|
||||
@ -40,7 +40,6 @@ 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.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.environment.adapters.indexentries import IndexEntries
|
||||
@ -558,21 +557,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)
|
||||
@ -878,7 +866,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.
|
||||
"""
|
||||
|
||||
|
@ -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')
|
||||
@ -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)
|
||||
|
||||
|
@ -7,24 +7,22 @@
|
||||
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 mock, import_module
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.ext.autodoc.importer import mock, import_object, get_object_members
|
||||
from sphinx.ext.autodoc.importer import _MockImporter # to keep compatibility # NOQA
|
||||
from sphinx.ext.autodoc.inspector import format_annotation, formatargspec # to keep compatibility # NOQA
|
||||
from sphinx.util import rpartition, force_decode
|
||||
@ -32,21 +30,23 @@ 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."""
|
||||
@ -383,55 +357,15 @@ 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
|
||||
with mock(self.env.config.autodoc_mock_imports):
|
||||
try:
|
||||
logger.debug('[autodoc] import %s', self.modname)
|
||||
obj = import_module(self.modname, self.env.config.autodoc_warningiserror)
|
||||
parent = None
|
||||
self.module = obj
|
||||
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
|
||||
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 (AttributeError, ImportError) as exc:
|
||||
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(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.warning(errmsg)
|
||||
except ImportError as exc:
|
||||
logger.warning(exc.args[0])
|
||||
self.env.note_reread()
|
||||
return False
|
||||
|
||||
@ -604,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:
|
||||
logger.warning('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]]
|
||||
@ -713,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
|
||||
@ -767,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
|
||||
@ -896,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
|
||||
@ -938,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)
|
||||
@ -1502,117 +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
|
||||
logger.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.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 []
|
||||
|
||||
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 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)
|
||||
@ -1623,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,7 +5,7 @@
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
@ -13,13 +13,17 @@ 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, Generator, List, Set # NOQA
|
||||
from typing import Any, Callable, Dict, Generator, List, Optional, Set # NOQA
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -144,3 +148,86 @@ def import_module(modname, warningiserror=False):
|
||||
# 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,7 +5,7 @@
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
|
@ -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,8 @@ 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:
|
||||
@ -153,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.
|
||||
|
||||
@ -167,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
|
||||
@ -176,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
|
||||
|
||||
@ -186,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)
|
||||
@ -289,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))
|
||||
@ -325,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)
|
||||
@ -615,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__':
|
||||
|
@ -6,7 +6,7 @@
|
||||
Check Python modules and C API for coverage. Mostly written by Josip
|
||||
Dzolonga for the Google Highly Open Participation contest.
|
||||
|
||||
: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 @@
|
||||
Mimic doctest by automatically executing code snippets and checking
|
||||
their results.
|
||||
|
||||
: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
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
You can also give an explicit caption, e.g. :exmpl:`Foo <foo>`.
|
||||
|
||||
: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 @@
|
||||
|
||||
To publish HTML docs at GitHub Pages, create .nojekyll file.
|
||||
|
||||
: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 @@
|
||||
Allow graphviz-formatted graphs to be included in Sphinx-generated
|
||||
documents inline.
|
||||
|
||||
: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.
|
||||
"""
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
namespace of the project configuration (that is, all variables from
|
||||
``conf.py`` are available.)
|
||||
|
||||
: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 @@
|
||||
|
||||
Image converter extension for 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.
|
||||
"""
|
||||
import subprocess
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Render math in HTML via dvipng or dvisvgm.
|
||||
|
||||
: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.
|
||||
"""
|
||||
|
||||
@ -30,6 +30,7 @@ from sphinx.util.png import read_png_depth, write_png_depth
|
||||
from sphinx.util.osutil import ensuredir, ENOENT, cd
|
||||
from sphinx.util.pycompat import sys_encoding
|
||||
from sphinx.ext.mathbase import setup_math as mathbase_setup, wrap_displaymath
|
||||
from sphinx.ext.mathbase import get_node_equation_number
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
@ -333,7 +334,8 @@ def html_visit_displaymath(self, node):
|
||||
self.body.append(self.starttag(node, 'div', CLASS='math'))
|
||||
self.body.append('<p>')
|
||||
if node['number']:
|
||||
self.body.append('<span class="eqno">(%s)' % node['number'])
|
||||
number = get_node_equation_number(self, node)
|
||||
self.body.append('<span class="eqno">(%s)' % number)
|
||||
self.add_permalink_ref(node, _('Permalink to this equation'))
|
||||
self.body.append('</span>')
|
||||
if fname is None:
|
||||
|
@ -32,7 +32,7 @@ r"""
|
||||
The graph is inserted as a PNG+image map into HTML and a PDF in
|
||||
LaTeX.
|
||||
|
||||
: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.
|
||||
"""
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
also be specified individually, e.g. if the docs should be buildable
|
||||
without Internet access.
|
||||
|
||||
: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.
|
||||
"""
|
||||
|
||||
@ -304,6 +304,7 @@ def missing_reference(app, env, node, contnode):
|
||||
in_set = setname
|
||||
to_try.append((inventories.named_inventory[setname], newtarget))
|
||||
if domain:
|
||||
node['reftarget'] = newtarget
|
||||
full_qualified_name = env.get_domain(domain).get_full_qualified_name(node)
|
||||
if full_qualified_name:
|
||||
to_try.append((inventories.named_inventory[setname], full_qualified_name))
|
||||
|
@ -6,7 +6,7 @@
|
||||
Set up everything for use of JSMath to display math in HTML
|
||||
via JavaScript.
|
||||
|
||||
: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.
|
||||
"""
|
||||
|
||||
@ -16,6 +16,7 @@ import sphinx
|
||||
from sphinx.locale import _
|
||||
from sphinx.application import ExtensionError
|
||||
from sphinx.ext.mathbase import setup_math as mathbase_setup
|
||||
from sphinx.ext.mathbase import get_node_equation_number
|
||||
|
||||
|
||||
def html_visit_math(self, node):
|
||||
@ -35,7 +36,8 @@ def html_visit_displaymath(self, node):
|
||||
if i == 0:
|
||||
# necessary to e.g. set the id property correctly
|
||||
if node['number']:
|
||||
self.body.append('<span class="eqno">(%s)' % node['number'])
|
||||
number = get_node_equation_number(self, node)
|
||||
self.body.append('<span class="eqno">(%s)' % number)
|
||||
self.add_permalink_ref(node, _('Permalink to this equation'))
|
||||
self.body.append('</span>')
|
||||
self.body.append(self.starttag(node, 'div', CLASS='math'))
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
Add external links to module code in Python object descriptions.
|
||||
|
||||
: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.
|
||||
"""
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user