mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch 'master' into refactor_latex
This commit is contained in:
commit
6eb5b29484
@ -5,8 +5,6 @@ environment:
|
||||
PYTHONWARNINGS: all
|
||||
|
||||
matrix:
|
||||
- PYTHON: 27
|
||||
TEST_IGNORE: --ignore py35
|
||||
- PYTHON: 37
|
||||
- PYTHON: 37-x64
|
||||
|
||||
|
@ -6,6 +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
|
||||
- run: /python3.5/bin/pip install -U pip setuptools
|
||||
- run: /python3.5/bin/pip install -U .[test,websupport]
|
||||
- run: make test PYTHON=/python3.5/bin/python
|
||||
|
@ -11,16 +11,9 @@ env:
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- python: 'pypy'
|
||||
env: TOXENV=pypy
|
||||
- python: '2.7'
|
||||
- python: '3.5'
|
||||
env:
|
||||
- TOXENV=du13
|
||||
- PYTEST_ADDOPTS="--cov ./ --cov-append --cov-config setup.cfg"
|
||||
- python: '3.4'
|
||||
env: TOXENV=py34
|
||||
- python: '3.5'
|
||||
env: TOXENV=py35
|
||||
- python: '3.6'
|
||||
env:
|
||||
- TOXENV=py36
|
||||
|
1
AUTHORS
1
AUTHORS
@ -38,6 +38,7 @@ Other contributors, listed alphabetically, are:
|
||||
* Zac Hatfield-Dodds -- doctest reporting improvements
|
||||
* Doug Hellmann -- graphviz improvements
|
||||
* Tim Hoffmann -- theme improvements
|
||||
* Antti Kaihola -- doctest extension (skipif option)
|
||||
* Dave Kuhlman -- original LaTeX writer
|
||||
* Blaise Laflamme -- pyramid theme
|
||||
* Chris Lamb -- reproducibility fixes
|
||||
|
252
CHANGES
252
CHANGES
@ -1,17 +1,128 @@
|
||||
Release 1.8.0 (in development)
|
||||
Release 2.0.0 (in development)
|
||||
==============================
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
* LaTeX builder now depends on TeX Live 2015 or above
|
||||
|
||||
Incompatible changes
|
||||
--------------------
|
||||
|
||||
* Drop python 2.7 and 3.4 support
|
||||
* Drop docutils 0.11 support
|
||||
* The default setting for :confval:`master_doc` is changed to ``'index'`` which
|
||||
has been longly used as default of sphinx-quickstart.
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
* The ``suffix`` argument of ``env.doc2path()`` is deprecated.
|
||||
* The string style ``base`` argument of ``env.doc2path()`` is deprecated.
|
||||
* ``sphinx.ext.doctest.doctest_encode()``
|
||||
* ``sphinx.testing.util.remove_unicode_literal()``
|
||||
* ``sphinx.util.osutil.walk()``
|
||||
|
||||
For more details, see `deprecation APIs list
|
||||
<http://www.sphinx-doc.org/en/master/extdev/index.html#deprecated-apis>`_
|
||||
|
||||
Features added
|
||||
--------------
|
||||
* #1618: The search results preview of generated HTML documentation is
|
||||
reader-friendlier: instead of showing the snippets as raw reStructuredText
|
||||
markup, Sphinx now renders the corresponding HTML. This means the Sphinx
|
||||
extension `Sphinx: pretty search results`__ is no longer necessary. Note that
|
||||
changes to the search function of your custom or 3rd-pary HTML template might
|
||||
overwrite this improvement.
|
||||
|
||||
__ https://github.com/sphinx-contrib/sphinx-pretty-searchresults
|
||||
|
||||
* #4182: autodoc: Support :confval:`suppress_warnings`
|
||||
* #4018: htmlhelp: Add :confval:`htmlhelp_file_suffix` and
|
||||
:confval:`htmlhelp_link_suffix`
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
Release 1.8.2 (in development)
|
||||
==============================
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Incompatible changes
|
||||
--------------------
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
Features added
|
||||
--------------
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
Release 1.8.1 (released Sep 22, 2018)
|
||||
=====================================
|
||||
|
||||
Incompatible changes
|
||||
--------------------
|
||||
|
||||
* LaTeX ``\pagestyle`` commands have been moved to the LaTeX template. No
|
||||
changes in PDF, except possibly if ``\sphinxtableofcontents``, which
|
||||
contained them, had been customized in :file:`conf.py`. (refs: #5455)
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* #5418: Incorrect default path for sphinx-build -d/doctrees files
|
||||
* #5421: autodoc emits deprecation warning for :confval:`autodoc_default_flags`
|
||||
* #5422: lambda object causes PicklingError on storing environment
|
||||
* #5417: Sphinx fails to build with syntax error in Python 2.7.5
|
||||
* #4911: add latexpdf to make.bat for non make-mode
|
||||
* #5436: Autodoc does not work with enum subclasses with properties/methods
|
||||
* #5437: autodoc: crashed on modules importing eggs
|
||||
* #5433: latex: ImportError: cannot import name 'DEFAULT_SETTINGS'
|
||||
* #5431: autodoc: ``autofunction`` emits a warning for callable objects
|
||||
* #5457: Fix TypeError in error message when override is prohibited
|
||||
* #5453: PDF builds of 'howto' documents have no page numbers
|
||||
* #5463: mathbase: math_role and MathDirective was disappeared in 1.8.0
|
||||
* #5454: latex: Index has disappeared from PDF for Japanese documents
|
||||
* #5432: py domain: ``:type:`` field can't process ``:term:`` references
|
||||
* #5426: py domain: TypeError has been raised for class attribute
|
||||
|
||||
Release 1.8.0 (released Sep 13, 2018)
|
||||
=====================================
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
1.8.0b1
|
||||
|
||||
* LaTeX: :confval:`latex_use_xindy`, if ``True`` (default for
|
||||
``xelatex/lualatex``), instructs ``make latexpdf`` to use :program:`xindy`
|
||||
for general index. Make sure your LaTeX distribution includes it.
|
||||
(refs: #5134)
|
||||
* LaTeX: ``latexmk`` is required for ``make latexpdf`` on Windows
|
||||
|
||||
Incompatible changes
|
||||
--------------------
|
||||
|
||||
1.8.0b2
|
||||
|
||||
* #5282: html theme: refer ``pygments_style`` settings of HTML themes
|
||||
preferentially
|
||||
* The URL of download files are changed
|
||||
* #5127: quickstart: ``Makefile`` and ``make.bat`` are not overwritten if exists
|
||||
|
||||
1.8.0b1
|
||||
|
||||
* #5156: the :py:mod:`sphinx.ext.graphviz: extension runs `dot` in the
|
||||
directory of the document being built instead of in the root directory of
|
||||
the documentation.
|
||||
@ -53,11 +164,30 @@ Incompatible changes
|
||||
before new build.
|
||||
* #5163: html: hlist items are now aligned to top
|
||||
* ``highlightlang`` directive is processed on resolving phase
|
||||
* #4000: latex: LaTeX template has been chaned. Following elements are moved
|
||||
into the template:
|
||||
|
||||
- ``\begin{document}``
|
||||
- ``shorthandoff`` variable
|
||||
- ``maketitle`` variable
|
||||
- ``tableofcontents`` variable
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
1.8.0b2
|
||||
|
||||
* ``sphinx.io.SphinxI18nReader.set_lineno_for_reporter()`` is deprecated
|
||||
* ``sphinx.io.SphinxI18nReader.line`` is deprecated
|
||||
* ``sphinx.util.i18n.find_catalog_source_file()`` has changed; the
|
||||
*gettext_compact* argument has been deprecated
|
||||
* #5403: ``sphinx.util.images.guess_mimetype()`` has changed; the *content*
|
||||
argument has been deprecated
|
||||
|
||||
1.8.0b1
|
||||
|
||||
* :confval:`source_parsers` is deprecated
|
||||
* :confval:`autodoc_default_flags` is deprecated
|
||||
* quickstart: ``--epub`` option becomes default, so it is deprecated
|
||||
* Drop function based directive support. For now, Sphinx only supports class
|
||||
based directives.
|
||||
@ -121,6 +251,8 @@ Deprecated
|
||||
* ``sphinx.ext.mathbase.eqref`` node is deprecated
|
||||
* ``sphinx.ext.mathbase.is_in_section_title()`` is deprecated
|
||||
* ``sphinx.ext.mathbase.MathDomain`` is deprecated
|
||||
* ``sphinx.ext.mathbase.MathDirective`` is deprecated
|
||||
* ``sphinx.ext.mathbase.math_role`` is deprecated
|
||||
* ``sphinx.ext.mathbase.setup_math()`` is deprecated
|
||||
* ``sphinx.directives.other.VersionChanges`` is deprecated
|
||||
* ``sphinx.highlighting.PygmentsBridge.unhighlight()`` is deprecated
|
||||
@ -135,6 +267,13 @@ For more details, see `deprecation APIs list
|
||||
Features added
|
||||
--------------
|
||||
|
||||
1.8.0b2
|
||||
|
||||
* #5388: Ensure frozen object descriptions are reproducible
|
||||
* #5362: apidoc: Add ``--tocfile`` option to change the filename of ToC
|
||||
|
||||
1.8.0b1
|
||||
|
||||
* Add :event:`config-inited` event
|
||||
* Add ``sphinx.config.Any`` to represent the config value accepts any type of
|
||||
value
|
||||
@ -163,17 +302,22 @@ Features added
|
||||
* Add ``Config.read()`` classmethod to create a new config object from
|
||||
configuration file
|
||||
* #4866: Wrap graphviz diagrams in ``<div>`` tag
|
||||
* Add :event:`viewcode-find-source` event to viewcode extension.
|
||||
* viewcode: Add :event:`viewcode-find-source` and
|
||||
:event:`viewcode-follow-imported` to load source code without loading
|
||||
* #4785: napoleon: Add strings to translation file for localisation
|
||||
* #4927: Display a warning when invalid values are passed to linenothreshold
|
||||
option of highlight directive
|
||||
* C++, add a ``cpp:texpr`` role as a sibling to ``cpp:expr``.
|
||||
* C++, add support for unions.
|
||||
* C++, add support for anonymous entities using names staring with ``@``.
|
||||
Fixes #3593 and #2683.
|
||||
* #5147: C++, add support for (most) character literals.
|
||||
* C++, cross-referencing entities inside primary templates is supported,
|
||||
and now properly documented.
|
||||
* C++:
|
||||
|
||||
- Add a ``cpp:texpr`` role as a sibling to ``cpp:expr``.
|
||||
- Add support for unions.
|
||||
- #3593, #2683: add support for anonymous entities using names staring with ``@``.
|
||||
- #5147: add support for (most) character literals.
|
||||
- Cross-referencing entities inside primary templates is supported,
|
||||
and now properly documented.
|
||||
- #1552: add new cross-referencing format for ``cpp:any`` and ``cpp:func`` roles,
|
||||
for referencing specific function overloads.
|
||||
|
||||
* #3606: MathJax should be loaded with async attribute
|
||||
* html: Output ``canonical_url`` metadata if :confval:`html_baseurl` set (refs:
|
||||
#4193)
|
||||
@ -194,10 +338,36 @@ Features added
|
||||
* #4614: sphinx-build: Add ``--keep-going`` option to show all warnings
|
||||
* Add :rst:role:`math:numref` role to refer equations (Same as :rst:role:`eq`)
|
||||
* quickstart: epub builder is enabled by default
|
||||
* #5246: Add :confval:`singlehtml_sidebars` to configure sidebars for singlehtml
|
||||
builder
|
||||
* #5273: doctest: Skip doctest conditionally
|
||||
* #5306: autodoc: emit a warning for invalid typehints
|
||||
* #4075, #5215: autodoc: Add :confval:`autodoc_default_options` which accepts
|
||||
option values as dict
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
1.8.0b2
|
||||
|
||||
* html: search box overrides to other elements if scrolled
|
||||
* i18n: warnings for translation catalogs have wrong line numbers (refs: #5321)
|
||||
* #5325: latex: cross references has been broken by multiply labeled objects
|
||||
* C++, fixes for symbol addition and lookup. Lookup should no longer break
|
||||
in partial builds. See also #5337.
|
||||
* #5348: download reference to remote file is not displayed
|
||||
* #5282: html theme: ``pygments_style`` of theme was overrided by ``conf.py``
|
||||
by default
|
||||
* #4379: toctree shows confusible warning when document is excluded
|
||||
* #2401: autodoc: ``:members:`` causes ``:special-members:`` not to be shown
|
||||
* autodoc: ImportError is replaced by AttributeError for deeper module
|
||||
* #2720, #4034: Incorrect links with ``:download:``, duplicate names, and
|
||||
parallel builds
|
||||
* #5290: autodoc: failed to analyze source code in egg package
|
||||
* #5399: Sphinx crashes if unknown po file exists
|
||||
|
||||
1.8.0b1
|
||||
|
||||
* i18n: message catalogs were reset on each initialization
|
||||
* #4850: latex: footnote inside footnote was not rendered
|
||||
* #4945: i18n: fix lang_COUNTRY not fallback correctly for IndexBuilder. Thanks
|
||||
@ -211,24 +381,26 @@ Bugs fixed
|
||||
* #5191: C++, prevent nested declarations in functions to avoid lookup problems.
|
||||
* #5126: C++, add missing isPack method for certain template parameter types.
|
||||
* #5187: C++, parse attributes on declerators as well.
|
||||
* C++, parse delete expressions and basic new expressions as well.
|
||||
* #5002: graphviz: SVGs do not adapt to the column width
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
Features removed
|
||||
----------------
|
||||
|
||||
1.8.0b1
|
||||
|
||||
* ``sphinx.ext.pngmath`` extension
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
1.8.0b1
|
||||
|
||||
* #5083: Fix wrong make.bat option for internationalization.
|
||||
* #5115: napoleon: add admonitions added by #4613 to the docs.
|
||||
|
||||
Release 1.7.7 (in development)
|
||||
==============================
|
||||
Release 1.7.10 (in development)
|
||||
===============================
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
@ -245,6 +417,46 @@ Features added
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
Release 1.7.9 (released Sep 05, 2018)
|
||||
=====================================
|
||||
|
||||
Features added
|
||||
--------------
|
||||
|
||||
* #5359: Make generated texinfo files reproducible by sorting the anchors
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* #5361: crashed on incremental build if document uses include directive
|
||||
|
||||
Release 1.7.8 (released Aug 29, 2018)
|
||||
=====================================
|
||||
|
||||
Incompatible changes
|
||||
--------------------
|
||||
|
||||
* The type of ``env.included`` has been changed to dict of set
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* #5320: intersphinx: crashed if invalid url given
|
||||
* #5326: manpage: crashed when invalid docname is specified as ``man_pages``
|
||||
* #5322: autodoc: ``Any`` typehint causes formatting error
|
||||
* #5327: "document isn't included in any toctree" warning on rebuild with
|
||||
generated files
|
||||
* #5335: quickstart: escape sequence has been displayed with MacPorts' python
|
||||
|
||||
Release 1.7.7 (released Aug 19, 2018)
|
||||
=====================================
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* #5198: document not in toctree warning when including files only for parallel
|
||||
builds
|
||||
* LaTeX: reduce "Token not allowed in a PDF string" hyperref warnings in latex
|
||||
@ -255,9 +467,13 @@ Bugs fixed
|
||||
1.5
|
||||
* LaTeX: fix the :confval:`latex_engine` documentation regarding Latin Modern
|
||||
font with XeLaTeX/LuaLateX (refs: #5251)
|
||||
|
||||
Testing
|
||||
--------
|
||||
* #5280: autodoc: Fix wrong type annotations for complex typing
|
||||
* autodoc: Optional types are wrongly rendered
|
||||
* #5291: autodoc crashed by ForwardRef types
|
||||
* #5211: autodoc: No docs generated for functools.partial functions
|
||||
* #5306: autodoc: ``getargspec()`` raises NameError for invalid typehints
|
||||
* #5298: imgmath: math_number_all causes equations to have two numbers in html
|
||||
* #5294: sphinx-quickstart blank prompts in PowerShell
|
||||
|
||||
Release 1.7.6 (released Jul 17, 2018)
|
||||
=====================================
|
||||
@ -1925,7 +2141,7 @@ Incompatible changes
|
||||
parsing is attempted to distinguish valid code. To get the old behavior back,
|
||||
add ``highlight_language = "python"`` to conf.py.
|
||||
* `Locale Date Markup Language
|
||||
<http://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns>`_ like
|
||||
<https://unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns>`_ like
|
||||
``"MMMM dd, YYYY"`` is default format for `today_fmt` and `html_last_updated_fmt`.
|
||||
However strftime format like ``"%B %d, %Y"`` is also supported for backward
|
||||
compatibility until Sphinx-1.5. Later format will be disabled from Sphinx-1.5.
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
.. image:: https://img.shields.io/pypi/v/sphinx.svg
|
||||
:target: https://pypi.org/project/Sphinx/
|
||||
:alt: Package on PyPi
|
||||
:alt: Package on PyPI
|
||||
|
||||
.. image:: https://readthedocs.org/projects/sphinx/badge/?version=master
|
||||
:target: http://www.sphinx-doc.org/
|
||||
|
@ -144,3 +144,10 @@ def setup(app):
|
||||
names=['param'], can_collapse=True)
|
||||
app.add_object_type('event', 'event', 'pair: %s; event', parse_event,
|
||||
doc_field_types=[fdesc])
|
||||
|
||||
# workaround for RTD
|
||||
from sphinx.util import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
app.info = lambda *args, **kwargs: logger.info(*args, **kwargs)
|
||||
app.warn = lambda *args, **kwargs: logger.warning(*args, **kwargs)
|
||||
app.debug = lambda *args, **kwargs: logger.debug(*args, **kwargs)
|
||||
|
@ -127,7 +127,7 @@ own extensions.
|
||||
.. _NumPy style: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
|
||||
.. _hyphenator: https://github.com/mnater/hyphenator
|
||||
.. _exceltable: https://pythonhosted.org/sphinxcontrib-exceltable/
|
||||
.. _YouTube: http://www.youtube.com/
|
||||
.. _YouTube: https://www.youtube.com/
|
||||
.. _ClearQuest: https://www.ibm.com/us-en/marketplace/rational-clearquest
|
||||
.. _Zope interfaces: https://zopeinterface.readthedocs.io/en/latest/README.html
|
||||
.. _slideshare: https://www.slideshare.net/
|
||||
|
@ -115,32 +115,6 @@ Emitting events
|
||||
.. automethod:: emit_firstresult(event, \*arguments)
|
||||
|
||||
|
||||
Producing messages / logging
|
||||
----------------------------
|
||||
|
||||
The application object also provides support for emitting leveled messages.
|
||||
|
||||
.. note::
|
||||
|
||||
There is no "error" call: in Sphinx, errors are defined as things that stop
|
||||
the build; just raise an exception (:exc:`sphinx.errors.SphinxError` or a
|
||||
custom subclass) to do that.
|
||||
|
||||
.. deprecated:: 1.6
|
||||
|
||||
Please use :ref:`logging-api` instead.
|
||||
|
||||
.. automethod:: Sphinx.warn
|
||||
|
||||
.. automethod:: Sphinx.info
|
||||
|
||||
.. automethod:: Sphinx.verbose
|
||||
|
||||
.. automethod:: Sphinx.debug
|
||||
|
||||
.. automethod:: Sphinx.debug2
|
||||
|
||||
|
||||
Sphinx runtime information
|
||||
--------------------------
|
||||
|
||||
|
@ -39,10 +39,6 @@ Build environment API
|
||||
|
||||
**Utility methods**
|
||||
|
||||
.. automethod:: warn
|
||||
|
||||
.. automethod:: warn_node
|
||||
|
||||
.. automethod:: doc2path
|
||||
|
||||
.. automethod:: relfn2path
|
||||
|
@ -116,6 +116,31 @@ The following is a list of deprecated interface.
|
||||
- (will be) Removed
|
||||
- Alternatives
|
||||
|
||||
* - ``suffix`` argument of ``BuildEnvironment.doc2path()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - string style ``base`` argument of ``BuildEnvironment.doc2path()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``os.path.join()``
|
||||
|
||||
* - ``sphinx.ext.doctest.doctest_encode()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.testing.util.remove_unicode_literal()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.util.osutil.walk()``
|
||||
- 2.0
|
||||
- 4.0
|
||||
- ``os.walk()``
|
||||
|
||||
* - :rst:dir:`highlightlang`
|
||||
- 1.8
|
||||
- 4.0
|
||||
@ -131,6 +156,32 @@ The following is a list of deprecated interface.
|
||||
- 4.0
|
||||
- :meth:`~sphinx.application.Sphinx.add_js_file()`
|
||||
|
||||
* - :confval:`autodoc_default_flags`
|
||||
- 1.8
|
||||
- 4.0
|
||||
- :confval:`autodoc_default_options`
|
||||
|
||||
* - ``content`` arguments of ``sphinx.util.image.guess_mimetype()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``gettext_compact`` arguments of
|
||||
``sphinx.util.i18n.find_catalog_source_files()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.io.SphinxI18nReader.set_lineno_for_reporter()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.io.SphinxI18nReader.line``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- N/A
|
||||
|
||||
* - ``sphinx.directives.other.VersionChanges``
|
||||
- 1.8
|
||||
- 3.0
|
||||
@ -157,6 +208,16 @@ The following is a list of deprecated interface.
|
||||
- 3.0
|
||||
- ``sphinx.domains.math.MathDomain``
|
||||
|
||||
* - ``sphinx.ext.mathbase.MathDirective``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``sphinx.directives.patches.MathDirective``
|
||||
|
||||
* - ``sphinx.ext.mathbase.math_role()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
- ``docutils.parsers.rst.roles.math_role()``
|
||||
|
||||
* - ``sphinx.ext.mathbase.setup_math()``
|
||||
- 1.8
|
||||
- 3.0
|
||||
|
@ -9,9 +9,9 @@ Logging API
|
||||
|
||||
.. autoclass:: SphinxLoggerAdapter(logging.LoggerAdapter)
|
||||
|
||||
.. method:: SphinxLoggerAdapter.error(level, msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.critical(level, msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.warning(level, msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.error(msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.critical(msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.warning(msg, *args, **kwargs)
|
||||
|
||||
Logs a message on this logger with the specified level.
|
||||
Basically, the arguments are as with python's logging module.
|
||||
@ -33,13 +33,14 @@ Logging API
|
||||
logger.warning('Warning happened!', location=some_node)
|
||||
|
||||
**color**
|
||||
The color of logs. By default, warning level logs are
|
||||
colored as ``"darkred"``. The others are not colored.
|
||||
The color of logs. By default, error level logs are colored as
|
||||
``"darkred"``, critical level ones is not colored, and warning level
|
||||
ones are colored as ``"red"``.
|
||||
|
||||
.. method:: SphinxLoggerAdapter.log(level, msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.info(level, msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.verbose(level, msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.debug(level, msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.info(msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.verbose(msg, *args, **kwargs)
|
||||
.. method:: SphinxLoggerAdapter.debug(msg, *args, **kwargs)
|
||||
|
||||
Logs a message to this logger with the specified level.
|
||||
Basically, the arguments are as with python's logging module.
|
||||
@ -55,9 +56,8 @@ Logging API
|
||||
:meth:`SphinxLoggerAdapter.warning`.
|
||||
|
||||
**color**
|
||||
The color of logs. By default, debug level logs are
|
||||
colored as ``"darkgray"``, and debug2 level ones are ``"lightgray"``.
|
||||
The others are not colored.
|
||||
The color of logs. By default, info and verbose level logs are not colored,
|
||||
and deug level ones are colored as ``"darkgray"``.
|
||||
|
||||
.. autofunction:: pending_logging()
|
||||
|
||||
|
@ -205,7 +205,7 @@ The following list gives some hints for the creation of epub files:
|
||||
.. _Epubcheck: https://github.com/IDPF/epubcheck
|
||||
.. _Calibre: https://calibre-ebook.com/
|
||||
.. _FBreader: https://fbreader.org/
|
||||
.. _Bookworm: http://www.oreilly.com/bookworm/index.html
|
||||
.. _Bookworm: https://www.oreilly.com/bookworm/index.html
|
||||
.. _kindlegen: https://www.amazon.com/gp/feature.html?docId=1000765211
|
||||
|
||||
.. _texinfo-faq:
|
||||
|
@ -326,4 +326,4 @@ There is `sphinx translation page`_ for Sphinx (master) documentation.
|
||||
.. _`sphinx-intl`: https://pypi.org/project/sphinx-intl/
|
||||
.. _Transifex: https://www.transifex.com/
|
||||
.. _`sphinx translation page`: https://www.transifex.com/sphinx-doc/sphinx-doc/
|
||||
.. _`Transifex Client documentation`: http://docs.transifex.com/developer/client/
|
||||
.. _`Transifex Client documentation`: https://docs.transifex.com/client/introduction/
|
||||
|
@ -55,15 +55,13 @@ See the :ref:`pertinent section in the FAQ list <usingwith>`.
|
||||
Prerequisites
|
||||
-------------
|
||||
|
||||
Sphinx needs at least **Python 2.7** or **Python 3.4** to run, as well as the
|
||||
docutils_ and Jinja2_ libraries. Sphinx should work with docutils version 0.10
|
||||
or some (not broken) SVN trunk snapshot. If you like to have source code
|
||||
highlighting support, you must also install the Pygments_ library.
|
||||
Sphinx needs at least **Python 3.5** to run, as well as the docutils_ and
|
||||
Jinja2_ libraries. Sphinx should work with docutils version 0.12 or some (not
|
||||
broken) SVN trunk snapshot.
|
||||
|
||||
.. _reStructuredText: http://docutils.sourceforge.net/rst.html
|
||||
.. _docutils: http://docutils.sourceforge.net/
|
||||
.. _Jinja2: http://jinja.pocoo.org/
|
||||
.. _Pygments: http://pygments.org/
|
||||
|
||||
|
||||
Usage
|
||||
|
@ -58,6 +58,10 @@ Options
|
||||
|
||||
Maximum depth for the generated table of contents file.
|
||||
|
||||
.. option:: --tocfile
|
||||
|
||||
Filename for a table of contents file. Defaults to ``modules``.
|
||||
|
||||
.. option:: -T, --no-toc
|
||||
|
||||
Do not create a table of contents file. Ignored when :option:`--full` is
|
||||
|
@ -165,16 +165,17 @@ The builder's "name" must be given to the **-b** command-line option of
|
||||
* ``texlive-fonts-recommended``
|
||||
* ``texlive-latex-extra``
|
||||
* ``latexmk`` (for ``make latexpdf`` on GNU/Linux and MacOS X)
|
||||
* ``latex-xcolor`` (old Ubuntu)
|
||||
* ``texlive-luatex``, ``texlive-xetex`` (see :confval:`latex_engine`)
|
||||
|
||||
The testing of Sphinx LaTeX is done on Ubuntu trusty with the above
|
||||
mentioned packages, which are from a TeXLive 2013 snapshot dated
|
||||
February 2014.
|
||||
The testing of Sphinx LaTeX is done on Ubuntu xenial with the above mentioned
|
||||
packages, which are from a TeXLive 2015 snapshot dated March 2016.
|
||||
|
||||
.. versionchanged:: 1.6
|
||||
Formerly, testing had been done on Ubuntu precise (TeXLive 2009).
|
||||
|
||||
.. versionchanged:: 2.0
|
||||
Formerly, testing had been done on Ubuntu trusty (TeXLive 2013).
|
||||
|
||||
.. note::
|
||||
|
||||
Since 1.6, ``make latexpdf`` uses ``latexmk`` (not on Windows). This
|
||||
@ -215,7 +216,7 @@ Note that a direct PDF builder is being provided by `rinohtype`_. The builder's
|
||||
name is ``rinoh``. Refer to the `rinohtype manual`_ for details.
|
||||
|
||||
.. _rinohtype: https://github.com/brechtm/rinohtype
|
||||
.. _rinohtype manual: http://www.mos6581.org/rinohtype/quickstart.html#sphinx-builder
|
||||
.. _rinohtype manual: https://www.mos6581.org/rinohtype/quickstart.html#sphinx-builder
|
||||
|
||||
.. module:: sphinx.builders.text
|
||||
.. class:: TextBuilder
|
||||
|
@ -149,7 +149,10 @@ General configuration
|
||||
.. confval:: master_doc
|
||||
|
||||
The document name of the "master" document, that is, the document that
|
||||
contains the root :rst:dir:`toctree` directive. Default is ``'contents'``.
|
||||
contains the root :rst:dir:`toctree` directive. Default is ``'index'``.
|
||||
|
||||
.. versionchanged:: 2.0
|
||||
The defualt is changed to ``'index'`` from ``'contents'``.
|
||||
|
||||
.. confval:: exclude_patterns
|
||||
|
||||
@ -1108,12 +1111,6 @@ that use Sphinx's HTMLWriter class.
|
||||
If true, the reST sources are included in the HTML build as
|
||||
:file:`_sources/{name}`. The default is ``True``.
|
||||
|
||||
.. warning::
|
||||
|
||||
If this config value is set to ``False``, the JavaScript search function
|
||||
will only display the titles of matching documents, and no excerpt from
|
||||
the matching contents.
|
||||
|
||||
.. confval:: html_show_sourcelink
|
||||
|
||||
If true (and :confval:`html_copy_source` is true as well), links to the
|
||||
@ -1251,7 +1248,7 @@ that use Sphinx's HTMLWriter class.
|
||||
|
||||
:'sphinx.search.ja.DefaultSplitter':
|
||||
TinySegmenter algorithm. This is default splitter.
|
||||
:'sphinx.search.ja.MeCabSplitter':
|
||||
:'sphinx.search.ja.MecabSplitter':
|
||||
MeCab binding. To use this splitter, 'mecab' python binding or dynamic
|
||||
link library ('libmecab.so' for linux, 'libmecab.dll' for windows) is
|
||||
required.
|
||||
@ -1333,6 +1330,16 @@ that use Sphinx's HTMLWriter class.
|
||||
|
||||
.. versionadded:: 1.6
|
||||
|
||||
Options for Single HTML output
|
||||
-------------------------------
|
||||
|
||||
.. confval:: singlehtml_sidebars
|
||||
|
||||
Custom sidebar templates, must be a dictionary that maps document names to
|
||||
template names. And it only allows a key named `'index'`. All other keys
|
||||
are ignored. For more information, refer to :confval:`html_sidebars`. By
|
||||
default, it is same as :confval:`html_sidebars`.
|
||||
|
||||
|
||||
.. _htmlhelp-options:
|
||||
|
||||
@ -1343,6 +1350,19 @@ Options for HTML help output
|
||||
|
||||
Output file base name for HTML help builder. Default is ``'pydoc'``.
|
||||
|
||||
.. confval:: htmlhelp_file_suffix
|
||||
|
||||
This is the file name suffix for generated HTML help files. The
|
||||
default is ``".html"``.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
.. confval:: htmlhelp_link_suffix
|
||||
|
||||
Suffix for generated links to HTML files. The default is ``".html"``.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
|
||||
.. _applehelp-options:
|
||||
|
||||
|
@ -45,6 +45,10 @@ docstrings to correct reStructuredText before :mod:`autodoc` processes them.
|
||||
.. _NumPy:
|
||||
https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
|
||||
|
||||
|
||||
Directives
|
||||
----------
|
||||
|
||||
:mod:`autodoc` provides several directives that are versions of the usual
|
||||
:rst:dir:`py:module`, :rst:dir:`py:class` and so forth. On parsing time, they
|
||||
import the corresponding module and extract the docstring of the given objects,
|
||||
@ -114,8 +118,17 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
|
||||
.. autoclass:: Noodle
|
||||
:members: eat, slurp
|
||||
|
||||
* If you want to make the ``members`` option (or other flag options described
|
||||
below) the default, see :confval:`autodoc_default_flags`.
|
||||
* If you want to make the ``members`` option (or other options described
|
||||
below) the default, see :confval:`autodoc_default_options`.
|
||||
|
||||
.. tip::
|
||||
|
||||
You can use a negated form, :samp:`'no-{flag}'`, as an option of
|
||||
autodoc directive, to disable it temporarily. For example::
|
||||
|
||||
.. automodule:: foo
|
||||
:no-undoc-members:
|
||||
|
||||
|
||||
* Members without docstrings will be left out, unless you give the
|
||||
``undoc-members`` flag option::
|
||||
@ -297,6 +310,9 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
|
||||
well-behaved decorating functions.
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
There are also new config values that you can set:
|
||||
|
||||
.. confval:: autoclass_content
|
||||
@ -341,20 +357,38 @@ 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'``, ``'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.
|
||||
For example, if ``autodoc_default_flags`` is set to ``['members',
|
||||
'undoc-members']``, and you write a directive like this::
|
||||
|
||||
.. automodule:: foo
|
||||
:no-undoc-members:
|
||||
|
||||
the directive will be interpreted as if only ``:members:`` was given.
|
||||
``'inherited-members'``, ``'show-inheritance'``, ``'ignore-module-all'``
|
||||
and ``'exclude-members'``.
|
||||
|
||||
.. versionadded:: 1.0
|
||||
|
||||
.. deprecated:: 1.8
|
||||
|
||||
Integrated into :confval:`autodoc_default_options`.
|
||||
|
||||
.. confval:: autodoc_default_options
|
||||
|
||||
The default options for autodoc directives. They are applied to all autodoc
|
||||
directives automatically. It must be a dictionary which maps option names
|
||||
to the values. For example::
|
||||
|
||||
autodoc_default_options = {
|
||||
'members': 'var1, var2',
|
||||
'member-order': 'bysource',
|
||||
'special-members': '__init__',
|
||||
'undoc-members': None,
|
||||
'exclude-members': '__weakref__'
|
||||
}
|
||||
|
||||
Setting ``None`` is equivalent to giving the option name in the list format
|
||||
(i.e. it means "yes/true/on").
|
||||
|
||||
The supported options are ``'members'``, ``'undoc-members'``,
|
||||
``'private-members'``, ``'special-members'``, ``'inherited-members'``,
|
||||
``'show-inheritance'``, ``'ignore-module-all'`` and ``'exclude-members'``.
|
||||
|
||||
.. versionadded:: 1.8
|
||||
|
||||
.. confval:: autodoc_docstring_signature
|
||||
|
||||
Functions imported from C modules cannot be introspected, and therefore the
|
||||
@ -405,6 +439,16 @@ There are also new config values that you can set:
|
||||
|
||||
.. versionadded:: 1.7
|
||||
|
||||
.. confval:: suppress_warnings
|
||||
:noindex:
|
||||
|
||||
:mod:`autodoc` supports to suppress warning messages via
|
||||
:confval:`suppress_warnings`. It allows following warnings types in
|
||||
addition:
|
||||
|
||||
* autodoc
|
||||
* autodoc.import_object
|
||||
|
||||
|
||||
Docstring preprocessing
|
||||
-----------------------
|
||||
|
@ -208,6 +208,8 @@ The following variables available in the templates:
|
||||
List containing names of all inherited members of class. Only available for
|
||||
classes.
|
||||
|
||||
.. versionadded:: 1.8.0
|
||||
|
||||
.. data:: functions
|
||||
|
||||
List containing names of "public" functions in the module. Here, "public"
|
||||
|
@ -198,6 +198,81 @@ The following is an example for the usage of the directives. The test via
|
||||
This parrot wouldn't voom if you put 3000 volts through it!
|
||||
|
||||
|
||||
Skipping tests conditionally
|
||||
----------------------------
|
||||
|
||||
``skipif``, a string option, can be used to skip directives conditionally. This
|
||||
may be useful e.g. when a different set of tests should be run depending on the
|
||||
environment (hardware, network/VPN, optional dependencies or different versions
|
||||
of dependencies). The ``skipif`` option is supported by all of the doctest
|
||||
directives. Below are typical use cases for ``skipif`` when used for different
|
||||
directives:
|
||||
|
||||
- :rst:dir:`testsetup` and :rst:dir:`testcleanup`
|
||||
|
||||
- conditionally skip test setup and/or cleanup
|
||||
- customize setup/cleanup code per environment
|
||||
|
||||
- :rst:dir:`doctest`
|
||||
|
||||
- conditionally skip both a test and its output verification
|
||||
|
||||
- :rst:dir:`testcode`
|
||||
|
||||
- conditionally skip a test
|
||||
- customize test code per environment
|
||||
|
||||
- :rst:dir:`testoutput`
|
||||
|
||||
- conditionally skip output assertion for a skipped test
|
||||
- expect different output depending on the environment
|
||||
|
||||
The value of the ``skipif`` option is evaluated as a Python expression. If the
|
||||
result is a true value, the directive is omitted from the test run just as if
|
||||
it wasn't present in the file at all.
|
||||
|
||||
Instead of repeating an expression, the :confval:`doctest_global_setup`
|
||||
configuration option can be used to assign it to a variable which can then be
|
||||
used instead.
|
||||
|
||||
Here's an example which skips some tests if Pandas is not installed:
|
||||
|
||||
.. code-block:: py
|
||||
:caption: conf.py
|
||||
|
||||
extensions = ['sphinx.ext.doctest']
|
||||
doctest_global_setup = '''
|
||||
try:
|
||||
import pandas as pd
|
||||
except ImportError:
|
||||
pd = None
|
||||
'''
|
||||
|
||||
.. code-block:: rst
|
||||
:caption: contents.rst
|
||||
|
||||
.. testsetup::
|
||||
:skipif: pd is None
|
||||
|
||||
data = pd.Series([42])
|
||||
|
||||
.. doctest::
|
||||
:skipif: pd is None
|
||||
|
||||
>>> data.iloc[0]
|
||||
42
|
||||
|
||||
.. testcode::
|
||||
:skipif: pd is None
|
||||
|
||||
print(data.iloc[-1])
|
||||
|
||||
.. testoutput::
|
||||
:skipif: pd is None
|
||||
|
||||
42
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
|
@ -178,7 +178,7 @@ class ExampleError(Exception):
|
||||
self.code = code
|
||||
|
||||
|
||||
class ExampleClass(object):
|
||||
class ExampleClass:
|
||||
"""The summary line for a class docstring should fit on one line.
|
||||
|
||||
If the class has public attributes, they may be documented here
|
||||
|
@ -223,7 +223,7 @@ class ExampleError(Exception):
|
||||
self.code = code
|
||||
|
||||
|
||||
class ExampleClass(object):
|
||||
class ExampleClass:
|
||||
"""The summary line for a class docstring should fit on one line.
|
||||
|
||||
If the class has public attributes, they may be documented here
|
||||
|
@ -54,7 +54,7 @@ It adds this directive:
|
||||
E D F
|
||||
"""
|
||||
|
||||
class A(object):
|
||||
class A:
|
||||
pass
|
||||
|
||||
class B(A):
|
||||
|
@ -183,7 +183,7 @@ Sphinx.
|
||||
|
||||
The default is empty (not configured).
|
||||
|
||||
.. _Using in-line configuration options: http://docs.mathjax.org/en/latest/configuration.html#using-in-line-configuration-options
|
||||
.. _Using in-line configuration options: https://docs.mathjax.org/en/latest/configuration.html#using-in-line-configuration-options
|
||||
|
||||
:mod:`sphinx.ext.jsmath` -- Render math via JavaScript
|
||||
------------------------------------------------------
|
||||
|
@ -409,10 +409,10 @@ sure that "sphinx.ext.napoleon" is enabled in `conf.py`::
|
||||
|
||||
.. attribute:: attr1
|
||||
|
||||
*int*
|
||||
|
||||
Description of `attr1`
|
||||
|
||||
:type: int
|
||||
|
||||
.. confval:: napoleon_use_param
|
||||
|
||||
True to use a ``:param:`` role for each function parameter. False to
|
||||
|
@ -25,7 +25,11 @@ from the source to the description will also be inserted.
|
||||
|
||||
In addition, if you don't want to import the modules by ``viewcode``,
|
||||
you can tell the location of the location of source code to ``viewcode``
|
||||
using :event:`viewcode-find-source` event.
|
||||
using the :event:`viewcode-find-source` event.
|
||||
|
||||
If :confval:`viewcode_follow_imported_members` is enabled,
|
||||
you will also need to resolve imported attributes
|
||||
using the :event:`viewcode-follow-imported` event.
|
||||
|
||||
This extension works only on HTML related builders like ``html``,
|
||||
``applehelp``, ``devhelp``, ``htmlhelp``, ``qthelp`` and so on except
|
||||
@ -83,3 +87,13 @@ Configuration
|
||||
|
||||
:param app: The Sphinx application object.
|
||||
:param modname: The name of the module to find source code for.
|
||||
|
||||
.. event:: viewcode-follow-imported (app, modname, attribute)
|
||||
|
||||
.. versionadded:: 1.8
|
||||
|
||||
Find the name of the original module for an attribute.
|
||||
|
||||
:param app: The Sphinx application object.
|
||||
:param modname: The name of the module that the attribute belongs to.
|
||||
:param attribute: The name of the member to follow.
|
||||
|
@ -12,10 +12,9 @@ Installing Sphinx
|
||||
Overview
|
||||
--------
|
||||
|
||||
Sphinx is written in `Python`__ and supports both Python 2.7 and Python 3.3+.
|
||||
We recommend the latter.
|
||||
Sphinx is written in `Python`__ and supports Python 3.5+.
|
||||
|
||||
__ http://docs.python-guide.org/en/latest/
|
||||
__ https://docs.python-guide.org/
|
||||
|
||||
|
||||
Linux
|
||||
@ -73,7 +72,7 @@ Homebrew
|
||||
|
||||
For more information, refer to the `package overview`__.
|
||||
|
||||
__ http://formulae.brew.sh/formula/sphinx-doc
|
||||
__ https://formulae.brew.sh/formula/sphinx-doc
|
||||
|
||||
MacPorts
|
||||
~~~~~~~~
|
||||
@ -121,9 +120,9 @@ Once Python is installed, you can install Sphinx using :command:`pip`. Refer
|
||||
to the :ref:`pip installation instructions <install-pypi>` below for more
|
||||
information.
|
||||
|
||||
__ http://docs.python-guide.org/en/latest/
|
||||
__ http://docs.python-guide.org/en/latest/starting/install3/win/
|
||||
__ http://docs.python-guide.org/en/latest/starting/install/win/
|
||||
__ https://docs.python-guide.org/
|
||||
__ https://docs.python-guide.org/starting/install3/win/
|
||||
__ https://docs.python-guide.org/starting/install/win/
|
||||
|
||||
|
||||
.. _install-pypi:
|
||||
|
@ -15,7 +15,7 @@ parsing the `CommonMark`__ Markdown flavor.
|
||||
__ https://daringfireball.net/projects/markdown/
|
||||
__ https://recommonmark.readthedocs.io/en/latest/index.html
|
||||
__ https://github.com/rtfd/CommonMark-py
|
||||
__ http://commonmark.org/
|
||||
__ https://commonmark.org/
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
@ -1005,20 +1005,46 @@ These roles link to the given declaration types:
|
||||
When a custom title is not needed it may be useful to use the roles for inline expressions,
|
||||
:rst:role:`cpp:expr` and :rst:role:`cpp:texpr`, where angle brackets do not need escaping.
|
||||
|
||||
.. admonition:: Note on References to Overloaded Functions
|
||||
|
||||
It is currently impossible to link to a specific version of an overloaded
|
||||
function. Currently the C++ domain is the first domain that has basic
|
||||
support for overloaded functions and until there is more data for comparison
|
||||
we don't want to select a bad syntax to reference a specific overload.
|
||||
Currently Sphinx will link to the first overloaded version of the function.
|
||||
|
||||
Declarations without template parameters and template arguments
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For linking to non-templated declarations the name must be a nested name, e.g.,
|
||||
``f`` or ``MyClass::f``.
|
||||
|
||||
|
||||
Overloaded (member) functions
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
When a (member) function is referenced using just its name, the reference
|
||||
will point to an arbitrary matching overload.
|
||||
The :rst:role:`cpp:any` and :rst:role:`cpp:func` roles will an alternative
|
||||
format, which simply is a complete function declaration.
|
||||
This will resolve to the exact matching overload.
|
||||
As example, consider the following class declaration:
|
||||
|
||||
.. cpp:namespace-push:: overload_example
|
||||
.. cpp:class:: C
|
||||
|
||||
.. cpp:function:: void f(double d) const
|
||||
.. cpp:function:: void f(double d)
|
||||
.. cpp:function:: void f(int i)
|
||||
.. cpp:function:: void f()
|
||||
|
||||
References using the :rst:role:`cpp:func` role:
|
||||
|
||||
- Arbitrary overload: ``C::f``, :cpp:func:`C::f`
|
||||
- Also arbitrary overload: ``C::f()``, :cpp:func:`C::f()`
|
||||
- Specific overload: ``void C::f()``, :cpp:func:`void C::f()`
|
||||
- Specific overload: ``void C::f(int)``, :cpp:func:`void C::f(int)`
|
||||
- Specific overload: ``void C::f(double)``, :cpp:func:`void C::f(double)`
|
||||
- Specific overload: ``void C::f(double) const``, :cpp:func:`void C::f(double) const`
|
||||
|
||||
Note that the :confval:`add_function_parentheses` configuration variable
|
||||
does not influence specific overload references.
|
||||
|
||||
.. cpp:namespace-pop::
|
||||
|
||||
|
||||
Templated declarations
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
2584
package-lock.json
generated
2584
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"jasmine-core": "^3.1.0",
|
||||
"karma": "^2.0.4",
|
||||
"karma": "^3.0.0",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-firefox-launcher": "^1.1.0",
|
||||
"karma-jasmine": "^1.1.2"
|
||||
|
24
setup.py
24
setup.py
@ -11,15 +11,15 @@ import sphinx
|
||||
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.')
|
||||
if sys.version_info < (3, 5):
|
||||
print('ERROR: Sphinx requires at least Python 3.5 to run.')
|
||||
sys.exit(1)
|
||||
|
||||
install_requires = [
|
||||
'six>=1.5',
|
||||
'Jinja2>=2.3',
|
||||
'Pygments>=2.0',
|
||||
'docutils>=0.11',
|
||||
'docutils>=0.12',
|
||||
'snowballstemmer>=1.1',
|
||||
'babel>=1.3,!=2.0',
|
||||
'alabaster>=0.7,<0.8',
|
||||
@ -27,7 +27,6 @@ install_requires = [
|
||||
'requests>=2.0.0',
|
||||
'setuptools',
|
||||
'packaging',
|
||||
'sphinxcontrib-websupport',
|
||||
]
|
||||
|
||||
extras_require = {
|
||||
@ -35,9 +34,6 @@ extras_require = {
|
||||
':sys_platform=="win32"': [
|
||||
'colorama>=0.3.5',
|
||||
],
|
||||
':python_version<"3.5"': [
|
||||
'typing'
|
||||
],
|
||||
'websupport': [
|
||||
'sqlalchemy>=0.9',
|
||||
'whoosh>=2.0',
|
||||
@ -49,11 +45,6 @@ extras_require = {
|
||||
'html5lib',
|
||||
'flake8>=3.5.0',
|
||||
'flake8-import-order',
|
||||
],
|
||||
'test:python_version<"3"': [
|
||||
'enum34',
|
||||
],
|
||||
'test:python_version>="3"': [
|
||||
'mypy',
|
||||
'typed_ast',
|
||||
],
|
||||
@ -65,7 +56,7 @@ extras_require = {
|
||||
cmdclass = {}
|
||||
|
||||
|
||||
class Tee(object):
|
||||
class Tee:
|
||||
def __init__(self, stream):
|
||||
self.stream = stream
|
||||
self.buffer = StringIO()
|
||||
@ -195,12 +186,11 @@ setup(
|
||||
'License :: OSI Approved :: BSD License',
|
||||
'Operating System :: OS Independent',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: Python :: 2',
|
||||
'Programming Language :: Python :: 2.7',
|
||||
'Programming Language :: Python :: 3',
|
||||
'Programming Language :: Python :: 3.4',
|
||||
'Programming Language :: Python :: 3 :: Only',
|
||||
'Programming Language :: Python :: 3.5',
|
||||
'Programming Language :: Python :: 3.6',
|
||||
'Programming Language :: Python :: 3.7',
|
||||
'Programming Language :: Python :: Implementation :: CPython',
|
||||
'Programming Language :: Python :: Implementation :: PyPy',
|
||||
'Framework :: Setuptools Plugin',
|
||||
@ -235,7 +225,7 @@ setup(
|
||||
'build_sphinx = sphinx.setup_command:BuildDoc',
|
||||
],
|
||||
},
|
||||
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
|
||||
python_requires=">=3.5",
|
||||
install_requires=install_requires,
|
||||
extras_require=extras_require,
|
||||
cmdclass=cmdclass,
|
||||
|
@ -15,12 +15,10 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
from os import path
|
||||
|
||||
from .deprecation import RemovedInNextVersionWarning
|
||||
from .deprecation import RemovedInSphinx20Warning
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
@ -37,8 +35,8 @@ if 'PYTHONWARNINGS' not in os.environ:
|
||||
warnings.filterwarnings('ignore', "'U' mode is deprecated",
|
||||
DeprecationWarning, module='docutils.io')
|
||||
|
||||
__version__ = '1.8.0+'
|
||||
__released__ = '1.8.0' # used when Sphinx builds its own docs
|
||||
__version__ = '2.0.0+'
|
||||
__released__ = '2.0.0' # used when Sphinx builds its own docs
|
||||
|
||||
#: Version info for better programmatic use.
|
||||
#:
|
||||
@ -48,7 +46,7 @@ __released__ = '1.8.0' # used when Sphinx builds its own docs
|
||||
#:
|
||||
#: .. versionadded:: 1.2
|
||||
#: Before version 1.2, check the string ``sphinx.__version__``.
|
||||
version_info = (1, 8, 0, 'beta', 0)
|
||||
version_info = (2, 0, 0, 'beta', 0)
|
||||
|
||||
package_dir = path.abspath(path.dirname(__file__))
|
||||
|
||||
@ -61,55 +59,10 @@ if __version__.endswith('+'):
|
||||
__version__ = __version__[:-1] # remove '+' for PEP-440 version spec.
|
||||
try:
|
||||
import subprocess
|
||||
p = subprocess.Popen(['git', 'show', '-s', '--pretty=format:%h',
|
||||
path.join(package_dir, '..')],
|
||||
p = subprocess.Popen(['git', 'show', '-s', '--pretty=format:%h'],
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
out, err = p.communicate()
|
||||
if out:
|
||||
__display_version__ += '/' + out.decode().strip()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def main(argv=sys.argv): # type: ignore
|
||||
# type: (List[unicode]) -> int
|
||||
from .cmd import build
|
||||
warnings.warn(
|
||||
'`sphinx.main()` has moved to `sphinx.cmd.build.main()`.',
|
||||
RemovedInSphinx20Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
argv = argv[1:] # skip first argument to adjust arguments (refs: #4615)
|
||||
return build.main(argv)
|
||||
|
||||
|
||||
def build_main(argv=sys.argv):
|
||||
"""Sphinx build "main" command-line entry."""
|
||||
from .cmd import build
|
||||
warnings.warn(
|
||||
'`sphinx.build_main()` has moved to `sphinx.cmd.build.build_main()`.',
|
||||
RemovedInSphinx20Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return build.build_main(argv[1:]) # skip first argument to adjust arguments (refs: #4615)
|
||||
|
||||
|
||||
def make_main(argv=sys.argv):
|
||||
"""Sphinx build "make mode" entry."""
|
||||
from .cmd import build
|
||||
warnings.warn(
|
||||
'`sphinx.build_main()` has moved to `sphinx.cmd.build.make_main()`.',
|
||||
RemovedInSphinx20Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
return build.make_main(argv[1:]) # skip first argument to adjust arguments (refs: #4615)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from .cmd import build
|
||||
warnings.warn(
|
||||
'`sphinx` has moved to `sphinx.build`.',
|
||||
RemovedInSphinx20Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
build.main()
|
||||
|
@ -20,7 +20,7 @@ if False:
|
||||
from typing import List, Sequence # NOQA
|
||||
|
||||
|
||||
class translatable(object):
|
||||
class translatable:
|
||||
"""Node which supports translation.
|
||||
|
||||
The translation goes forward with following steps:
|
||||
@ -53,7 +53,7 @@ class translatable(object):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class not_smartquotable(object):
|
||||
class not_smartquotable:
|
||||
"""A node which does not support smart-quotes."""
|
||||
support_smartquotes = False
|
||||
|
||||
|
@ -1,41 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
sphinx.apidoc
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
This file has moved to :py:mod:`sphinx.ext.apidoc`.
|
||||
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.ext.apidoc import main as _main
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import List # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
|
||||
def main(argv=sys.argv):
|
||||
# type: (List[str]) -> None
|
||||
warnings.warn(
|
||||
'`sphinx.apidoc.main()` has moved to `sphinx.ext.apidoc.main()`.',
|
||||
RemovedInSphinx20Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
_main(argv[1:]) # skip first argument to adjust arguments (refs: #4615)
|
||||
|
||||
|
||||
# So program can be started with "python -m sphinx.apidoc ..."
|
||||
if __name__ == "__main__":
|
||||
warnings.warn(
|
||||
'`sphinx.apidoc` has moved to `sphinx.ext.apidoc`.',
|
||||
RemovedInSphinx20Warning,
|
||||
stacklevel=2,
|
||||
)
|
||||
main()
|
@ -13,6 +13,7 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import pickle
|
||||
import sys
|
||||
import warnings
|
||||
from collections import deque
|
||||
@ -20,8 +21,6 @@ from inspect import isclass
|
||||
from os import path
|
||||
|
||||
from docutils.parsers.rst import Directive, directives, roles
|
||||
from six import itervalues
|
||||
from six.moves import cPickle as pickle
|
||||
from six.moves import cStringIO
|
||||
|
||||
import sphinx
|
||||
@ -29,7 +28,7 @@ from sphinx import package_dir, locale
|
||||
from sphinx.config import Config, check_unicode
|
||||
from sphinx.config import CONFIG_FILENAME # NOQA # for compatibility (RemovedInSphinx30)
|
||||
from sphinx.deprecation import (
|
||||
RemovedInSphinx20Warning, RemovedInSphinx30Warning, RemovedInSphinx40Warning
|
||||
RemovedInSphinx30Warning, RemovedInSphinx40Warning
|
||||
)
|
||||
from sphinx.environment import BuildEnvironment
|
||||
from sphinx.errors import ApplicationError, ConfigError, VersionRequirementError
|
||||
@ -118,7 +117,7 @@ ENV_PICKLE_FILENAME = 'environment.pickle'
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Sphinx(object):
|
||||
class Sphinx:
|
||||
"""The main application class and extensibility interface.
|
||||
|
||||
:ivar srcdir: Directory containing source.
|
||||
@ -250,11 +249,6 @@ class Sphinx(object):
|
||||
self.config.init_values()
|
||||
self.emit('config-inited', self.config)
|
||||
|
||||
# check primary_domain if requested
|
||||
primary_domain = self.config.primary_domain
|
||||
if primary_domain and not self.registry.has_domain(primary_domain):
|
||||
logger.warning(__('primary_domain %r not found, ignored.'), primary_domain)
|
||||
|
||||
# create the builder
|
||||
self.builder = self.create_builder(buildername)
|
||||
# set up the build environment
|
||||
@ -369,72 +363,6 @@ class Sphinx(object):
|
||||
self.emit('build-finished', None)
|
||||
self.builder.cleanup()
|
||||
|
||||
# ---- logging handling ----------------------------------------------------
|
||||
def warn(self, message, location=None, type=None, subtype=None):
|
||||
# type: (unicode, unicode, unicode, unicode) -> None
|
||||
"""Emit a warning.
|
||||
|
||||
If *location* is given, it should either be a tuple of (*docname*,
|
||||
*lineno*) or a string describing the location of the warning as well as
|
||||
possible.
|
||||
|
||||
*type* and *subtype* are used to suppress warnings with
|
||||
:confval:`suppress_warnings`.
|
||||
|
||||
.. deprecated:: 1.6
|
||||
Use :mod:`sphinx.util.logging` instead.
|
||||
"""
|
||||
warnings.warn('app.warning() is now deprecated. Use sphinx.util.logging instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
logger.warning(message, type=type, subtype=subtype, location=location)
|
||||
|
||||
def info(self, message='', nonl=False):
|
||||
# type: (unicode, bool) -> None
|
||||
"""Emit an informational message.
|
||||
|
||||
If *nonl* is true, don't emit a newline at the end (which implies that
|
||||
more info output will follow soon.)
|
||||
|
||||
.. deprecated:: 1.6
|
||||
Use :mod:`sphinx.util.logging` instead.
|
||||
"""
|
||||
warnings.warn('app.info() is now deprecated. Use sphinx.util.logging instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
logger.info(message, nonl=nonl)
|
||||
|
||||
def verbose(self, message, *args, **kwargs):
|
||||
# type: (unicode, Any, Any) -> None
|
||||
"""Emit a verbose informational message.
|
||||
|
||||
.. deprecated:: 1.6
|
||||
Use :mod:`sphinx.util.logging` instead.
|
||||
"""
|
||||
warnings.warn('app.verbose() is now deprecated. Use sphinx.util.logging instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
logger.verbose(message, *args, **kwargs)
|
||||
|
||||
def debug(self, message, *args, **kwargs):
|
||||
# type: (unicode, Any, Any) -> None
|
||||
"""Emit a debug-level informational message.
|
||||
|
||||
.. deprecated:: 1.6
|
||||
Use :mod:`sphinx.util.logging` instead.
|
||||
"""
|
||||
warnings.warn('app.debug() is now deprecated. Use sphinx.util.logging instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
logger.debug(message, *args, **kwargs)
|
||||
|
||||
def debug2(self, message, *args, **kwargs):
|
||||
# type: (unicode, Any, Any) -> None
|
||||
"""Emit a lowlevel debug-level informational message.
|
||||
|
||||
.. deprecated:: 1.6
|
||||
Use :mod:`sphinx.util.logging` instead.
|
||||
"""
|
||||
warnings.warn('app.debug2() is now deprecated. Use debug() instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
logger.debug(message, *args, **kwargs)
|
||||
|
||||
# ---- general extensibility interface -------------------------------------
|
||||
|
||||
def setup_extension(self, extname):
|
||||
@ -913,21 +841,6 @@ class Sphinx(object):
|
||||
ref_nodeclass, objname, doc_field_types,
|
||||
override=override)
|
||||
|
||||
def add_description_unit(self, directivename, rolename, indextemplate='',
|
||||
parse_node=None, ref_nodeclass=None, objname='',
|
||||
doc_field_types=[]):
|
||||
# type: (unicode, unicode, unicode, Callable, nodes.Node, unicode, List) -> None
|
||||
"""Deprecated alias for :meth:`add_object_type`.
|
||||
|
||||
.. deprecated:: 1.6
|
||||
Use :meth:`add_object_type` instead.
|
||||
"""
|
||||
warnings.warn('app.add_description_unit() is now deprecated. '
|
||||
'Use app.add_object_type() instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
self.add_object_type(directivename, rolename, indextemplate, parse_node,
|
||||
ref_nodeclass, objname, doc_field_types)
|
||||
|
||||
def add_crossref_type(self, directivename, rolename, indextemplate='',
|
||||
ref_nodeclass=None, objname='', override=False):
|
||||
# type: (unicode, unicode, unicode, nodes.Node, unicode, bool) -> None
|
||||
@ -1040,6 +953,8 @@ class Sphinx(object):
|
||||
And it allows keyword arguments as attributes of script tag.
|
||||
"""
|
||||
self.registry.add_js_file(filename, **kwargs)
|
||||
if hasattr(self.builder, 'add_js_file'):
|
||||
self.builder.add_js_file(filename, **kwargs) # type: ignore
|
||||
|
||||
def add_css_file(self, filename, **kwargs):
|
||||
# type: (unicode, **unicode) -> None
|
||||
@ -1078,6 +993,8 @@ class Sphinx(object):
|
||||
"""
|
||||
logger.debug('[app] adding stylesheet: %r', filename)
|
||||
self.registry.add_css_files(filename, **kwargs)
|
||||
if hasattr(self.builder, 'add_css_file'):
|
||||
self.builder.add_css_file(filename, **kwargs) # type: ignore
|
||||
|
||||
def add_stylesheet(self, filename, alternate=False, title=None):
|
||||
# type: (unicode, bool, unicode) -> None
|
||||
@ -1278,7 +1195,7 @@ class Sphinx(object):
|
||||
else:
|
||||
raise ValueError('parallel type %s is not supported' % typ)
|
||||
|
||||
for ext in itervalues(self.extensions):
|
||||
for ext in self.extensions.values():
|
||||
allowed = getattr(ext, attrname, None)
|
||||
if allowed is None:
|
||||
logger.warning(message, ext.name)
|
||||
@ -1290,7 +1207,7 @@ class Sphinx(object):
|
||||
return True
|
||||
|
||||
|
||||
class TemplateBridge(object):
|
||||
class TemplateBridge:
|
||||
"""
|
||||
This class defines the interface for a "template bridge", that is, a class
|
||||
that renders templates given a template name and a context.
|
||||
|
@ -9,14 +9,12 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import pickle
|
||||
import time
|
||||
import warnings
|
||||
from os import path
|
||||
|
||||
from docutils import nodes
|
||||
from six.moves import cPickle as pickle
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.environment import CONFIG_OK, CONFIG_CHANGED_REASON
|
||||
from sphinx.environment.adapters.asset import ImageAdapter
|
||||
from sphinx.errors import SphinxError
|
||||
@ -54,7 +52,7 @@ if False:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Builder(object):
|
||||
class Builder:
|
||||
"""
|
||||
Builds target formats from the reST sources.
|
||||
"""
|
||||
@ -97,8 +95,6 @@ class Builder(object):
|
||||
|
||||
self.app = app # type: Sphinx
|
||||
self.env = None # type: BuildEnvironment
|
||||
self.warn = app.warn # type: Callable
|
||||
self.info = app.info # type: Callable
|
||||
self.config = app.config # type: Config
|
||||
self.tags = app.tags # type: Tags
|
||||
self.tags.add(self.format)
|
||||
@ -138,22 +134,6 @@ class Builder(object):
|
||||
"""
|
||||
return self.app.registry.create_translator(self, *args)
|
||||
|
||||
@property
|
||||
def translator_class(self):
|
||||
# type: () -> Callable[[Any], nodes.NodeVisitor]
|
||||
"""Return a class of translator.
|
||||
|
||||
.. deprecated:: 1.6
|
||||
"""
|
||||
translator_class = self.app.registry.get_translator_class(self)
|
||||
if translator_class is None and self.default_translator_class is None:
|
||||
warnings.warn('builder.translator_class() is now deprecated. '
|
||||
'Please use builder.create_translator() and '
|
||||
'builder.default_translator_class instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
return None
|
||||
return self.create_translator
|
||||
|
||||
# helper methods
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
@ -261,7 +241,6 @@ class Builder(object):
|
||||
[path.join(self.srcdir, x) for x in self.config.locale_dirs],
|
||||
self.config.language,
|
||||
charset=self.config.source_encoding,
|
||||
gettext_compact=self.config.gettext_compact,
|
||||
force_all=True,
|
||||
excluded=Matcher(['**/.?**']))
|
||||
message = __('all of %d po files') % len(catalogs)
|
||||
@ -284,7 +263,6 @@ class Builder(object):
|
||||
self.config.language,
|
||||
domains=list(specified_domains),
|
||||
charset=self.config.source_encoding,
|
||||
gettext_compact=self.config.gettext_compact,
|
||||
excluded=Matcher(['**/.?**']))
|
||||
message = __('targets for %d po files that are specified') % len(catalogs)
|
||||
self.compile_catalogs(catalogs, message)
|
||||
@ -295,7 +273,6 @@ class Builder(object):
|
||||
[path.join(self.srcdir, x) for x in self.config.locale_dirs],
|
||||
self.config.language,
|
||||
charset=self.config.source_encoding,
|
||||
gettext_compact=self.config.gettext_compact,
|
||||
excluded=Matcher(['**/.?**']))
|
||||
message = __('targets for %d po files that are out of date') % len(catalogs)
|
||||
self.compile_catalogs(catalogs, message)
|
||||
@ -559,7 +536,7 @@ class Builder(object):
|
||||
doctree.settings.env = None
|
||||
doctree.settings.record_dependencies = None
|
||||
|
||||
doctree_filename = self.env.doc2path(docname, self.env.doctreedir, '.doctree')
|
||||
doctree_filename = path.join(self.doctreedir, docname + '.doctree')
|
||||
ensuredir(path.dirname(doctree_filename))
|
||||
with open(doctree_filename, 'wb') as f:
|
||||
pickle.dump(doctree, f, pickle.HIGHEST_PROTOCOL)
|
||||
|
@ -10,7 +10,6 @@
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import codecs
|
||||
import pipes
|
||||
import plistlib
|
||||
import shlex
|
||||
@ -36,13 +35,6 @@ if False:
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Use plistlib.dump in 3.4 and above
|
||||
try:
|
||||
write_plist = plistlib.dump # type: ignore
|
||||
except AttributeError:
|
||||
write_plist = plistlib.writePlist
|
||||
|
||||
|
||||
# False access page (used because helpd expects strict XHTML)
|
||||
access_page_template = '''\
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\
|
||||
@ -174,7 +166,7 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
|
||||
|
||||
logger.info(bold(__('writing Info.plist... ')), nonl=True)
|
||||
with open(path.join(contents_dir, 'Info.plist'), 'wb') as f:
|
||||
write_plist(info_plist, f)
|
||||
plistlib.dump(info_plist, f) # type: ignore
|
||||
logger.info(__('done'))
|
||||
|
||||
# Copy the icon, if one is supplied
|
||||
@ -193,7 +185,7 @@ class AppleHelpBuilder(StandaloneHTMLBuilder):
|
||||
|
||||
# Build the access page
|
||||
logger.info(bold(__('building access page...')), nonl=True)
|
||||
with codecs.open(path.join(language_dir, '_access.html'), 'w') as f: # type: ignore
|
||||
with open(path.join(language_dir, '_access.html'), 'w') as f:
|
||||
f.write(access_page_template % {
|
||||
'toc': htmlescape(toc, quote=True),
|
||||
'title': htmlescape(self.config.applehelp_title)
|
||||
|
@ -9,12 +9,9 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import codecs
|
||||
from os import path
|
||||
from typing import cast
|
||||
|
||||
from six import iteritems
|
||||
|
||||
from sphinx import package_dir
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.domains.changeset import ChangeSetDomain
|
||||
@ -109,15 +106,17 @@ class ChangesBuilder(Builder):
|
||||
'version': version,
|
||||
'docstitle': self.config.html_title,
|
||||
'shorttitle': self.config.html_short_title,
|
||||
'libchanges': sorted(iteritems(libchanges)),
|
||||
'libchanges': sorted(libchanges.items()),
|
||||
'apichanges': sorted(apichanges),
|
||||
'otherchanges': sorted(iteritems(otherchanges)),
|
||||
'otherchanges': sorted(otherchanges.items()),
|
||||
'show_copyright': self.config.html_show_copyright,
|
||||
'show_sphinx': self.config.html_show_sphinx,
|
||||
}
|
||||
with codecs.open(path.join(self.outdir, 'index.html'), 'w', 'utf8') as f: # type: ignore # NOQA
|
||||
with open(path.join(self.outdir, 'index.html'), 'w', # type: ignore
|
||||
encoding='utf8') as f:
|
||||
f.write(self.templates.render('changes/frameset.html', ctx))
|
||||
with codecs.open(path.join(self.outdir, 'changes.html'), 'w', 'utf8') as f: # type: ignore # NOQA
|
||||
with open(path.join(self.outdir, 'changes.html'), 'w', # type: ignore
|
||||
encoding='utf8') as f:
|
||||
f.write(self.templates.render('changes/versionchanges.html', ctx))
|
||||
|
||||
hltext = ['.. versionadded:: %s' % version,
|
||||
@ -135,8 +134,8 @@ class ChangesBuilder(Builder):
|
||||
|
||||
logger.info(bold(__('copying source files...')))
|
||||
for docname in self.env.all_docs:
|
||||
with codecs.open(self.env.doc2path(docname), 'r', # type: ignore
|
||||
self.env.config.source_encoding) as f:
|
||||
with open(self.env.doc2path(docname), 'r', # type: ignore
|
||||
encoding=self.env.config.source_encoding) as f:
|
||||
try:
|
||||
lines = f.readlines()
|
||||
except UnicodeDecodeError:
|
||||
@ -144,7 +143,7 @@ class ChangesBuilder(Builder):
|
||||
continue
|
||||
targetfn = path.join(self.outdir, 'rst', os_path(docname)) + '.html'
|
||||
ensuredir(path.dirname(targetfn))
|
||||
with codecs.open(targetfn, 'w', 'utf-8') as f: # type: ignore
|
||||
with open(targetfn, 'w', encoding='utf-8') as f: # type: ignore
|
||||
text = ''.join(hl(i + 1, line) for (i, line) in enumerate(lines))
|
||||
ctx = {
|
||||
'filename': self.env.doc2path(docname, None),
|
||||
@ -152,7 +151,7 @@ class ChangesBuilder(Builder):
|
||||
}
|
||||
f.write(self.templates.render('changes/rstsource.html', ctx))
|
||||
themectx = dict(('theme_' + key, val) for (key, val) in
|
||||
iteritems(self.theme.get_options({})))
|
||||
self.theme.get_options({}).items())
|
||||
copy_asset_file(path.join(package_dir, 'themes', 'default', 'static', 'default.css_t'),
|
||||
self.outdir, context=themectx, renderer=self.templates)
|
||||
copy_asset_file(path.join(package_dir, 'themes', 'basic', 'static', 'basic.css'),
|
||||
|
@ -15,6 +15,7 @@ from __future__ import absolute_import
|
||||
import gzip
|
||||
import re
|
||||
from os import path
|
||||
from typing import Any
|
||||
|
||||
from docutils import nodes
|
||||
|
||||
@ -23,6 +24,7 @@ from sphinx.builders.html import StandaloneHTMLBuilder
|
||||
from sphinx.environment.adapters.indexentries import IndexEntries
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.nodes import NodeMatcher
|
||||
from sphinx.util.osutil import make_filename
|
||||
|
||||
try:
|
||||
@ -32,7 +34,7 @@ except ImportError:
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Dict, List # NOQA
|
||||
from typing import Dict, List # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
|
||||
@ -100,12 +102,8 @@ class DevhelpBuilder(StandaloneHTMLBuilder):
|
||||
parent.attrib['link'] = node['refuri']
|
||||
parent.attrib['name'] = node.astext()
|
||||
|
||||
def istoctree(node):
|
||||
# type: (nodes.Node) -> bool
|
||||
return isinstance(node, addnodes.compact_paragraph) and \
|
||||
'toctree' in node
|
||||
|
||||
for node in tocdoc.traverse(istoctree):
|
||||
matcher = NodeMatcher(addnodes.compact_paragraph, toctree=Any)
|
||||
for node in tocdoc.traverse(matcher):
|
||||
write_toc(node, chapters)
|
||||
|
||||
# Index
|
||||
|
@ -18,7 +18,7 @@ from os import path, walk, getenv
|
||||
from time import time
|
||||
from uuid import uuid4
|
||||
|
||||
from six import iteritems, StringIO
|
||||
from six import StringIO
|
||||
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.domains.python import pairindextypes
|
||||
@ -62,7 +62,7 @@ msgstr ""
|
||||
"""[1:]
|
||||
|
||||
|
||||
class Catalog(object):
|
||||
class Catalog:
|
||||
"""Catalog of translatable messages."""
|
||||
|
||||
def __init__(self):
|
||||
@ -84,7 +84,7 @@ class Catalog(object):
|
||||
self.metadata[msg].append((origin.source, origin.line, origin.uid))
|
||||
|
||||
|
||||
class MsgOrigin(object):
|
||||
class MsgOrigin:
|
||||
"""
|
||||
Origin holder for Catalog message origin.
|
||||
"""
|
||||
@ -268,7 +268,7 @@ class MessageCatalogBuilder(I18nBuilder):
|
||||
ctime = datetime.fromtimestamp(
|
||||
timestamp, ltz).strftime('%Y-%m-%d %H:%M%z'),
|
||||
)
|
||||
for textdomain, catalog in status_iterator(iteritems(self.catalogs), # type: ignore
|
||||
for textdomain, catalog in status_iterator(self.catalogs.items(), # type: ignore
|
||||
__("writing message catalogs... "),
|
||||
"darkgreen", len(self.catalogs),
|
||||
self.app.verbosity,
|
||||
|
@ -9,7 +9,7 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import codecs
|
||||
import pickle
|
||||
import posixpath
|
||||
import re
|
||||
import sys
|
||||
@ -25,14 +25,13 @@ from docutils.frontend import OptionParser
|
||||
from docutils.io import DocTreeInput, StringOutput
|
||||
from docutils.readers.doctree import Reader as DoctreeReader
|
||||
from docutils.utils import relative_path
|
||||
from six import iteritems, text_type, string_types
|
||||
from six.moves import cPickle as pickle
|
||||
from six import text_type, string_types
|
||||
|
||||
from sphinx import package_dir, __display_version__
|
||||
from sphinx.application import ENV_PICKLE_FILENAME
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.config import string_classes
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning, RemovedInSphinx30Warning
|
||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||
from sphinx.environment.adapters.asset import ImageAdapter
|
||||
from sphinx.environment.adapters.indexentries import IndexEntries
|
||||
from sphinx.environment.adapters.toctree import TocTree
|
||||
@ -92,53 +91,6 @@ def get_stable_hash(obj):
|
||||
return md5(text_type(obj).encode('utf8')).hexdigest()
|
||||
|
||||
|
||||
class CSSContainer(list):
|
||||
"""The container for stylesheets.
|
||||
|
||||
To support the extensions which access the container directly, this wraps
|
||||
the entry with Stylesheet class.
|
||||
"""
|
||||
def append(self, obj):
|
||||
# type: (Union[unicode, Stylesheet]) -> None
|
||||
if isinstance(obj, Stylesheet):
|
||||
super(CSSContainer, self).append(obj)
|
||||
else:
|
||||
super(CSSContainer, self).append(Stylesheet(obj))
|
||||
|
||||
def insert(self, index, obj):
|
||||
# type: (int, Union[unicode, Stylesheet]) -> None
|
||||
warnings.warn('builder.css_files is deprecated. '
|
||||
'Please use app.add_stylesheet() instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
if isinstance(obj, Stylesheet):
|
||||
super(CSSContainer, self).insert(index, obj)
|
||||
else:
|
||||
super(CSSContainer, self).insert(index, Stylesheet(obj))
|
||||
|
||||
def extend(self, other): # type: ignore
|
||||
# type: (List[Union[unicode, Stylesheet]]) -> None
|
||||
warnings.warn('builder.css_files is deprecated. '
|
||||
'Please use app.add_stylesheet() instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
for item in other:
|
||||
self.append(item)
|
||||
|
||||
def __iadd__(self, other): # type: ignore
|
||||
# type: (List[Union[unicode, Stylesheet]]) -> CSSContainer
|
||||
warnings.warn('builder.css_files is deprecated. '
|
||||
'Please use app.add_stylesheet() instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
for item in other:
|
||||
self.append(item)
|
||||
return self
|
||||
|
||||
def __add__(self, other):
|
||||
# type: (List[Union[unicode, Stylesheet]]) -> CSSContainer
|
||||
ret = CSSContainer(self)
|
||||
ret += other
|
||||
return ret
|
||||
|
||||
|
||||
class Stylesheet(text_type):
|
||||
"""A metadata of stylesheet.
|
||||
|
||||
@ -216,7 +168,7 @@ class JavaScript(text_type):
|
||||
return self
|
||||
|
||||
|
||||
class BuildInfo(object):
|
||||
class BuildInfo:
|
||||
"""buildinfo file manipulator.
|
||||
|
||||
HTMLBuilder and its family are storing their own envdata to ``.buildinfo``.
|
||||
@ -256,10 +208,6 @@ class BuildInfo(object):
|
||||
return (self.config_hash == other.config_hash and
|
||||
self.tags_hash == other.tags_hash)
|
||||
|
||||
def __ne__(self, other): # type: ignore
|
||||
# type: (BuildInfo) -> bool
|
||||
return not (self == other) # for py27
|
||||
|
||||
def dump(self, f):
|
||||
# type: (IO) -> None
|
||||
f.write('# Sphinx build info version 1\n'
|
||||
@ -311,7 +259,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
super(StandaloneHTMLBuilder, self).__init__(app)
|
||||
|
||||
# CSS files
|
||||
self.css_files = CSSContainer() # type: List[Dict[unicode, unicode]]
|
||||
self.css_files = [] # type: List[Dict[unicode, unicode]]
|
||||
|
||||
# JS files
|
||||
self.script_files = JSContainer() # type: List[JavaScript]
|
||||
@ -330,20 +278,23 @@ class StandaloneHTMLBuilder(Builder):
|
||||
self.init_highlighter()
|
||||
self.init_css_files()
|
||||
self.init_js_files()
|
||||
if self.config.html_file_suffix is not None:
|
||||
self.out_suffix = self.config.html_file_suffix
|
||||
|
||||
if self.config.html_link_suffix is not None:
|
||||
self.link_suffix = self.config.html_link_suffix
|
||||
html_file_suffix = self.get_builder_config('file_suffix', 'html')
|
||||
if html_file_suffix is not None:
|
||||
self.out_suffix = html_file_suffix
|
||||
|
||||
html_link_suffix = self.get_builder_config('link_suffix', 'html')
|
||||
if html_link_suffix is not None:
|
||||
self.link_suffix = html_link_suffix
|
||||
else:
|
||||
self.link_suffix = self.out_suffix
|
||||
|
||||
self.use_index = self.get_builder_config('use_index', 'html')
|
||||
|
||||
if self.config.html_experimental_html5_writer and not html5_ready:
|
||||
self.app.warn(('html_experimental_html5_writer is set, but current version '
|
||||
'is old. Docutils\' version should be 0.13 or newer, but %s.') %
|
||||
docutils.__version__)
|
||||
logger.warning(__('html_experimental_html5_writer is set, but current version '
|
||||
'is old. Docutils\' version should be 0.13 or newer, but %s.'),
|
||||
docutils.__version__)
|
||||
|
||||
def create_build_info(self):
|
||||
# type: () -> BuildInfo
|
||||
@ -633,7 +584,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
if self.theme:
|
||||
self.globalcontext.update(
|
||||
('theme_' + key, val) for (key, val) in
|
||||
iteritems(self.theme.get_options(self.theme_options)))
|
||||
self.theme.get_options(self.theme_options).items())
|
||||
self.globalcontext.update(self.config.html_context)
|
||||
|
||||
def get_doc_context(self, docname, body, metatags):
|
||||
@ -864,10 +815,10 @@ class StandaloneHTMLBuilder(Builder):
|
||||
for src in status_iterator(self.env.dlfiles, __('copying downloadable files... '),
|
||||
"brown", len(self.env.dlfiles), self.app.verbosity,
|
||||
stringify_func=to_relpath):
|
||||
dest = self.env.dlfiles[src][1]
|
||||
try:
|
||||
copyfile(path.join(self.srcdir, src),
|
||||
path.join(self.outdir, '_downloads', dest))
|
||||
dest = path.join(self.outdir, '_downloads', self.env.dlfiles[src][1])
|
||||
ensuredir(path.dirname(dest))
|
||||
copyfile(path.join(self.srcdir, src), dest)
|
||||
except EnvironmentError as err:
|
||||
logger.warning(__('cannot copy downloadable file %r: %s'),
|
||||
path.join(self.srcdir, src), err)
|
||||
@ -1003,9 +954,9 @@ class StandaloneHTMLBuilder(Builder):
|
||||
try:
|
||||
searchindexfn = path.join(self.outdir, self.searchindex_filename)
|
||||
if self.indexer_dumps_unicode:
|
||||
f = codecs.open(searchindexfn, 'r', encoding='utf-8') # type: ignore
|
||||
f = open(searchindexfn, 'r', encoding='utf-8') # type: ignore
|
||||
else:
|
||||
f = open(searchindexfn, 'rb') # type: ignore
|
||||
f = open(searchindexfn, 'rb')
|
||||
with f:
|
||||
self.indexer.load(f, self.indexer_format)
|
||||
except (IOError, OSError, ValueError):
|
||||
@ -1066,7 +1017,8 @@ class StandaloneHTMLBuilder(Builder):
|
||||
sidebars = [name.strip() for name in theme_default_sidebars.split(',')]
|
||||
|
||||
# user sidebar settings
|
||||
for pattern, patsidebars in iteritems(self.config.html_sidebars):
|
||||
html_sidebars = self.get_builder_config('sidebars', 'html')
|
||||
for pattern, patsidebars in html_sidebars.items():
|
||||
if patmatch(pagename, pattern):
|
||||
if matched:
|
||||
if has_wildcard(pattern):
|
||||
@ -1084,14 +1036,6 @@ class StandaloneHTMLBuilder(Builder):
|
||||
if sidebars is None:
|
||||
# keep defaults
|
||||
pass
|
||||
elif isinstance(sidebars, string_types):
|
||||
# 0.x compatible mode: insert custom sidebar before searchbox
|
||||
customsidebar = sidebars
|
||||
sidebars = None
|
||||
warnings.warn('Now html_sidebars only allows list of sidebar '
|
||||
'templates as a value. Support for a string value '
|
||||
'will be removed at Sphinx-2.0.',
|
||||
RemovedInSphinx20Warning)
|
||||
|
||||
ctx['sidebars'] = sidebars
|
||||
ctx['customsidebar'] = customsidebar
|
||||
@ -1161,7 +1105,7 @@ class StandaloneHTMLBuilder(Builder):
|
||||
warnings.warn('The template function warn() was deprecated. '
|
||||
'Use warning() instead.',
|
||||
RemovedInSphinx30Warning)
|
||||
self.warn(*args, **kwargs)
|
||||
logger.warning(*args, **kwargs)
|
||||
return '' # return empty string
|
||||
ctx['warn'] = warn
|
||||
|
||||
@ -1191,7 +1135,8 @@ class StandaloneHTMLBuilder(Builder):
|
||||
# outfilename's path is in general different from self.outdir
|
||||
ensuredir(path.dirname(outfilename))
|
||||
try:
|
||||
with codecs.open(outfilename, 'w', ctx['encoding'], 'xmlcharrefreplace') as f: # type: ignore # NOQA
|
||||
with open(outfilename, 'w', # type: ignore
|
||||
encoding=ctx['encoding'], errors='xmlcharrefreplace') as f:
|
||||
f.write(output)
|
||||
except (IOError, OSError) as err:
|
||||
logger.warning(__("error writing file %s: %s"), outfilename, err)
|
||||
@ -1228,9 +1173,9 @@ class StandaloneHTMLBuilder(Builder):
|
||||
# first write to a temporary file, so that if dumping fails,
|
||||
# the existing index won't be overwritten
|
||||
if self.indexer_dumps_unicode:
|
||||
f = codecs.open(searchindexfn + '.tmp', 'w', encoding='utf-8') # type: ignore
|
||||
f = open(searchindexfn + '.tmp', 'w', encoding='utf-8') # type: ignore
|
||||
else:
|
||||
f = open(searchindexfn + '.tmp', 'wb') # type: ignore
|
||||
f = open(searchindexfn + '.tmp', 'wb')
|
||||
with f:
|
||||
self.indexer.dump(f, self.indexer_format)
|
||||
movefile(searchindexfn + '.tmp', searchindexfn)
|
||||
@ -1345,8 +1290,8 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
# There are related codes in inline_all_toctres() and
|
||||
# HTMLTranslter#add_secnumber().
|
||||
new_secnumbers = {} # type: Dict[unicode, Tuple[int, ...]]
|
||||
for docname, secnums in iteritems(self.env.toc_secnumbers):
|
||||
for id, secnum in iteritems(secnums):
|
||||
for docname, secnums in self.env.toc_secnumbers.items():
|
||||
for id, secnum in secnums.items():
|
||||
alias = "%s/%s" % (docname, id)
|
||||
new_secnumbers[alias] = secnum
|
||||
|
||||
@ -1365,11 +1310,11 @@ class SingleFileHTMLBuilder(StandaloneHTMLBuilder):
|
||||
# HTMLTranslter#add_fignumber().
|
||||
new_fignumbers = {} # type: Dict[unicode, Dict[unicode, Tuple[int, ...]]]
|
||||
# {u'foo': {'figure': {'id2': (2,), 'id1': (1,)}}, u'bar': {'figure': {'id1': (3,)}}}
|
||||
for docname, fignumlist in iteritems(self.env.toc_fignumbers):
|
||||
for figtype, fignums in iteritems(fignumlist):
|
||||
for docname, fignumlist in self.env.toc_fignumbers.items():
|
||||
for figtype, fignums in fignumlist.items():
|
||||
alias = "%s/%s" % (docname, figtype)
|
||||
new_fignumbers.setdefault(alias, {})
|
||||
for id, fignum in iteritems(fignums):
|
||||
for id, fignum in fignums.items():
|
||||
new_fignumbers[alias][id] = fignum
|
||||
|
||||
return {self.config.master_doc: new_fignumbers}
|
||||
@ -1487,9 +1432,9 @@ class SerializingHTMLBuilder(StandaloneHTMLBuilder):
|
||||
def dump_context(self, context, filename):
|
||||
# type: (Dict, unicode) -> None
|
||||
if self.implementation_dumps_unicode:
|
||||
f = codecs.open(filename, 'w', encoding='utf-8') # type: ignore
|
||||
f = open(filename, 'w', encoding='utf-8') # type: ignore
|
||||
else:
|
||||
f = open(filename, 'wb') # type: ignore
|
||||
f = open(filename, 'wb')
|
||||
with f:
|
||||
self.implementation.dump(context, f, *self.additional_dump_args)
|
||||
|
||||
@ -1714,6 +1659,8 @@ def setup(app):
|
||||
app.add_config_value('html_baseurl', '', 'html')
|
||||
app.add_config_value('html_math_renderer', None, 'env')
|
||||
|
||||
app.add_config_value('singlehtml_sidebars', lambda self: self.html_sidebars, 'html')
|
||||
|
||||
# event handlers
|
||||
app.connect('config-inited', convert_html_css_files)
|
||||
app.connect('config-inited', convert_html_js_files)
|
||||
|
@ -11,7 +11,6 @@
|
||||
"""
|
||||
from __future__ import print_function
|
||||
|
||||
import codecs
|
||||
import os
|
||||
from os import path
|
||||
|
||||
@ -19,6 +18,7 @@ from docutils import nodes
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.builders.html import StandaloneHTMLBuilder
|
||||
from sphinx.config import string_classes
|
||||
from sphinx.environment.adapters.indexentries import IndexEntries
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import logging
|
||||
@ -133,8 +133,9 @@ that the their then there these they this to
|
||||
was will with
|
||||
""".split()
|
||||
|
||||
# The following list includes only languages supported by Sphinx.
|
||||
# See http://msdn.microsoft.com/en-us/library/ms930130.aspx for more.
|
||||
# The following list includes only languages supported by Sphinx. See
|
||||
# https://docs.microsoft.com/en-us/previous-versions/windows/embedded/ms930130(v=msdn.10)
|
||||
# for more.
|
||||
chm_locales = {
|
||||
# lang: LCID, encoding
|
||||
'ca': (0x403, 'cp1252'),
|
||||
@ -195,10 +196,10 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
|
||||
|
||||
def init(self):
|
||||
# type: () -> None
|
||||
StandaloneHTMLBuilder.init(self)
|
||||
# the output files for HTML help must be .html only
|
||||
# the output files for HTML help is .html by default
|
||||
self.out_suffix = '.html'
|
||||
self.link_suffix = '.html'
|
||||
StandaloneHTMLBuilder.init(self)
|
||||
# determine the correct locale setting
|
||||
locale = chm_locales.get(self.config.language)
|
||||
if locale is not None:
|
||||
@ -207,8 +208,8 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
|
||||
def open_file(self, outdir, basename, mode='w'):
|
||||
# type: (unicode, unicode, unicode) -> IO
|
||||
# open a file with the correct encoding for the selected language
|
||||
return codecs.open(path.join(outdir, basename), mode, # type: ignore
|
||||
self.encoding, 'xmlcharrefreplace')
|
||||
return open(path.join(outdir, basename), mode, # type: ignore
|
||||
encoding=self.encoding, errors='xmlcharrefreplace')
|
||||
|
||||
def update_page_context(self, pagename, templatename, ctx, event_arg):
|
||||
# type: (unicode, unicode, Dict, unicode) -> None
|
||||
@ -341,6 +342,8 @@ def setup(app):
|
||||
app.add_builder(HTMLHelpBuilder)
|
||||
|
||||
app.add_config_value('htmlhelp_basename', lambda self: make_filename(self.project), None)
|
||||
app.add_config_value('htmlhelp_file_suffix', None, 'html', string_classes)
|
||||
app.add_config_value('htmlhelp_link_suffix', None, 'html', string_classes)
|
||||
|
||||
return {
|
||||
'version': 'builtin',
|
||||
|
@ -35,3 +35,12 @@ class math_reference(nodes.Inline, nodes.Referential, nodes.TextElement):
|
||||
class thebibliography(nodes.container):
|
||||
"""A node for wrapping bibliographies."""
|
||||
pass
|
||||
|
||||
|
||||
HYPERLINK_SUPPORT_NODES = (
|
||||
nodes.figure,
|
||||
nodes.literal_block,
|
||||
nodes.table,
|
||||
nodes.section,
|
||||
captioned_literal_block,
|
||||
)
|
||||
|
@ -16,6 +16,7 @@ from sphinx.builders.latex.nodes import (
|
||||
captioned_literal_block, footnotemark, footnotetext, math_reference, thebibliography
|
||||
)
|
||||
from sphinx.transforms import SphinxTransform
|
||||
from sphinx.util.nodes import NodeMatcher
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
@ -30,7 +31,7 @@ class FootnoteDocnameUpdater(SphinxTransform):
|
||||
TARGET_NODES = (nodes.footnote, nodes.footnote_reference)
|
||||
|
||||
def apply(self):
|
||||
for node in self.document.traverse(lambda n: isinstance(n, self.TARGET_NODES)):
|
||||
for node in self.document.traverse(NodeMatcher(*self.TARGET_NODES)):
|
||||
node['docname'] = self.env.docname
|
||||
|
||||
|
||||
@ -536,14 +537,14 @@ class CitationReferenceTransform(SphinxTransform):
|
||||
if self.app.builder.name != 'latex':
|
||||
return
|
||||
|
||||
matcher = NodeMatcher(addnodes.pending_xref, refdomain='std', reftype='citation')
|
||||
citations = self.env.get_domain('std').data['citations']
|
||||
for node in self.document.traverse(addnodes.pending_xref):
|
||||
if node['refdomain'] == 'std' and node['reftype'] == 'citation':
|
||||
docname, labelid, _ = citations.get(node['reftarget'], ('', '', 0))
|
||||
if docname:
|
||||
citation_ref = nodes.citation_reference('', *node.children,
|
||||
docname=docname, refname=labelid)
|
||||
node.replace_self(citation_ref)
|
||||
for node in self.document.traverse(matcher):
|
||||
docname, labelid, _ = citations.get(node['reftarget'], ('', '', 0))
|
||||
if docname:
|
||||
citation_ref = nodes.citation_reference('', *node.children,
|
||||
docname=docname, refname=labelid)
|
||||
node.replace_self(citation_ref)
|
||||
|
||||
|
||||
class MathReferenceTransform(SphinxTransform):
|
||||
@ -577,10 +578,10 @@ class LiteralBlockTransform(SphinxTransform):
|
||||
if self.app.builder.name != 'latex':
|
||||
return
|
||||
|
||||
for node in self.document.traverse(nodes.container):
|
||||
if node.get('literal_block') is True:
|
||||
newnode = captioned_literal_block('', *node.children, **node.attributes)
|
||||
node.replace_self(newnode)
|
||||
matcher = NodeMatcher(nodes.container, literal_block=True)
|
||||
for node in self.document.traverse(matcher):
|
||||
newnode = captioned_literal_block('', *node.children, **node.attributes)
|
||||
node.replace_self(newnode)
|
||||
|
||||
|
||||
class DocumentTargetTransform(SphinxTransform):
|
||||
|
@ -9,7 +9,6 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import codecs
|
||||
import re
|
||||
import socket
|
||||
import threading
|
||||
@ -308,7 +307,8 @@ class CheckExternalLinksBuilder(Builder):
|
||||
|
||||
def write_entry(self, what, docname, line, uri):
|
||||
# type: (unicode, unicode, int, unicode) -> None
|
||||
with codecs.open(path.join(self.outdir, 'output.txt'), 'a', 'utf-8') as output: # type: ignore # NOQA
|
||||
with open(path.join(self.outdir, 'output.txt'), 'a', # type: ignore
|
||||
encoding='utf-8') as output:
|
||||
output.write("%s:%s: [%s] %s\n" % (self.env.doc2path(docname, None),
|
||||
line, what, uri))
|
||||
|
||||
|
@ -73,6 +73,10 @@ class ManualPageBuilder(Builder):
|
||||
|
||||
for info in self.config.man_pages:
|
||||
docname, name, description, authors, section = info
|
||||
if docname not in self.env.all_docs:
|
||||
logger.warning(__('"man_pages" config value references unknown '
|
||||
'document %s'), docname)
|
||||
continue
|
||||
if isinstance(authors, string_types):
|
||||
if authors:
|
||||
authors = [authors]
|
||||
|
@ -9,7 +9,6 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import codecs
|
||||
import os
|
||||
import posixpath
|
||||
import re
|
||||
@ -145,7 +144,8 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
|
||||
nspace = nspace.lower()
|
||||
|
||||
# write the project file
|
||||
with codecs.open(path.join(outdir, outname + '.qhp'), 'w', 'utf-8') as f: # type: ignore # NOQA
|
||||
with open(path.join(outdir, outname + '.qhp'), 'w', # type: ignore
|
||||
encoding='utf-8') as f:
|
||||
body = render_file('project.qhp', outname=outname,
|
||||
title=self.config.html_title, version=self.config.version,
|
||||
project=self.config.project, namespace=nspace,
|
||||
@ -159,7 +159,8 @@ class QtHelpBuilder(StandaloneHTMLBuilder):
|
||||
startpage = 'qthelp://' + posixpath.join(nspace, 'doc', 'index.html')
|
||||
|
||||
logger.info(__('writing collection project file...'))
|
||||
with codecs.open(path.join(outdir, outname + '.qhcp'), 'w', 'utf-8') as f: # type: ignore # NOQA
|
||||
with open(path.join(outdir, outname + '.qhcp'), 'w', # type: ignore
|
||||
encoding='utf-8') as f:
|
||||
body = render_file('project.qhcp', outname=outname,
|
||||
title=self.config.html_short_title,
|
||||
homepage=homepage, startpage=startpage)
|
||||
|
@ -9,7 +9,6 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import codecs
|
||||
from os import path
|
||||
|
||||
from docutils.io import StringOutput
|
||||
@ -51,8 +50,7 @@ class TextBuilder(Builder):
|
||||
if docname not in self.env.all_docs:
|
||||
yield docname
|
||||
continue
|
||||
targetname = self.env.doc2path(docname, self.outdir,
|
||||
self.out_suffix)
|
||||
targetname = path.join(self.outdir, docname + self.out_suffix)
|
||||
try:
|
||||
targetmtime = path.getmtime(targetname)
|
||||
except Exception:
|
||||
@ -82,7 +80,7 @@ class TextBuilder(Builder):
|
||||
outfilename = path.join(self.outdir, os_path(docname) + self.out_suffix)
|
||||
ensuredir(path.dirname(outfilename))
|
||||
try:
|
||||
with codecs.open(outfilename, 'w', 'utf-8') as f: # type: ignore
|
||||
with open(outfilename, 'w', encoding='utf-8') as f: # type: ignore
|
||||
f.write(self.writer.output)
|
||||
except (IOError, OSError) as err:
|
||||
logger.warning(__("error writing file %s: %s"), outfilename, err)
|
||||
|
@ -9,7 +9,6 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import codecs
|
||||
from os import path
|
||||
|
||||
from docutils import nodes
|
||||
@ -54,8 +53,7 @@ class XMLBuilder(Builder):
|
||||
if docname not in self.env.all_docs:
|
||||
yield docname
|
||||
continue
|
||||
targetname = self.env.doc2path(docname, self.outdir,
|
||||
self.out_suffix)
|
||||
targetname = path.join(self.outdir, docname + self.out_suffix)
|
||||
try:
|
||||
targetmtime = path.getmtime(targetname)
|
||||
except Exception:
|
||||
@ -95,7 +93,7 @@ class XMLBuilder(Builder):
|
||||
outfilename = path.join(self.outdir, os_path(docname) + self.out_suffix)
|
||||
ensuredir(path.dirname(outfilename))
|
||||
try:
|
||||
with codecs.open(outfilename, 'w', 'utf-8') as f: # type: ignore
|
||||
with open(outfilename, 'w', encoding='utf-8') as f: # type: ignore
|
||||
f.write(self.writer.output)
|
||||
except (IOError, OSError) as err:
|
||||
logger.warning(__("error writing file %s: %s"), outfilename, err)
|
||||
|
@ -219,7 +219,7 @@ def build_main(argv=sys.argv[1:]): # type: ignore
|
||||
args.confdir = args.sourcedir
|
||||
|
||||
if not args.doctreedir:
|
||||
args.doctreedir = os.path.join(args.sourcedir, '.doctrees')
|
||||
args.doctreedir = os.path.join(args.outputdir, '.doctrees')
|
||||
|
||||
# handle remaining filename arguments
|
||||
filenames = args.filenames
|
||||
|
@ -59,7 +59,7 @@ BUILDERS = [
|
||||
]
|
||||
|
||||
|
||||
class Make(object):
|
||||
class Make:
|
||||
|
||||
def __init__(self, srcdir, builddir, opts):
|
||||
# type: (unicode, unicode, List[unicode]) -> None
|
||||
|
@ -17,8 +17,8 @@ import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import warnings
|
||||
from collections import OrderedDict
|
||||
from io import open
|
||||
from os import path
|
||||
|
||||
# try to import readline, unix specific enhancement
|
||||
@ -26,18 +26,20 @@ try:
|
||||
import readline
|
||||
if readline.__doc__ and 'libedit' in readline.__doc__:
|
||||
readline.parse_and_bind("bind ^I rl_complete")
|
||||
USE_LIBEDIT = True
|
||||
else:
|
||||
readline.parse_and_bind("tab: complete")
|
||||
USE_LIBEDIT = False
|
||||
except ImportError:
|
||||
pass
|
||||
USE_LIBEDIT = False
|
||||
|
||||
from docutils.utils import column_width
|
||||
from six import PY2, PY3, text_type, binary_type
|
||||
from six.moves import input
|
||||
from six import text_type, binary_type
|
||||
from six.moves.urllib.parse import quote as urlquote
|
||||
|
||||
import sphinx.locale
|
||||
from sphinx import __display_version__, package_dir
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import texescape
|
||||
from sphinx.util.console import ( # type: ignore
|
||||
@ -80,6 +82,12 @@ DEFAULTS = {
|
||||
|
||||
PROMPT_PREFIX = '> '
|
||||
|
||||
if sys.platform == 'win32':
|
||||
# On Windows, show questions as bold because of color scheme of PowerShell (refs: #5294).
|
||||
COLOR_QUESTION = 'bold'
|
||||
else:
|
||||
COLOR_QUESTION = 'purple'
|
||||
|
||||
|
||||
# function to get input from terminal -- overridden by the test suite
|
||||
def term_input(prompt):
|
||||
@ -177,21 +185,13 @@ def do_prompt(text, default=None, validator=nonempty):
|
||||
prompt = PROMPT_PREFIX + '%s [%s]: ' % (text, default) # type: unicode
|
||||
else:
|
||||
prompt = PROMPT_PREFIX + text + ': '
|
||||
if PY2:
|
||||
# for Python 2.x, try to get a Unicode string out of it
|
||||
if prompt.encode('ascii', 'replace').decode('ascii', 'replace') \
|
||||
!= prompt:
|
||||
if TERM_ENCODING:
|
||||
prompt = prompt.encode(TERM_ENCODING)
|
||||
else:
|
||||
print(turquoise(__('* Note: non-ASCII default value provided '
|
||||
'and terminal encoding unknown -- assuming '
|
||||
'UTF-8 or Latin-1.')))
|
||||
try:
|
||||
prompt = prompt.encode('utf-8')
|
||||
except UnicodeEncodeError:
|
||||
prompt = prompt.encode('latin1')
|
||||
prompt = colorize('purple', prompt, input_mode=True)
|
||||
if USE_LIBEDIT:
|
||||
# Note: libedit has a problem for combination of ``input()`` and escape
|
||||
# sequence (see #5335). To avoid the problem, all prompts are not colored
|
||||
# on libedit.
|
||||
pass
|
||||
else:
|
||||
prompt = colorize(COLOR_QUESTION, prompt, input_mode=True)
|
||||
x = term_input(prompt).strip()
|
||||
if default and not x:
|
||||
x = default
|
||||
@ -208,10 +208,9 @@ def do_prompt(text, default=None, validator=nonempty):
|
||||
def convert_python_source(source, rex=re.compile(r"[uU]('.*?')")):
|
||||
# type: (unicode, Pattern) -> unicode
|
||||
# remove Unicode literal prefixes
|
||||
if PY3:
|
||||
return rex.sub('\\1', source)
|
||||
else:
|
||||
return source
|
||||
warnings.warn('convert_python_source() is deprecated.',
|
||||
RemovedInSphinx40Warning)
|
||||
return rex.sub('\\1', source)
|
||||
|
||||
|
||||
class QuickstartRenderer(SphinxRenderer):
|
||||
@ -385,7 +384,7 @@ def generate(d, overwrite=True, silent=False, templatedir=None):
|
||||
if 'mastertocmaxdepth' not in d:
|
||||
d['mastertocmaxdepth'] = 2
|
||||
|
||||
d['PY3'] = PY3
|
||||
d['PY3'] = True
|
||||
d['project_fn'] = make_filename(d['project'])
|
||||
d['project_url'] = urlquote(d['project'].encode('idna'))
|
||||
d['project_manpage'] = d['project_fn'].lower()
|
||||
@ -431,7 +430,7 @@ def generate(d, overwrite=True, silent=False, templatedir=None):
|
||||
if overwrite or not path.isfile(fpath):
|
||||
if 'quiet' not in d:
|
||||
print(__('Creating file %s.') % fpath)
|
||||
with open(fpath, 'wt', encoding='utf-8', newline=newline) as f:
|
||||
with open(fpath, 'wt', encoding='utf-8', newline=newline) as f: # type: ignore
|
||||
f.write(content)
|
||||
else:
|
||||
if 'quiet' not in d:
|
||||
@ -441,7 +440,7 @@ def generate(d, overwrite=True, silent=False, templatedir=None):
|
||||
if not conf_path or not path.isfile(conf_path):
|
||||
conf_path = os.path.join(package_dir, 'templates', 'quickstart', 'conf.py_t')
|
||||
with open(conf_path) as f:
|
||||
conf_text = convert_python_source(f.read())
|
||||
conf_text = f.read()
|
||||
|
||||
write_file(path.join(srcdir, 'conf.py'), template.render_string(conf_text, d))
|
||||
|
||||
@ -664,7 +663,7 @@ def main(argv=sys.argv[1:]):
|
||||
except ValueError:
|
||||
print(__('Invalid template variable: %s') % variable)
|
||||
|
||||
generate(d, templatedir=args.templatedir)
|
||||
generate(d, overwrite=False, templatedir=args.templatedir)
|
||||
return 0
|
||||
|
||||
|
||||
|
@ -17,9 +17,7 @@ from collections import OrderedDict
|
||||
from os import path, getenv
|
||||
from typing import Any, NamedTuple, Union
|
||||
|
||||
from six import (
|
||||
PY2, PY3, iteritems, string_types, binary_type, text_type, integer_types, class_types
|
||||
)
|
||||
from six import string_types, binary_type, text_type, integer_types
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||
from sphinx.errors import ConfigError, ExtensionError
|
||||
@ -38,18 +36,30 @@ if False:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
CONFIG_FILENAME = 'conf.py'
|
||||
UNSERIALIZEABLE_TYPES = class_types + (types.ModuleType, types.FunctionType)
|
||||
UNSERIALIZABLE_TYPES = (type, types.ModuleType, types.FunctionType)
|
||||
copyright_year_re = re.compile(r'^((\d{4}-)?)(\d{4})(?=[ ,])')
|
||||
|
||||
if PY3:
|
||||
unicode = str # special alias for static typing...
|
||||
|
||||
ConfigValue = NamedTuple('ConfigValue', [('name', str),
|
||||
('value', Any),
|
||||
('rebuild', Union[bool, unicode])])
|
||||
('rebuild', Union[bool, text_type])])
|
||||
|
||||
|
||||
class ENUM(object):
|
||||
def is_serializable(obj):
|
||||
# type: (Any) -> bool
|
||||
"""Check if object is serializable or not."""
|
||||
if isinstance(obj, UNSERIALIZABLE_TYPES):
|
||||
return False
|
||||
elif isinstance(obj, dict):
|
||||
for key, value in obj.items():
|
||||
if not is_serializable(key) or not is_serializable(value):
|
||||
return False
|
||||
elif isinstance(obj, (list, tuple, set)):
|
||||
return all(is_serializable(i) for i in obj)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class ENUM:
|
||||
"""represents the config value should be a one of candidates.
|
||||
|
||||
Example:
|
||||
@ -68,11 +78,9 @@ class ENUM(object):
|
||||
|
||||
|
||||
string_classes = [text_type] # type: List
|
||||
if PY2:
|
||||
string_classes.append(binary_type) # => [str, unicode]
|
||||
|
||||
|
||||
class Config(object):
|
||||
class Config:
|
||||
"""Configuration file abstraction.
|
||||
|
||||
The config object makes the values of all config values available as
|
||||
@ -104,7 +112,7 @@ class Config(object):
|
||||
locale_dirs = (['locales'], 'env', []),
|
||||
figure_language_filename = (u'{root}.{language}{ext}', 'env', [str]),
|
||||
|
||||
master_doc = ('contents', 'env', []),
|
||||
master_doc = ('index', 'env', []),
|
||||
source_suffix = ({'.rst': 'restructuredtext'}, 'env', Any),
|
||||
source_encoding = ('utf-8-sig', 'env', []),
|
||||
source_parsers = ({}, 'env', []),
|
||||
@ -246,7 +254,7 @@ class Config(object):
|
||||
def init_values(self):
|
||||
# type: () -> None
|
||||
config = self._raw_config
|
||||
for valname, value in iteritems(self.overrides):
|
||||
for valname, value in self.overrides.items():
|
||||
try:
|
||||
if '.' in valname:
|
||||
realvalname, key = valname.split('.', 1)
|
||||
@ -295,7 +303,7 @@ class Config(object):
|
||||
|
||||
def __iter__(self):
|
||||
# type: () -> Generator[ConfigValue, None, None]
|
||||
for name, value in iteritems(self.values):
|
||||
for name, value in self.values.items():
|
||||
yield ConfigValue(name, getattr(self, name), value[1]) # type: ignore
|
||||
|
||||
def add(self, name, default, rebuild, types):
|
||||
@ -316,17 +324,17 @@ class Config(object):
|
||||
"""Obtains serializable data for pickling."""
|
||||
# remove potentially pickling-problematic values from config
|
||||
__dict__ = {}
|
||||
for key, value in iteritems(self.__dict__):
|
||||
if key.startswith('_') or isinstance(value, UNSERIALIZEABLE_TYPES):
|
||||
for key, value in self.__dict__.items():
|
||||
if key.startswith('_') or not is_serializable(value):
|
||||
pass
|
||||
else:
|
||||
__dict__[key] = value
|
||||
|
||||
# create a picklable copy of values list
|
||||
__dict__['values'] = {}
|
||||
for key, value in iteritems(self.values): # type: ignore
|
||||
for key, value in self.values.items(): # type: ignore
|
||||
real_value = getattr(self, key)
|
||||
if isinstance(real_value, UNSERIALIZEABLE_TYPES):
|
||||
if not is_serializable(real_value):
|
||||
# omit unserializable value
|
||||
real_value = None
|
||||
|
||||
@ -352,9 +360,8 @@ def eval_config_file(filename, tags):
|
||||
try:
|
||||
execfile_(filename, namespace)
|
||||
except SyntaxError as err:
|
||||
msg = __("There is a syntax error in your configuration file: %s")
|
||||
if PY3:
|
||||
msg += __("\nDid you change the syntax from 2.x to 3.x?")
|
||||
msg = __("There is a syntax error in your configuration file: %s\n"
|
||||
"Did you change the syntax from 2.x to 3.x?")
|
||||
raise ConfigError(msg % err)
|
||||
except SystemExit:
|
||||
msg = __("The configuration file (or one of the modules it imports) "
|
||||
@ -388,8 +395,8 @@ def convert_source_suffix(app, config):
|
||||
# if dict, convert it to OrderedDict
|
||||
config.source_suffix = OrderedDict(config.source_suffix) # type: ignore
|
||||
else:
|
||||
logger.warning(__("The config value `source_suffix' expected to "
|
||||
"a string, list of strings or dictionary. "
|
||||
logger.warning(__("The config value `source_suffix' expects "
|
||||
"a string, list of strings, or dictionary. "
|
||||
"But `%r' is given." % source_suffix))
|
||||
|
||||
|
||||
@ -456,11 +463,18 @@ def check_confval_types(app, config):
|
||||
continue # at least we share a non-trivial base class
|
||||
|
||||
if annotations:
|
||||
msg = __("The config value `{name}' has type `{current.__name__}', "
|
||||
"expected to {permitted}.")
|
||||
msg = __("The config value `{name}' has type `{current.__name__}'; "
|
||||
"expected {permitted}.")
|
||||
wrapped_annotations = ["`{}'".format(c.__name__) for c in annotations]
|
||||
if len(wrapped_annotations) > 2:
|
||||
permitted = "{}, or {}".format(
|
||||
", ".join(wrapped_annotations[:-1]),
|
||||
wrapped_annotations[-1])
|
||||
else:
|
||||
permitted = " or ".join(wrapped_annotations)
|
||||
logger.warning(msg.format(name=confval.name,
|
||||
current=type(confval.value),
|
||||
permitted=str([c.__name__ for c in annotations])))
|
||||
permitted=permitted))
|
||||
else:
|
||||
msg = __("The config value `{name}' has type `{current.__name__}', "
|
||||
"defaults to `{default.__name__}'.")
|
||||
@ -476,19 +490,28 @@ def check_unicode(config):
|
||||
"""
|
||||
nonascii_re = re.compile(br'[\x80-\xff]')
|
||||
|
||||
for name, value in iteritems(config._raw_config):
|
||||
for name, value in config._raw_config.items():
|
||||
if isinstance(value, binary_type) and nonascii_re.search(value):
|
||||
logger.warning(__('the config value %r is set to a string with non-ASCII '
|
||||
'characters; this can lead to Unicode errors occurring. '
|
||||
'Please use Unicode strings, e.g. %r.'), name, u'Content')
|
||||
|
||||
|
||||
def check_primary_domain(app, config):
|
||||
# type: (Sphinx, Config) -> None
|
||||
primary_domain = config.primary_domain
|
||||
if primary_domain and not app.registry.has_domain(primary_domain):
|
||||
logger.warning(__('primary_domain %r not found, ignored.'), primary_domain)
|
||||
config.primary_domain = None # type: ignore
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[unicode, Any]
|
||||
app.connect('config-inited', convert_source_suffix)
|
||||
app.connect('config-inited', init_numfig_format)
|
||||
app.connect('config-inited', correct_copyright_year)
|
||||
app.connect('config-inited', check_confval_types)
|
||||
app.connect('config-inited', check_primary_domain)
|
||||
|
||||
return {
|
||||
'version': 'builtin',
|
||||
|
@ -17,10 +17,6 @@ if False:
|
||||
from typing import Any, Dict, Type # NOQA
|
||||
|
||||
|
||||
class RemovedInSphinx20Warning(DeprecationWarning):
|
||||
pass
|
||||
|
||||
|
||||
class RemovedInSphinx30Warning(PendingDeprecationWarning):
|
||||
pass
|
||||
|
||||
@ -29,7 +25,7 @@ class RemovedInSphinx40Warning(PendingDeprecationWarning):
|
||||
pass
|
||||
|
||||
|
||||
RemovedInNextVersionWarning = RemovedInSphinx20Warning
|
||||
RemovedInNextVersionWarning = RemovedInSphinx30Warning
|
||||
|
||||
|
||||
class DeprecatedDict(dict):
|
||||
|
@ -233,7 +233,7 @@ class DefaultDomain(SphinxDirective):
|
||||
domain_name = self.arguments[0].lower()
|
||||
# if domain_name not in env.domains:
|
||||
# # try searching by label
|
||||
# for domain in itervalues(env.domains):
|
||||
# for domain in env.domains.values():
|
||||
# if domain.label.lower() == domain_name:
|
||||
# domain_name = domain.name
|
||||
# break
|
||||
|
@ -7,7 +7,6 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import codecs
|
||||
import sys
|
||||
import warnings
|
||||
from difflib import unified_diff
|
||||
@ -177,7 +176,7 @@ class CodeBlock(SphinxDirective):
|
||||
return [literal]
|
||||
|
||||
|
||||
class LiteralIncludeReader(object):
|
||||
class LiteralIncludeReader:
|
||||
INVALID_OPTIONS_PAIR = [
|
||||
('lineno-match', 'lineno-start'),
|
||||
('lineno-match', 'append'),
|
||||
@ -213,7 +212,8 @@ class LiteralIncludeReader(object):
|
||||
def read_file(self, filename, location=None):
|
||||
# type: (unicode, Any) -> List[unicode]
|
||||
try:
|
||||
with codecs.open(filename, 'r', self.encoding, errors='strict') as f: # type: ignore # NOQA
|
||||
with open(filename, 'r', # type: ignore
|
||||
encoding=self.encoding, errors='strict') as f:
|
||||
text = f.read() # type: unicode
|
||||
if 'tab-width' in self.options:
|
||||
text = text.expandtabs(self.options['tab-width'])
|
||||
|
@ -15,14 +15,13 @@ from docutils.parsers.rst import directives
|
||||
from docutils.parsers.rst.directives.admonitions import BaseAdmonition
|
||||
from docutils.parsers.rst.directives.misc import Class
|
||||
from docutils.parsers.rst.directives.misc import Include as BaseInclude
|
||||
from six.moves import range
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.domains.changeset import VersionChange # NOQA # for compatibility
|
||||
from sphinx.locale import _
|
||||
from sphinx.util import url_re, docname_join
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
from sphinx.util.matching import patfilter
|
||||
from sphinx.util.matching import Matcher, patfilter
|
||||
from sphinx.util.nodes import explicit_title_re, set_source_info, \
|
||||
process_index_entry
|
||||
|
||||
@ -96,6 +95,7 @@ class TocTree(SphinxDirective):
|
||||
all_docnames.remove(self.env.docname) # remove current document
|
||||
|
||||
ret = []
|
||||
excluded = Matcher(self.config.exclude_patterns)
|
||||
for entry in self.content:
|
||||
if not entry:
|
||||
continue
|
||||
@ -131,9 +131,13 @@ class TocTree(SphinxDirective):
|
||||
if url_re.match(ref) or ref == 'self':
|
||||
toctree['entries'].append((title, ref))
|
||||
elif docname not in self.env.found_docs:
|
||||
ret.append(self.state.document.reporter.warning(
|
||||
'toctree contains reference to nonexisting '
|
||||
'document %r' % docname, line=self.lineno))
|
||||
if excluded(self.env.doc2path(docname, None)):
|
||||
message = 'toctree contains reference to excluded document %r'
|
||||
else:
|
||||
message = 'toctree contains reference to nonexisting document %r'
|
||||
|
||||
ret.append(self.state.document.reporter.warning(message % docname,
|
||||
line=self.lineno))
|
||||
self.env.note_reread()
|
||||
else:
|
||||
all_docnames.discard(docname)
|
||||
|
@ -12,8 +12,6 @@
|
||||
|
||||
import copy
|
||||
|
||||
from six import iteritems
|
||||
|
||||
from sphinx.errors import SphinxError
|
||||
from sphinx.locale import _
|
||||
|
||||
@ -28,7 +26,7 @@ if False:
|
||||
from sphinx.util.typing import RoleFunction # NOQA
|
||||
|
||||
|
||||
class ObjType(object):
|
||||
class ObjType:
|
||||
"""
|
||||
An ObjType is the description for a type of object that a domain can
|
||||
document. In the object_types attribute of Domain subclasses, object type
|
||||
@ -55,7 +53,7 @@ class ObjType(object):
|
||||
self.attrs.update(attrs)
|
||||
|
||||
|
||||
class Index(object):
|
||||
class Index:
|
||||
"""
|
||||
An Index is the description for a domain-specific index. To add an index to
|
||||
a domain, subclass Index, overriding the three name attributes:
|
||||
@ -113,7 +111,7 @@ class Index(object):
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
class Domain(object):
|
||||
class Domain:
|
||||
"""
|
||||
A Domain is meant to be a group of "object" description directives for
|
||||
objects of a similar nature, and corresponding roles to create references to
|
||||
@ -183,7 +181,7 @@ 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)
|
||||
for name, obj in iteritems(self.object_types):
|
||||
for name, obj in self.object_types.items():
|
||||
for rolename in obj.roles:
|
||||
self._role2type.setdefault(rolename, []).append(name)
|
||||
self._type2role[name] = obj.roles[0] if obj.roles else ''
|
||||
|
@ -12,7 +12,6 @@
|
||||
from typing import NamedTuple
|
||||
|
||||
from docutils import nodes
|
||||
from six import iteritems
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx import locale
|
||||
@ -112,7 +111,7 @@ class ChangeSetDomain(Domain):
|
||||
|
||||
def clear_doc(self, docname):
|
||||
# type: (unicode) -> None
|
||||
for version, changes in iteritems(self.data['changes']):
|
||||
for version, changes in self.data['changes'].items():
|
||||
for changeset in changes[:]:
|
||||
if changeset.docname == docname:
|
||||
changes.remove(changeset)
|
||||
@ -120,7 +119,7 @@ class ChangeSetDomain(Domain):
|
||||
def merge_domaindata(self, docnames, otherdata):
|
||||
# type: (List[unicode], Dict) -> None
|
||||
# XXX duplicates?
|
||||
for version, otherchanges in iteritems(otherdata['changes']):
|
||||
for version, otherchanges in otherdata['changes'].items():
|
||||
changes = self.data['changes'].setdefault(version, [])
|
||||
for changeset in otherchanges:
|
||||
if changeset.docname in docnames:
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,6 @@ import re
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import directives
|
||||
from six import iteritems
|
||||
|
||||
from sphinx import addnodes, locale
|
||||
from sphinx.deprecation import DeprecatedDict, RemovedInSphinx30Warning
|
||||
@ -114,7 +113,7 @@ def _pseudo_parse_arglist(signode, arglist):
|
||||
|
||||
# This override allows our inline type specifiers to behave like :class: link
|
||||
# when it comes to handling "." and "~" prefixes.
|
||||
class PyXrefMixin(object):
|
||||
class PyXrefMixin:
|
||||
def make_xref(self,
|
||||
rolename, # type: unicode
|
||||
domain, # type: unicode
|
||||
@ -536,7 +535,7 @@ class PyClassmember(PyObject):
|
||||
return ''
|
||||
|
||||
|
||||
class PyDecoratorMixin(object):
|
||||
class PyDecoratorMixin:
|
||||
"""
|
||||
Mixin for decorator directives.
|
||||
"""
|
||||
@ -677,7 +676,7 @@ class PythonModuleIndex(Index):
|
||||
ignores = self.domain.env.config['modindex_common_prefix'] # type: ignore
|
||||
ignores = sorted(ignores, key=len, reverse=True)
|
||||
# list of all modules, sorted by module name
|
||||
modules = sorted(iteritems(self.domain.data['modules']),
|
||||
modules = sorted(self.domain.data['modules'].items(),
|
||||
key=lambda x: x[0].lower())
|
||||
# sort out collapsable modules
|
||||
prev_modname = ''
|
||||
@ -727,7 +726,7 @@ class PythonModuleIndex(Index):
|
||||
collapse = len(modules) - num_toplevels < num_toplevels
|
||||
|
||||
# sort by first letter
|
||||
sorted_content = sorted(iteritems(content))
|
||||
sorted_content = sorted(content.items())
|
||||
|
||||
return sorted_content, collapse
|
||||
|
||||
@ -923,9 +922,9 @@ class PythonDomain(Domain):
|
||||
|
||||
def get_objects(self):
|
||||
# type: () -> Iterator[Tuple[unicode, unicode, unicode, unicode, unicode, int]]
|
||||
for modname, info in iteritems(self.data['modules']):
|
||||
for modname, info in self.data['modules'].items():
|
||||
yield (modname, modname, 'module', info[0], 'module-' + modname, 0)
|
||||
for refname, (docname, type) in iteritems(self.data['objects']):
|
||||
for refname, (docname, type) in self.data['objects'].items():
|
||||
if type != 'module': # modules are already handled
|
||||
yield (refname, refname, type, docname, refname, 1)
|
||||
|
||||
|
@ -11,8 +11,6 @@
|
||||
|
||||
import re
|
||||
|
||||
from six import iteritems
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.directives import ObjectDescription
|
||||
from sphinx.domains import Domain, ObjType
|
||||
@ -172,7 +170,7 @@ class ReSTDomain(Domain):
|
||||
|
||||
def get_objects(self):
|
||||
# type: () -> Iterator[Tuple[unicode, unicode, unicode, unicode, unicode, int]]
|
||||
for (typ, name), docname in iteritems(self.data['objects']):
|
||||
for (typ, name), docname in self.data['objects'].items():
|
||||
yield name, name, typ, docname, typ + '-' + name, 1
|
||||
|
||||
|
||||
|
@ -17,7 +17,6 @@ from copy import copy
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import directives
|
||||
from docutils.statemachine import ViewList
|
||||
from six import iteritems
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||
@ -529,7 +528,7 @@ class StandardDomain(Domain):
|
||||
|
||||
# set up enumerable nodes
|
||||
self.enumerable_nodes = copy(self.enumerable_nodes) # create a copy for this instance
|
||||
for node, settings in iteritems(env.app.registry.enumerable_nodes):
|
||||
for node, settings in env.app.registry.enumerable_nodes.items():
|
||||
self.enumerable_nodes[node] = settings
|
||||
|
||||
def clear_doc(self, docname):
|
||||
@ -607,7 +606,7 @@ class StandardDomain(Domain):
|
||||
def note_labels(self, env, docname, document):
|
||||
# type: (BuildEnvironment, unicode, nodes.Node) -> None
|
||||
labels, anonlabels = self.data['labels'], self.data['anonlabels']
|
||||
for name, explicit in iteritems(document.nametypes):
|
||||
for name, explicit in document.nametypes.items():
|
||||
if not explicit:
|
||||
continue
|
||||
labelid = document.nameids[name]
|
||||
@ -647,7 +646,7 @@ class StandardDomain(Domain):
|
||||
|
||||
def check_consistency(self):
|
||||
# type: () -> None
|
||||
for name, (docname, labelid, lineno) in iteritems(self.data['citations']):
|
||||
for name, (docname, labelid, lineno) in self.data['citations'].items():
|
||||
if name not in self.data['citation_refs']:
|
||||
logger.warning(__('Citation [%s] is not referenced.'), name,
|
||||
type='ref', subtype='citation',
|
||||
@ -887,20 +886,20 @@ class StandardDomain(Domain):
|
||||
# handle the special 'doc' reference here
|
||||
for doc in self.env.all_docs:
|
||||
yield (doc, clean_astext(self.env.titles[doc]), 'doc', doc, '', -1)
|
||||
for (prog, option), info in iteritems(self.data['progoptions']):
|
||||
for (prog, option), info in self.data['progoptions'].items():
|
||||
if prog:
|
||||
fullname = ".".join([prog, option])
|
||||
yield (fullname, fullname, 'cmdoption', info[0], info[1], 1)
|
||||
else:
|
||||
yield (option, option, 'cmdoption', info[0], info[1], 1)
|
||||
for (type, name), info in iteritems(self.data['objects']):
|
||||
for (type, name), info in self.data['objects'].items():
|
||||
yield (name, name, type, info[0], info[1],
|
||||
self.object_types[type].attrs['searchprio'])
|
||||
for name, info in iteritems(self.data['labels']):
|
||||
for name, info in self.data['labels'].items():
|
||||
yield (name, info[2], 'label', info[0], info[1], -1)
|
||||
# add anonymous-only labels as well
|
||||
non_anon_labels = set(self.data['labels'])
|
||||
for name, info in iteritems(self.data['anonlabels']):
|
||||
for name, info in self.data['anonlabels'].items():
|
||||
if name not in non_anon_labels:
|
||||
yield (name, name, 'label', info[0], info[1], -1)
|
||||
|
||||
|
@ -10,25 +10,21 @@
|
||||
"""
|
||||
|
||||
import os
|
||||
import re
|
||||
import pickle
|
||||
import sys
|
||||
import warnings
|
||||
from collections import defaultdict
|
||||
from copy import copy
|
||||
from io import BytesIO
|
||||
from os import path
|
||||
|
||||
from docutils.utils import get_source_line
|
||||
from six import BytesIO, next
|
||||
from six.moves import cPickle as pickle
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning, RemovedInSphinx30Warning
|
||||
from sphinx.environment.adapters.indexentries import IndexEntries
|
||||
from sphinx.deprecation import RemovedInSphinx30Warning, RemovedInSphinx40Warning
|
||||
from sphinx.environment.adapters.toctree import TocTree
|
||||
from sphinx.errors import SphinxError, BuildEnvironmentError, DocumentError, ExtensionError
|
||||
from sphinx.locale import __
|
||||
from sphinx.transforms import SphinxTransformer
|
||||
from sphinx.util import get_matching_docs, FilenameUniqDict
|
||||
from sphinx.util import get_matching_docs, DownloadFiles, FilenameUniqDict
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.docutils import LoggingReporter
|
||||
from sphinx.util.i18n import find_catalog_files
|
||||
@ -65,9 +61,7 @@ default_settings = {
|
||||
|
||||
# This is increased every time an environment attribute is added
|
||||
# or changed to properly invalidate pickle files.
|
||||
#
|
||||
# NOTE: increase base version by 2 to have distinct numbers for Py2 and 3
|
||||
ENV_VERSION = 53 + (sys.version_info[0] - 2)
|
||||
ENV_VERSION = 56
|
||||
|
||||
# config status
|
||||
CONFIG_OK = 1
|
||||
@ -94,7 +88,7 @@ class NoUri(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class BuildEnvironment(object):
|
||||
class BuildEnvironment:
|
||||
"""
|
||||
The environment in which the ReST files are translated.
|
||||
Stores an inventory of cross-file targets and provides doctree
|
||||
@ -125,9 +119,6 @@ class BuildEnvironment(object):
|
||||
self.settings = default_settings.copy()
|
||||
self.settings['env'] = self
|
||||
|
||||
# the function to write warning messages with
|
||||
self._warnfunc = None # type: Callable
|
||||
|
||||
# All "docnames" here are /-separated and relative and exclude
|
||||
# the source suffix.
|
||||
|
||||
@ -139,7 +130,8 @@ class BuildEnvironment(object):
|
||||
self.dependencies = defaultdict(set) # type: Dict[unicode, Set[unicode]]
|
||||
# docname -> set of dependent file
|
||||
# names, relative to documentation root
|
||||
self.included = set() # type: Set[unicode]
|
||||
self.included = defaultdict(set) # type: Dict[unicode, Set[unicode]]
|
||||
# docname -> set of included file
|
||||
# docnames included from other documents
|
||||
self.reread_always = set() # type: Set[unicode]
|
||||
# docnames to re-read unconditionally on
|
||||
@ -189,7 +181,8 @@ class BuildEnvironment(object):
|
||||
|
||||
# these map absolute path -> (docnames, unique filename)
|
||||
self.images = FilenameUniqDict() # type: FilenameUniqDict
|
||||
self.dlfiles = FilenameUniqDict() # type: FilenameUniqDict
|
||||
self.dlfiles = DownloadFiles() # type: DownloadFiles
|
||||
# filename -> (set of docnames, destination)
|
||||
|
||||
# the original URI for images
|
||||
self.original_image_uri = {} # type: Dict[unicode, unicode]
|
||||
@ -271,11 +264,6 @@ class BuildEnvironment(object):
|
||||
# Allow to disable by 3rd party extension (workaround)
|
||||
self.settings.setdefault('smart_quotes', True)
|
||||
|
||||
def set_warnfunc(self, func):
|
||||
# type: (Callable) -> None
|
||||
warnings.warn('env.set_warnfunc() is now deprecated. Use sphinx.util.logging instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
|
||||
def set_versioning_method(self, method, compare):
|
||||
# type: (unicode, bool) -> None
|
||||
"""This sets the doctree versioning method for this environment.
|
||||
@ -295,28 +283,13 @@ class BuildEnvironment(object):
|
||||
self.versioning_condition = condition
|
||||
self.versioning_compare = compare
|
||||
|
||||
def warn(self, docname, msg, lineno=None, **kwargs):
|
||||
# type: (unicode, unicode, int, Any) -> None
|
||||
"""Emit a warning.
|
||||
|
||||
This differs from using ``app.warn()`` in that the warning may not
|
||||
be emitted instantly, but collected for emitting all warnings after
|
||||
the update of the environment.
|
||||
"""
|
||||
self.app.warn(msg, location=(docname, lineno), **kwargs) # type: ignore
|
||||
|
||||
def warn_node(self, msg, node, **kwargs):
|
||||
# type: (unicode, nodes.Node, Any) -> None
|
||||
"""Like :meth:`warn`, but with source information taken from *node*."""
|
||||
self._warnfunc(msg, '%s:%s' % get_source_line(node), **kwargs)
|
||||
|
||||
def clear_doc(self, docname):
|
||||
# type: (unicode) -> None
|
||||
"""Remove all traces of a source file in the inventory."""
|
||||
if docname in self.all_docs:
|
||||
self.all_docs.pop(docname, None)
|
||||
self.included.pop(docname, None)
|
||||
self.reread_always.discard(docname)
|
||||
self.included.discard(docname)
|
||||
|
||||
for domain in self.domains.values():
|
||||
domain.clear_doc(docname)
|
||||
@ -331,10 +304,13 @@ class BuildEnvironment(object):
|
||||
docnames = set(docnames) # type: ignore
|
||||
for docname in docnames:
|
||||
self.all_docs[docname] = other.all_docs[docname]
|
||||
self.included[docname] = other.included[docname]
|
||||
if docname in other.reread_always:
|
||||
self.reread_always.add(docname)
|
||||
if docname in other.included:
|
||||
self.included.add(docname)
|
||||
|
||||
for version, changes in other.versionchanges.items():
|
||||
self.versionchanges.setdefault(version, []).extend(
|
||||
change for change in changes if change[1] in docnames)
|
||||
|
||||
for domainname, domain in self.domains.items():
|
||||
domain.merge_domaindata(docnames, other.domaindata[domainname])
|
||||
@ -362,6 +338,13 @@ class BuildEnvironment(object):
|
||||
If *base* is a path string, return absolute path under that.
|
||||
If *suffix* is not None, add it instead of config.source_suffix.
|
||||
"""
|
||||
if suffix:
|
||||
warnings.warn('The suffix argument for doc2path() is deprecated.',
|
||||
RemovedInSphinx40Warning)
|
||||
if base not in (True, None):
|
||||
warnings.warn('The string style base argument for doc2path() is deprecated.',
|
||||
RemovedInSphinx40Warning)
|
||||
|
||||
docname = docname.replace(SEP, path.sep)
|
||||
if suffix is None:
|
||||
# Use first candidate if there is not a file for any suffix
|
||||
@ -461,8 +444,8 @@ class BuildEnvironment(object):
|
||||
added.add(docname)
|
||||
continue
|
||||
# if the doctree file is not there, rebuild
|
||||
if not path.isfile(self.doc2path(docname, self.doctreedir,
|
||||
'.doctree')):
|
||||
filename = path.join(self.doctreedir, docname + '.doctree')
|
||||
if not path.isfile(filename):
|
||||
changed.add(docname)
|
||||
continue
|
||||
# check the "reread always" list
|
||||
@ -551,7 +534,7 @@ class BuildEnvironment(object):
|
||||
|
||||
*filename* should be absolute or relative to the source directory.
|
||||
"""
|
||||
self.included.add(self.path2doc(filename))
|
||||
self.included[self.docname].add(self.path2doc(filename))
|
||||
|
||||
def note_reread(self):
|
||||
# type: () -> None
|
||||
@ -560,32 +543,6 @@ class BuildEnvironment(object):
|
||||
"""
|
||||
self.reread_always.add(self.docname)
|
||||
|
||||
def note_toctree(self, docname, toctreenode):
|
||||
# type: (unicode, addnodes.toctree) -> None
|
||||
"""Note a TOC tree directive in a document and gather information about
|
||||
file relations from it.
|
||||
"""
|
||||
warnings.warn('env.note_toctree() is deprecated. '
|
||||
'Use sphinx.environment.adapters.toctree.TocTree instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
TocTree(self).note(docname, toctreenode)
|
||||
|
||||
def get_toc_for(self, docname, builder):
|
||||
# type: (unicode, Builder) -> Dict[unicode, nodes.Node]
|
||||
"""Return a TOC nodetree -- for use on the same page only!"""
|
||||
warnings.warn('env.get_toc_for() is deprecated. '
|
||||
'Use sphinx.environment.adapters.toctre.TocTree instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
return TocTree(self).get_toc_for(docname, builder)
|
||||
|
||||
def get_toctree_for(self, docname, builder, collapse, **kwds):
|
||||
# type: (unicode, Builder, bool, Any) -> addnodes.toctree
|
||||
"""Return the global TOC nodetree."""
|
||||
warnings.warn('env.get_toctree_for() is deprecated. '
|
||||
'Use sphinx.environment.adapters.toctre.TocTree instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
return TocTree(self).get_toctree_for(docname, builder, collapse, **kwds)
|
||||
|
||||
def get_domain(self, domainname):
|
||||
# type: (unicode) -> Domain
|
||||
"""Return the domain instance with the specified name.
|
||||
@ -602,8 +559,8 @@ class BuildEnvironment(object):
|
||||
def get_doctree(self, docname):
|
||||
# type: (unicode) -> nodes.Node
|
||||
"""Read the doctree for a file from the pickle and return it."""
|
||||
doctree_filename = self.doc2path(docname, self.doctreedir, '.doctree')
|
||||
with open(doctree_filename, 'rb') as f:
|
||||
filename = path.join(self.doctreedir, docname + '.doctree')
|
||||
with open(filename, 'rb') as f:
|
||||
doctree = pickle.load(f)
|
||||
doctree.settings.env = self
|
||||
doctree.reporter = LoggingReporter(self.doc2path(docname))
|
||||
@ -673,16 +630,6 @@ class BuildEnvironment(object):
|
||||
# allow custom references to be resolved
|
||||
self.app.emit('doctree-resolved', doctree, docname)
|
||||
|
||||
def create_index(self, builder, group_entries=True,
|
||||
_fixre=re.compile(r'(.*) ([(][^()]*[)])')):
|
||||
# type: (Builder, bool, Pattern) -> List[Tuple[unicode, List[Tuple[unicode, List[unicode]]]]] # NOQA
|
||||
warnings.warn('env.create_index() is deprecated. '
|
||||
'Use sphinx.environment.adapters.indexentreis.IndexEntries instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
return IndexEntries(self).create_index(builder,
|
||||
group_entries=group_entries,
|
||||
_fixre=_fixre)
|
||||
|
||||
def collect_relations(self):
|
||||
# type: () -> Dict[unicode, List[unicode]]
|
||||
traversed = set()
|
||||
@ -720,12 +667,13 @@ class BuildEnvironment(object):
|
||||
def check_consistency(self):
|
||||
# type: () -> None
|
||||
"""Do consistency checks."""
|
||||
included = set().union(*self.included.values()) # type: ignore
|
||||
for docname in sorted(self.all_docs):
|
||||
if docname not in self.files_to_rebuild:
|
||||
if docname == self.config.master_doc:
|
||||
# the master file is not included anywhere ;)
|
||||
continue
|
||||
if docname in self.included:
|
||||
if docname in included:
|
||||
# the document is included from other documents
|
||||
continue
|
||||
if 'orphan' in self.metadata[docname]:
|
||||
@ -798,7 +746,7 @@ class BuildEnvironment(object):
|
||||
|
||||
@classmethod
|
||||
def loads(cls, string, app=None):
|
||||
# type: (unicode, Sphinx) -> BuildEnvironment
|
||||
# type: (bytes, Sphinx) -> BuildEnvironment
|
||||
warnings.warn('BuildEnvironment.loads() is deprecated. '
|
||||
'Please use pickle.loads() instead.',
|
||||
RemovedInSphinx30Warning)
|
||||
|
@ -14,7 +14,7 @@ if False:
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
|
||||
|
||||
class ImageAdapter(object):
|
||||
class ImageAdapter:
|
||||
def __init__(self, env):
|
||||
# type: (BuildEnvironment) -> None
|
||||
self.env = env
|
||||
|
@ -13,7 +13,7 @@ import re
|
||||
import unicodedata
|
||||
from itertools import groupby
|
||||
|
||||
from six import text_type, iteritems
|
||||
from six import text_type
|
||||
|
||||
from sphinx.locale import _, __
|
||||
from sphinx.util import split_into, logging
|
||||
@ -27,7 +27,7 @@ if False:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class IndexEntries(object):
|
||||
class IndexEntries:
|
||||
def __init__(self, env):
|
||||
# type: (BuildEnvironment) -> None
|
||||
self.env = env
|
||||
@ -60,7 +60,7 @@ class IndexEntries(object):
|
||||
# maintain links in sorted/deterministic order
|
||||
bisect.insort(entry[0], (main, uri))
|
||||
|
||||
for fn, entries in iteritems(self.env.indexentries):
|
||||
for fn, entries in self.env.indexentries.items():
|
||||
# new entry types must be listed in directives/other.py!
|
||||
for type, value, tid, main, index_key in entries:
|
||||
try:
|
||||
@ -146,7 +146,7 @@ class IndexEntries(object):
|
||||
# type: (Tuple[unicode, List]) -> unicode
|
||||
# hack: mutating the subitems dicts to a list in the keyfunc
|
||||
k, v = item
|
||||
v[1] = sorted((si, se) for (si, (se, void, void)) in iteritems(v[1]))
|
||||
v[1] = sorted((si, se) for (si, (se, void, void)) in v[1].items())
|
||||
if v[2] is None:
|
||||
# now calculate the key
|
||||
if k.startswith(u'\N{RIGHT-TO-LEFT MARK}'):
|
||||
|
@ -10,11 +10,11 @@
|
||||
"""
|
||||
|
||||
from docutils import nodes
|
||||
from six import iteritems
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import url_re, logging
|
||||
from sphinx.util.matching import Matcher
|
||||
from sphinx.util.nodes import clean_astext, process_only_nodes
|
||||
|
||||
if False:
|
||||
@ -26,7 +26,7 @@ if False:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TocTree(object):
|
||||
class TocTree:
|
||||
def __init__(self, env):
|
||||
# type: (BuildEnvironment) -> None
|
||||
self.env = env
|
||||
@ -83,6 +83,7 @@ class TocTree(object):
|
||||
# interactions between marking and pruning the tree (see bug #1046).
|
||||
|
||||
toctree_ancestors = self.get_toctree_ancestors(docname)
|
||||
excluded = Matcher(self.env.config.exclude_patterns)
|
||||
|
||||
def _toctree_add_classes(node, depth):
|
||||
# type: (nodes.Node, int) -> None
|
||||
@ -172,8 +173,12 @@ class TocTree(object):
|
||||
ref, location=toctreenode)
|
||||
except KeyError:
|
||||
# this is raised if the included file does not exist
|
||||
logger.warning(__('toctree contains reference to nonexisting document %r'),
|
||||
ref, location=toctreenode)
|
||||
if excluded(self.env.doc2path(ref, None)):
|
||||
message = __('toctree contains reference to excluded document %r')
|
||||
else:
|
||||
message = __('toctree contains reference to nonexisting document %r')
|
||||
|
||||
logger.warning(message, ref, location=toctreenode)
|
||||
else:
|
||||
# if titles_only is given, only keep the main title and
|
||||
# sub-toctrees
|
||||
@ -255,7 +260,7 @@ class TocTree(object):
|
||||
def get_toctree_ancestors(self, docname):
|
||||
# type: (unicode) -> List[unicode]
|
||||
parent = {}
|
||||
for p, children in iteritems(self.env.toctree_includes):
|
||||
for p, children in self.env.toctree_includes.items():
|
||||
for child in children:
|
||||
parent[child] = p
|
||||
ancestors = [] # type: List[unicode]
|
||||
|
@ -9,8 +9,6 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from six import itervalues
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Dict, List, Set # NOQA
|
||||
@ -19,7 +17,7 @@ if False:
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
|
||||
|
||||
class EnvironmentCollector(object):
|
||||
class EnvironmentCollector:
|
||||
"""An EnvironmentCollector is a specific data collector from each document.
|
||||
|
||||
It gathers data and stores :py:class:`BuildEnvironment
|
||||
@ -44,7 +42,7 @@ class EnvironmentCollector(object):
|
||||
def disable(self, app):
|
||||
# type: (Sphinx) -> None
|
||||
assert self.listener_ids is not None
|
||||
for listener_id in itervalues(self.listener_ids):
|
||||
for listener_id in self.listener_ids.values():
|
||||
app.disconnect(listener_id)
|
||||
self.listener_ids = None
|
||||
|
||||
|
@ -15,7 +15,6 @@ from os import path
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.utils import relative_path
|
||||
from six import iteritems, itervalues
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.environment.collectors import EnvironmentCollector
|
||||
@ -87,7 +86,7 @@ class ImageCollector(EnvironmentCollector):
|
||||
|
||||
# map image paths to unique image names (so that they can be put
|
||||
# into a single directory)
|
||||
for imgpath in itervalues(candidates):
|
||||
for imgpath in candidates.values():
|
||||
app.env.dependencies[docname].add(imgpath)
|
||||
if not os.access(path.join(app.srcdir, imgpath), os.R_OK):
|
||||
logger.warning(__('image file not readable: %s') % imgpath,
|
||||
@ -108,7 +107,7 @@ class ImageCollector(EnvironmentCollector):
|
||||
except (OSError, IOError) as err:
|
||||
logger.warning(__('image file %s not readable: %s') % (filename, err),
|
||||
location=node, type='image', subtype='not_readable')
|
||||
for key, files in iteritems(globbed):
|
||||
for key, files in globbed.items():
|
||||
candidates[key] = sorted(files, key=len)[0] # select by similarity
|
||||
|
||||
|
||||
@ -128,13 +127,16 @@ class DownloadFileCollector(EnvironmentCollector):
|
||||
"""Process downloadable file paths. """
|
||||
for node in doctree.traverse(addnodes.download_reference):
|
||||
targetname = node['reftarget']
|
||||
rel_filename, filename = app.env.relfn2path(targetname, app.env.docname)
|
||||
app.env.dependencies[app.env.docname].add(rel_filename)
|
||||
if not os.access(filename, os.R_OK):
|
||||
logger.warning(__('download file not readable: %s') % filename,
|
||||
location=node, type='download', subtype='not_readable')
|
||||
continue
|
||||
node['filename'] = app.env.dlfiles.add_file(app.env.docname, filename)
|
||||
if '://' in targetname:
|
||||
node['refuri'] = targetname
|
||||
else:
|
||||
rel_filename, filename = app.env.relfn2path(targetname, app.env.docname)
|
||||
app.env.dependencies[app.env.docname].add(rel_filename)
|
||||
if not os.access(filename, os.R_OK):
|
||||
logger.warning(__('download file not readable: %s') % filename,
|
||||
location=node, type='download', subtype='not_readable')
|
||||
continue
|
||||
node['filename'] = app.env.dlfiles.add_file(app.env.docname, filename)
|
||||
|
||||
|
||||
def setup(app):
|
||||
|
@ -9,12 +9,13 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import os
|
||||
from os import path
|
||||
|
||||
from docutils.utils import relative_path
|
||||
|
||||
from sphinx.environment.collectors import EnvironmentCollector
|
||||
from sphinx.util.osutil import getcwd, fs_encoding
|
||||
from sphinx.util.osutil import fs_encoding
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
@ -40,7 +41,7 @@ class DependenciesCollector(EnvironmentCollector):
|
||||
def process_doc(self, app, doctree):
|
||||
# type: (Sphinx, nodes.Node) -> None
|
||||
"""Process docutils-generated dependency info."""
|
||||
cwd = getcwd()
|
||||
cwd = os.getcwd()
|
||||
frompath = path.join(path.normpath(app.srcdir), 'dummy')
|
||||
deps = doctree.settings.record_dependencies
|
||||
if not deps:
|
||||
|
@ -50,11 +50,7 @@ class IndexEntriesCollector(EnvironmentCollector):
|
||||
node.parent.remove(node)
|
||||
else:
|
||||
for entry in node['entries']:
|
||||
if len(entry) == 5:
|
||||
# Since 1.4: new index structure including index_key (5th column)
|
||||
entries.append(entry)
|
||||
else:
|
||||
entries.append(entry + (None,))
|
||||
entries.append(entry)
|
||||
|
||||
|
||||
def setup(app):
|
||||
|
@ -10,7 +10,6 @@
|
||||
"""
|
||||
|
||||
from docutils import nodes
|
||||
from six import iteritems
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.environment.adapters.toctree import TocTree
|
||||
@ -295,7 +294,7 @@ class TocTreeCollector(EnvironmentCollector):
|
||||
|
||||
if env.config.numfig:
|
||||
_walk_doc(env.config.master_doc, tuple()) # type: ignore
|
||||
for docname, fignums in iteritems(env.toc_fignumbers):
|
||||
for docname, fignums in env.toc_fignumbers.items():
|
||||
if fignums != old_fignumbers.get(docname):
|
||||
rewrite_needed.append(docname)
|
||||
|
||||
|
@ -55,6 +55,7 @@ class ExtensionError(SphinxError):
|
||||
def __init__(self, message, orig_exc=None):
|
||||
# type: (unicode, Exception) -> None
|
||||
SphinxError.__init__(self, message)
|
||||
self.message = message
|
||||
self.orig_exc = orig_exc
|
||||
|
||||
def __repr__(self):
|
||||
|
@ -14,8 +14,6 @@ from __future__ import print_function
|
||||
|
||||
from collections import OrderedDict, defaultdict
|
||||
|
||||
from six import itervalues
|
||||
|
||||
from sphinx.errors import ExtensionError
|
||||
from sphinx.locale import __
|
||||
|
||||
@ -45,7 +43,7 @@ core_events = {
|
||||
} # type: Dict[unicode, unicode]
|
||||
|
||||
|
||||
class EventManager(object):
|
||||
class EventManager:
|
||||
def __init__(self):
|
||||
# type: () -> None
|
||||
self.events = core_events.copy()
|
||||
@ -70,13 +68,13 @@ class EventManager(object):
|
||||
|
||||
def disconnect(self, listener_id):
|
||||
# type: (int) -> None
|
||||
for event in itervalues(self.listeners):
|
||||
for event in self.listeners.values():
|
||||
event.pop(listener_id, None)
|
||||
|
||||
def emit(self, name, *args):
|
||||
# type: (unicode, Any) -> List
|
||||
results = []
|
||||
for callback in itervalues(self.listeners[name]):
|
||||
for callback in self.listeners[name].values():
|
||||
results.append(callback(*args))
|
||||
return results
|
||||
|
||||
|
@ -32,7 +32,7 @@ from sphinx import __display_version__, package_dir
|
||||
from sphinx.cmd.quickstart import EXTENSIONS
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import rst
|
||||
from sphinx.util.osutil import FileAvoidWrite, ensuredir, walk
|
||||
from sphinx.util.osutil import FileAvoidWrite, ensuredir
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
@ -235,7 +235,7 @@ def recurse_tree(rootpath, excludes, opts):
|
||||
root_package = None
|
||||
|
||||
toplevels = []
|
||||
for root, subs, files in walk(rootpath, followlinks=followlinks):
|
||||
for root, subs, files in os.walk(rootpath, followlinks=followlinks):
|
||||
# document only Python module files (that aren't excluded)
|
||||
py_files = sorted(f for f in files
|
||||
if path.splitext(f)[1] in PY_SUFFIXES and
|
||||
@ -340,7 +340,9 @@ Note: By default this script will not overwrite already created files."""))
|
||||
parser.add_argument('-P', '--private', action='store_true',
|
||||
dest='includeprivate',
|
||||
help=__('include "_private" modules'))
|
||||
parser.add_argument('-T', '--no-toc', action='store_true', dest='notoc',
|
||||
parser.add_argument('--tocfile', action='store', dest='tocfile', default='modules',
|
||||
help=__("don't create a table of contents file"))
|
||||
parser.add_argument('-T', '--no-toc', action='store_false', dest='tocfile',
|
||||
help=__("don't create a table of contents file"))
|
||||
parser.add_argument('-E', '--no-headings', action='store_true',
|
||||
dest='noheadings',
|
||||
@ -453,8 +455,8 @@ def main(argv=sys.argv[1:]):
|
||||
|
||||
if not args.dryrun:
|
||||
qs.generate(d, silent=True, overwrite=args.force)
|
||||
elif not args.notoc:
|
||||
create_modules_toc_file(modules, args)
|
||||
elif args.tocfile:
|
||||
create_modules_toc_file(modules, args, args.tocfile)
|
||||
|
||||
return 0
|
||||
|
||||
|
@ -15,16 +15,15 @@ import inspect
|
||||
import re
|
||||
import sys
|
||||
import warnings
|
||||
from typing import Any
|
||||
|
||||
from docutils.statemachine import ViewList
|
||||
from six import iteritems, itervalues, text_type, class_types, string_types
|
||||
from six import text_type, string_types
|
||||
|
||||
import sphinx
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.errors import ExtensionError
|
||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||
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.locale import _, __
|
||||
from sphinx.pycode import ModuleAnalyzer, PycodeError
|
||||
from sphinx.util import logging
|
||||
@ -32,7 +31,7 @@ from sphinx.util import rpartition, force_decode
|
||||
from sphinx.util.docstrings import prepare_docstring
|
||||
from sphinx.util.inspect import Signature, isdescriptor, safe_getmembers, \
|
||||
safe_getattr, object_description, is_builtin_class_method, \
|
||||
isenumattribute, isclassmethod, isstaticmethod, getdoc
|
||||
isenumattribute, isclassmethod, isstaticmethod, isfunction, isbuiltin, ispartial, getdoc
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
@ -41,6 +40,7 @@ if False:
|
||||
from docutils import nodes # NOQA
|
||||
from docutils.utils import Reporter # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.config import Config # NOQA
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
from sphinx.ext.autodoc.directive import DocumenterBridge # NOQA
|
||||
|
||||
@ -108,56 +108,18 @@ def bool_option(arg):
|
||||
return True
|
||||
|
||||
|
||||
class AutodocReporter(object):
|
||||
"""
|
||||
A reporter replacement that assigns the correct source name
|
||||
and line number to a system message, as recorded in a ViewList.
|
||||
"""
|
||||
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
|
||||
|
||||
def __getattr__(self, name):
|
||||
# type: (unicode) -> Any
|
||||
return getattr(self.reporter, name)
|
||||
|
||||
def system_message(self, level, message, *children, **kwargs):
|
||||
# type: (int, unicode, Any, Any) -> nodes.system_message
|
||||
if 'line' in kwargs and 'source' not in kwargs:
|
||||
try:
|
||||
source, line = self.viewlist.items[kwargs['line']]
|
||||
except IndexError:
|
||||
pass
|
||||
else:
|
||||
kwargs['source'] = source
|
||||
kwargs['line'] = line
|
||||
return self.reporter.system_message(level, message,
|
||||
*children, **kwargs)
|
||||
|
||||
def debug(self, *args, **kwargs):
|
||||
# type: (Any, Any) -> nodes.system_message
|
||||
if self.reporter.debug_flag:
|
||||
return self.system_message(0, *args, **kwargs)
|
||||
|
||||
def info(self, *args, **kwargs):
|
||||
# type: (Any, Any) -> nodes.system_message
|
||||
return self.system_message(1, *args, **kwargs)
|
||||
|
||||
def warning(self, *args, **kwargs):
|
||||
# type: (Any, Any) -> nodes.system_message
|
||||
return self.system_message(2, *args, **kwargs)
|
||||
|
||||
def error(self, *args, **kwargs):
|
||||
# type: (Any, Any) -> nodes.system_message
|
||||
return self.system_message(3, *args, **kwargs)
|
||||
|
||||
def severe(self, *args, **kwargs):
|
||||
# type: (Any, Any) -> nodes.system_message
|
||||
return self.system_message(4, *args, **kwargs)
|
||||
def merge_special_members_option(options):
|
||||
# type: (Dict) -> None
|
||||
"""Merge :special-members: option to :members: option."""
|
||||
if 'special-members' in options and options['special-members'] is not ALL:
|
||||
if options.get('members') is ALL:
|
||||
pass
|
||||
elif options.get('members'):
|
||||
for member in options['special-members']:
|
||||
if member not in options['members']:
|
||||
options['members'].append(member)
|
||||
else:
|
||||
options['members'] = options['special-members']
|
||||
|
||||
|
||||
# Some useful event listener factories for autodoc-process-docstring.
|
||||
@ -239,7 +201,7 @@ class Options(dict):
|
||||
return None
|
||||
|
||||
|
||||
class Documenter(object):
|
||||
class Documenter:
|
||||
"""
|
||||
A Documenter knows how to autodocument a single object type. When
|
||||
registered with the AutoDirective, it will be used to document objects
|
||||
@ -340,7 +302,8 @@ class Documenter(object):
|
||||
explicit_modname, path, base, args, retann = \
|
||||
py_ext_sig_re.match(self.name).groups() # type: ignore
|
||||
except AttributeError:
|
||||
logger.warning(__('invalid signature for auto%s (%r)') % (self.objtype, self.name))
|
||||
logger.warning(__('invalid signature for auto%s (%r)') % (self.objtype, self.name),
|
||||
type='autodoc')
|
||||
return False
|
||||
|
||||
# support explicit module and class name separation via ::
|
||||
@ -377,7 +340,7 @@ class Documenter(object):
|
||||
self.module, self.parent, self.object_name, self.object = ret
|
||||
return True
|
||||
except ImportError as exc:
|
||||
logger.warning(exc.args[0])
|
||||
logger.warning(exc.args[0], type='autodoc', subtype='import_object')
|
||||
self.env.note_reread()
|
||||
return False
|
||||
|
||||
@ -399,7 +362,9 @@ class Documenter(object):
|
||||
return True
|
||||
|
||||
modname = self.get_attr(self.object, '__module__', None)
|
||||
if modname and modname != self.modname:
|
||||
if ispartial(self.object) and modname == '_functools': # for pypy
|
||||
return True
|
||||
elif modname and modname != self.modname:
|
||||
return False
|
||||
return True
|
||||
|
||||
@ -438,7 +403,7 @@ class Documenter(object):
|
||||
args = self.format_args()
|
||||
except Exception as err:
|
||||
logger.warning(__('error while formatting arguments for %s: %s') %
|
||||
(self.fullname, err))
|
||||
(self.fullname, err), type='autodoc')
|
||||
args = None
|
||||
|
||||
retann = self.retann
|
||||
@ -473,9 +438,8 @@ class Documenter(object):
|
||||
def get_doc(self, encoding=None, ignore=1):
|
||||
# type: (unicode, int) -> List[List[unicode]]
|
||||
"""Decode and return lines of the docstring(s) for the object."""
|
||||
docstring = self.get_attr(self.object, '__doc__', None)
|
||||
if docstring is None and self.env.config.autodoc_inherit_docstrings:
|
||||
docstring = getdoc(self.object)
|
||||
docstring = getdoc(self.object, self.get_attr,
|
||||
self.env.config.autodoc_inherit_docstrings)
|
||||
# make sure we have Unicode docstrings, then sanitize and split
|
||||
# into lines
|
||||
if isinstance(docstring, text_type):
|
||||
@ -561,12 +525,12 @@ class Documenter(object):
|
||||
selected.append((name, members[name].value))
|
||||
else:
|
||||
logger.warning(__('missing attribute %s in object %s') %
|
||||
(name, self.fullname))
|
||||
(name, self.fullname), type='autodoc')
|
||||
return False, sorted(selected)
|
||||
elif self.options.inherited_members:
|
||||
return False, sorted((m.name, m.value) for m in itervalues(members))
|
||||
return False, sorted((m.name, m.value) for m in members.values())
|
||||
else:
|
||||
return False, sorted((m.name, m.value) for m in itervalues(members)
|
||||
return False, sorted((m.name, m.value) for m in members.values()
|
||||
if m.directly_defined)
|
||||
|
||||
def filter_members(self, members, want_all):
|
||||
@ -599,9 +563,7 @@ class Documenter(object):
|
||||
# if isattr is True, the member is documented as an attribute
|
||||
isattr = False
|
||||
|
||||
doc = self.get_attr(member, '__doc__', None)
|
||||
if doc is None and self.env.config.autodoc_inherit_docstrings:
|
||||
doc = getdoc(member)
|
||||
doc = getdoc(member, self.get_attr, self.env.config.autodoc_inherit_docstrings)
|
||||
|
||||
# if the member __doc__ is the same as self's __doc__, it's just
|
||||
# inherited and therefore not the member's doc
|
||||
@ -652,7 +614,7 @@ class Documenter(object):
|
||||
except Exception as exc:
|
||||
logger.warning(__('autodoc: failed to determine %r to be documented.'
|
||||
'the following exception was raised:\n%s'),
|
||||
member, exc)
|
||||
member, exc, type='autodoc')
|
||||
keep = False
|
||||
|
||||
if keep:
|
||||
@ -679,13 +641,18 @@ class Documenter(object):
|
||||
|
||||
# remove members given by exclude-members
|
||||
if self.options.exclude_members:
|
||||
members = [(membername, member) for (membername, member) in members
|
||||
if membername not in self.options.exclude_members]
|
||||
members = [
|
||||
(membername, member) for (membername, member) in members
|
||||
if (
|
||||
self.options.exclude_members is ALL or
|
||||
membername not in self.options.exclude_members
|
||||
)
|
||||
]
|
||||
|
||||
# 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(self.documenters)
|
||||
classes = [cls for cls in self.documenters.values()
|
||||
if cls.can_document_member(member, mname, isattr, self)]
|
||||
if not classes:
|
||||
# don't know how to document this member
|
||||
@ -740,7 +707,7 @@ class Documenter(object):
|
||||
__('don\'t know which module to import for autodocumenting '
|
||||
'%r (try placing a "module" or "currentmodule" directive '
|
||||
'in the document, or giving an explicit module name)') %
|
||||
self.name)
|
||||
self.name, type='autodoc')
|
||||
return
|
||||
|
||||
# now, import the module and get object to document
|
||||
@ -817,6 +784,11 @@ class ModuleDocumenter(Documenter):
|
||||
'imported-members': bool_option, 'ignore-module-all': bool_option
|
||||
} # type: Dict[unicode, Callable]
|
||||
|
||||
def __init__(self, *args):
|
||||
# type: (Any) -> None
|
||||
super(ModuleDocumenter, self).__init__(*args)
|
||||
merge_special_members_option(self.options)
|
||||
|
||||
@classmethod
|
||||
def can_document_member(cls, member, membername, isattr, parent):
|
||||
# type: (Any, unicode, bool, Any) -> bool
|
||||
@ -826,7 +798,8 @@ class ModuleDocumenter(Documenter):
|
||||
def resolve_name(self, modname, parents, path, base):
|
||||
# type: (str, Any, str, Any) -> Tuple[str, List[unicode]]
|
||||
if modname is not None:
|
||||
logger.warning(__('"::" in automodule name doesn\'t make sense'))
|
||||
logger.warning(__('"::" in automodule name doesn\'t make sense'),
|
||||
type='autodoc')
|
||||
return (path or '') + base, []
|
||||
|
||||
def parse_name(self):
|
||||
@ -834,7 +807,8 @@ class ModuleDocumenter(Documenter):
|
||||
ret = Documenter.parse_name(self)
|
||||
if self.args or self.retann:
|
||||
logger.warning(__('signature arguments or return annotation '
|
||||
'given for automodule %s') % self.fullname)
|
||||
'given for automodule %s') % self.fullname,
|
||||
type='autodoc')
|
||||
return ret
|
||||
|
||||
def add_directive_header(self, sig):
|
||||
@ -869,7 +843,9 @@ class ModuleDocumenter(Documenter):
|
||||
logger.warning(
|
||||
__('__all__ should be a list of strings, not %r '
|
||||
'(in module %s) -- ignoring __all__') %
|
||||
(memberlist, self.fullname))
|
||||
(memberlist, self.fullname),
|
||||
type='autodoc'
|
||||
)
|
||||
# fall back to all members
|
||||
return True, safe_getmembers(self.object)
|
||||
else:
|
||||
@ -882,7 +858,9 @@ class ModuleDocumenter(Documenter):
|
||||
logger.warning(
|
||||
__('missing attribute mentioned in :members: or __all__: '
|
||||
'module %s, attribute %s') %
|
||||
(safe_getattr(self.object, '__name__', '???'), mname))
|
||||
(safe_getattr(self.object, '__name__', '???'), mname),
|
||||
type='autodoc'
|
||||
)
|
||||
return False, ret
|
||||
|
||||
|
||||
@ -940,7 +918,7 @@ class ClassLevelDocumenter(Documenter):
|
||||
return modname, parents + [base]
|
||||
|
||||
|
||||
class DocstringSignatureMixin(object):
|
||||
class DocstringSignatureMixin:
|
||||
"""
|
||||
Mixin for FunctionDocumenter and MethodDocumenter to provide the
|
||||
feature of reading the signature from the docstring.
|
||||
@ -1022,16 +1000,21 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
|
||||
@classmethod
|
||||
def can_document_member(cls, member, membername, isattr, parent):
|
||||
# type: (Any, unicode, bool, Any) -> bool
|
||||
return inspect.isfunction(member) or inspect.isbuiltin(member)
|
||||
return isfunction(member) or isbuiltin(member)
|
||||
|
||||
def format_args(self):
|
||||
# type: () -> unicode
|
||||
if inspect.isbuiltin(self.object) or \
|
||||
inspect.ismethoddescriptor(self.object):
|
||||
if isbuiltin(self.object) or inspect.ismethoddescriptor(self.object):
|
||||
# cannot introspect arguments of a C function or method
|
||||
return None
|
||||
try:
|
||||
args = Signature(self.object).format_args()
|
||||
if (not isfunction(self.object) and
|
||||
not isbuiltin(self.object) and
|
||||
not inspect.isclass(self.object) and
|
||||
hasattr(self.object, '__call__')):
|
||||
args = Signature(self.object.__call__).format_args()
|
||||
else:
|
||||
args = Signature(self.object).format_args()
|
||||
except TypeError:
|
||||
if (is_builtin_class_method(self.object, '__new__') and
|
||||
is_builtin_class_method(self.object, '__init__')):
|
||||
@ -1070,10 +1053,15 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
||||
'private-members': bool_option, 'special-members': members_option,
|
||||
} # type: Dict[unicode, Callable]
|
||||
|
||||
def __init__(self, *args):
|
||||
# type: (Any) -> None
|
||||
super(ClassDocumenter, self).__init__(*args)
|
||||
merge_special_members_option(self.options)
|
||||
|
||||
@classmethod
|
||||
def can_document_member(cls, member, membername, isattr, parent):
|
||||
# type: (Any, unicode, bool, Any) -> bool
|
||||
return isinstance(member, class_types)
|
||||
return isinstance(member, type)
|
||||
|
||||
def import_object(self):
|
||||
# type: () -> Any
|
||||
@ -1095,7 +1083,7 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
|
||||
# __init__ written in C?
|
||||
if initmeth is None or \
|
||||
is_builtin_class_method(self.object, '__init__') or \
|
||||
not(inspect.ismethod(initmeth) or inspect.isfunction(initmeth)):
|
||||
not(inspect.ismethod(initmeth) or isfunction(initmeth)):
|
||||
return None
|
||||
try:
|
||||
return Signature(initmeth, bound_method=True, has_retval=False).format_args()
|
||||
@ -1225,8 +1213,7 @@ class ExceptionDocumenter(ClassDocumenter):
|
||||
@classmethod
|
||||
def can_document_member(cls, member, membername, isattr, parent):
|
||||
# type: (Any, unicode, bool, Any) -> bool
|
||||
return isinstance(member, class_types) and \
|
||||
issubclass(member, BaseException) # type: ignore
|
||||
return isinstance(member, type) and issubclass(member, BaseException)
|
||||
|
||||
|
||||
class DataDocumenter(ModuleLevelDocumenter):
|
||||
@ -1310,8 +1297,7 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
|
||||
|
||||
def format_args(self):
|
||||
# type: () -> unicode
|
||||
if inspect.isbuiltin(self.object) or \
|
||||
inspect.ismethoddescriptor(self.object):
|
||||
if isbuiltin(self.object) or inspect.ismethoddescriptor(self.object):
|
||||
# can never get arguments of a C function or method
|
||||
return None
|
||||
if isstaticmethod(self.object, cls=self.parent, name=self.object_name):
|
||||
@ -1343,7 +1329,7 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
|
||||
@staticmethod
|
||||
def is_function_or_method(obj):
|
||||
# type: (Any) -> bool
|
||||
return inspect.isfunction(obj) or inspect.isbuiltin(obj) or inspect.ismethod(obj)
|
||||
return isfunction(obj) or isbuiltin(obj) or inspect.ismethod(obj)
|
||||
|
||||
@classmethod
|
||||
def can_document_member(cls, member, membername, isattr, parent):
|
||||
@ -1358,7 +1344,7 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
|
||||
# exported anywhere by Python
|
||||
return isdatadesc or (not isinstance(parent, ModuleDocumenter) and
|
||||
not inspect.isroutine(member) and
|
||||
not isinstance(member, class_types))
|
||||
not isinstance(member, type))
|
||||
|
||||
def document_members(self, all_members=False):
|
||||
# type: (bool) -> None
|
||||
@ -1441,93 +1427,46 @@ class InstanceAttributeDocumenter(AttributeDocumenter):
|
||||
AttributeDocumenter.add_content(self, more_content, no_docstring=True)
|
||||
|
||||
|
||||
class DeprecatedDict(dict):
|
||||
def __init__(self, message):
|
||||
# type: (str) -> None
|
||||
self.message = message
|
||||
super(DeprecatedDict, self).__init__()
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
# type: (unicode, Any) -> None
|
||||
warnings.warn(self.message, RemovedInSphinx20Warning)
|
||||
super(DeprecatedDict, self).__setitem__(key, value)
|
||||
|
||||
def setdefault(self, key, default=None):
|
||||
# type: (unicode, Any) -> None
|
||||
warnings.warn(self.message, RemovedInSphinx20Warning)
|
||||
super(DeprecatedDict, self).setdefault(key, default)
|
||||
|
||||
def update(self, other=None): # type: ignore
|
||||
# type: (Dict) -> 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 (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 = DeprecatedDict(
|
||||
'AutoDirective._special_attrgetters has been deprecated. '
|
||||
'Please use app.add_autodoc_attrgetter() instead.'
|
||||
) # type: Dict[Type, Callable]
|
||||
|
||||
|
||||
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)
|
||||
# actually, it should be possible to override Documenters
|
||||
# if cls.objtype in AutoDirective._registry:
|
||||
# raise ExtensionError('autodoc documenter for %r is already '
|
||||
# 'registered' % cls.objtype)
|
||||
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
|
||||
return app.registry.documenters
|
||||
|
||||
|
||||
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):
|
||||
for typ, func in app.registry.autodoc_attrgettrs.items():
|
||||
if isinstance(obj, typ):
|
||||
return func(obj, name, *defargs)
|
||||
|
||||
return safe_getattr(obj, name, *defargs)
|
||||
|
||||
|
||||
def merge_autodoc_default_flags(app, config):
|
||||
# type: (Sphinx, Config) -> None
|
||||
"""This merges the autodoc_default_flags to autodoc_default_options."""
|
||||
if not config.autodoc_default_flags:
|
||||
return
|
||||
|
||||
# Note: this option will be removed in Sphinx-4.0. But I marked this as
|
||||
# RemovedInSphinx *30* Warning because we have to emit warnings for users
|
||||
# who will be still in use with Sphinx-3.x. So we should replace this by
|
||||
# logger.warning() on 3.0.0 release.
|
||||
warnings.warn('autodoc_default_flags is now deprecated. '
|
||||
'Please use autodoc_default_options instead.',
|
||||
RemovedInSphinx30Warning)
|
||||
|
||||
for option in config.autodoc_default_flags:
|
||||
if isinstance(option, string_types):
|
||||
config.autodoc_default_options[option] = None
|
||||
else:
|
||||
logger.warning(
|
||||
__("Ignoring invalid option in autodoc_default_flags: %r"),
|
||||
option, type='autodoc'
|
||||
)
|
||||
|
||||
|
||||
def setup(app):
|
||||
# type: (Sphinx) -> Dict[unicode, Any]
|
||||
app.add_autodocumenter(ModuleDocumenter)
|
||||
@ -1542,6 +1481,7 @@ def setup(app):
|
||||
app.add_config_value('autoclass_content', 'class', True)
|
||||
app.add_config_value('autodoc_member_order', 'alphabetic', True)
|
||||
app.add_config_value('autodoc_default_flags', [], True)
|
||||
app.add_config_value('autodoc_default_options', {}, True)
|
||||
app.add_config_value('autodoc_docstring_signature', True, True)
|
||||
app.add_config_value('autodoc_mock_imports', [], True)
|
||||
app.add_config_value('autodoc_warningiserror', True, True)
|
||||
@ -1550,4 +1490,6 @@ def setup(app):
|
||||
app.add_event('autodoc-process-signature')
|
||||
app.add_event('autodoc-skip-member')
|
||||
|
||||
app.connect('config-inited', merge_autodoc_default_flags)
|
||||
|
||||
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
|
||||
|
@ -31,10 +31,10 @@ 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']
|
||||
'ignore-module-all', 'exclude-members']
|
||||
|
||||
|
||||
class DummyOptionSpec(object):
|
||||
class DummyOptionSpec:
|
||||
"""An option_spec allows any options."""
|
||||
|
||||
def __getitem__(self, key):
|
||||
@ -42,7 +42,7 @@ class DummyOptionSpec(object):
|
||||
return lambda x: x
|
||||
|
||||
|
||||
class DocumenterBridge(object):
|
||||
class DocumenterBridge:
|
||||
"""A parameters container for Documenters."""
|
||||
|
||||
def __init__(self, env, reporter, options, lineno):
|
||||
@ -67,8 +67,8 @@ def process_documenter_options(documenter, config, options):
|
||||
continue
|
||||
else:
|
||||
negated = options.pop('no-' + name, True) is None
|
||||
if name in config.autodoc_default_flags and not negated:
|
||||
options[name] = None
|
||||
if name in config.autodoc_default_options and not negated:
|
||||
options[name] = config.autodoc_default_options[name]
|
||||
|
||||
return Options(assemble_option_dict(options.items(), documenter.option_spec))
|
||||
|
||||
|
@ -16,8 +16,6 @@ import warnings
|
||||
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
|
||||
|
||||
@ -28,7 +26,7 @@ if False:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class _MockObject(object):
|
||||
class _MockObject:
|
||||
"""Used by autodoc_mock_imports."""
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
@ -93,7 +91,7 @@ class _MockModule(ModuleType):
|
||||
return o
|
||||
|
||||
|
||||
class _MockImporter(object):
|
||||
class _MockImporter:
|
||||
def __init__(self, names):
|
||||
# type: (List[str]) -> None
|
||||
self.names = names
|
||||
@ -168,13 +166,15 @@ def import_object(modname, objpath, objtype='', attrgetter=safe_getattr, warning
|
||||
|
||||
try:
|
||||
module = None
|
||||
exc_on_importing = None
|
||||
objpath = list(objpath)
|
||||
while module is None:
|
||||
try:
|
||||
module = import_module(modname, warningiserror=warningiserror)
|
||||
logger.debug('[autodoc] import %s => %r', modname, module)
|
||||
except ImportError:
|
||||
except ImportError as exc:
|
||||
logger.debug('[autodoc] import %s => failed', modname)
|
||||
exc_on_importing = exc
|
||||
if '.' in modname:
|
||||
# retry with parent module
|
||||
modname, name = modname.rsplit('.', 1)
|
||||
@ -193,6 +193,10 @@ def import_object(modname, objpath, objtype='', attrgetter=safe_getattr, warning
|
||||
object_name = attrname
|
||||
return [module, parent, object_name, obj]
|
||||
except (AttributeError, ImportError) as exc:
|
||||
if isinstance(exc, AttributeError) and exc_on_importing:
|
||||
# restore ImportError
|
||||
exc = exc_on_importing
|
||||
|
||||
if objpath:
|
||||
errmsg = ('autodoc: failed to import %s %r from module %r' %
|
||||
(objtype, '.'.join(objpath), modname))
|
||||
@ -213,8 +217,6 @@ def import_object(modname, objpath, objtype='', attrgetter=safe_getattr, warning
|
||||
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)
|
||||
|
||||
@ -228,12 +230,6 @@ def get_object_members(subject, objpath, attrgetter, analyzer=None):
|
||||
# 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 = {} # type: Dict[str, Attribute]
|
||||
|
||||
# enum members
|
||||
@ -242,6 +238,11 @@ def get_object_members(subject, objpath, attrgetter, analyzer=None):
|
||||
if name not in members:
|
||||
members[name] = Attribute(name, True, value)
|
||||
|
||||
superclass = subject.__mro__[1]
|
||||
for name, value in obj_dict.items():
|
||||
if name not in superclass.__dict__:
|
||||
members[name] = Attribute(name, True, value)
|
||||
|
||||
# other members
|
||||
for name in dir(subject):
|
||||
try:
|
||||
|
@ -1,184 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
sphinx.ext.autodoc.inspector
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Inspect utilities for autodoc
|
||||
|
||||
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import typing
|
||||
import warnings
|
||||
|
||||
from six import StringIO, string_types
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.util.inspect import object_description
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Callable, Dict, Tuple # NOQA
|
||||
|
||||
|
||||
def format_annotation(annotation):
|
||||
# type: (Any) -> str
|
||||
"""Return formatted representation of a type annotation.
|
||||
|
||||
Show qualified names for types and additional details for types from
|
||||
the ``typing`` module.
|
||||
|
||||
Displaying complex types from ``typing`` relies on its private API.
|
||||
"""
|
||||
warnings.warn('format_annotation() is now deprecated. '
|
||||
'Please use sphinx.util.inspect.Signature instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
if isinstance(annotation, typing.TypeVar): # type: ignore
|
||||
return annotation.__name__
|
||||
if annotation == Ellipsis:
|
||||
return '...'
|
||||
if not isinstance(annotation, type):
|
||||
return repr(annotation)
|
||||
|
||||
qualified_name = (annotation.__module__ + '.' + annotation.__qualname__ # type: ignore
|
||||
if annotation else repr(annotation))
|
||||
|
||||
if annotation.__module__ == 'builtins':
|
||||
return annotation.__qualname__ # type: ignore
|
||||
else:
|
||||
if hasattr(typing, 'GenericMeta') and \
|
||||
isinstance(annotation, typing.GenericMeta):
|
||||
# In Python 3.5.2+, all arguments are stored in __args__,
|
||||
# whereas __parameters__ only contains generic parameters.
|
||||
#
|
||||
# Prior to Python 3.5.2, __args__ is not available, and all
|
||||
# arguments are in __parameters__.
|
||||
params = None
|
||||
if hasattr(annotation, '__args__'):
|
||||
if annotation.__args__ is None or len(annotation.__args__) <= 2: # type: ignore # NOQA
|
||||
params = annotation.__args__ # type: ignore
|
||||
else: # typing.Callable
|
||||
args = ', '.join(format_annotation(a) for a in annotation.__args__[:-1]) # type: ignore # NOQA
|
||||
result = format_annotation(annotation.__args__[-1]) # type: ignore
|
||||
return '%s[[%s], %s]' % (qualified_name, args, result)
|
||||
elif hasattr(annotation, '__parameters__'):
|
||||
params = annotation.__parameters__ # type: ignore
|
||||
if params is not None:
|
||||
param_str = ', '.join(format_annotation(p) for p in params)
|
||||
return '%s[%s]' % (qualified_name, param_str)
|
||||
elif (hasattr(typing, 'UnionMeta') and
|
||||
isinstance(annotation, typing.UnionMeta) and # type: ignore
|
||||
hasattr(annotation, '__union_params__')):
|
||||
params = annotation.__union_params__
|
||||
if params is not None:
|
||||
param_str = ', '.join(format_annotation(p) for p in params)
|
||||
return '%s[%s]' % (qualified_name, param_str)
|
||||
elif (hasattr(typing, 'CallableMeta') and
|
||||
isinstance(annotation, typing.CallableMeta) and # type: ignore
|
||||
getattr(annotation, '__args__', None) is not None and
|
||||
hasattr(annotation, '__result__')):
|
||||
# Skipped in the case of plain typing.Callable
|
||||
args = annotation.__args__
|
||||
if args is None:
|
||||
return qualified_name
|
||||
elif args is Ellipsis:
|
||||
args_str = '...'
|
||||
else:
|
||||
formatted_args = (format_annotation(a) for a in args)
|
||||
args_str = '[%s]' % ', '.join(formatted_args)
|
||||
return '%s[%s, %s]' % (qualified_name,
|
||||
args_str,
|
||||
format_annotation(annotation.__result__))
|
||||
elif (hasattr(typing, 'TupleMeta') and
|
||||
isinstance(annotation, typing.TupleMeta) and # type: ignore
|
||||
hasattr(annotation, '__tuple_params__') and
|
||||
hasattr(annotation, '__tuple_use_ellipsis__')):
|
||||
params = annotation.__tuple_params__
|
||||
if params is not None:
|
||||
param_strings = [format_annotation(p) for p in params]
|
||||
if annotation.__tuple_use_ellipsis__:
|
||||
param_strings.append('...')
|
||||
return '%s[%s]' % (qualified_name,
|
||||
', '.join(param_strings))
|
||||
return qualified_name
|
||||
|
||||
|
||||
def formatargspec(function, args, varargs=None, varkw=None, defaults=None,
|
||||
kwonlyargs=(), kwonlydefaults={}, annotations={}):
|
||||
# type: (Callable, Tuple[str, ...], str, str, Any, Tuple, Dict, Dict[str, Any]) -> str
|
||||
"""Return a string representation of an ``inspect.FullArgSpec`` tuple.
|
||||
|
||||
An enhanced version of ``inspect.formatargspec()`` that handles typing
|
||||
annotations better.
|
||||
"""
|
||||
warnings.warn('formatargspec() is now deprecated. '
|
||||
'Please use sphinx.util.inspect.Signature instead.',
|
||||
RemovedInSphinx20Warning)
|
||||
|
||||
def format_arg_with_annotation(name):
|
||||
# type: (str) -> str
|
||||
if name in annotations:
|
||||
return '%s: %s' % (name, format_annotation(get_annotation(name)))
|
||||
return name
|
||||
|
||||
def get_annotation(name):
|
||||
# type: (str) -> str
|
||||
value = annotations[name]
|
||||
if isinstance(value, string_types):
|
||||
return introspected_hints.get(name, value)
|
||||
else:
|
||||
return value
|
||||
|
||||
introspected_hints = (typing.get_type_hints(function) # type: ignore
|
||||
if typing and hasattr(function, '__code__') else {})
|
||||
|
||||
fd = StringIO()
|
||||
fd.write('(')
|
||||
|
||||
formatted = []
|
||||
defaults_start = len(args) - len(defaults) if defaults else len(args)
|
||||
|
||||
for i, arg in enumerate(args):
|
||||
arg_fd = StringIO()
|
||||
if isinstance(arg, list):
|
||||
# support tupled arguments list (only for py2): def foo((x, y))
|
||||
arg_fd.write('(')
|
||||
arg_fd.write(format_arg_with_annotation(arg[0]))
|
||||
for param in arg[1:]:
|
||||
arg_fd.write(', ')
|
||||
arg_fd.write(format_arg_with_annotation(param))
|
||||
arg_fd.write(')')
|
||||
else:
|
||||
arg_fd.write(format_arg_with_annotation(arg))
|
||||
if defaults and i >= defaults_start:
|
||||
arg_fd.write(' = ' if arg in annotations else '=')
|
||||
arg_fd.write(object_description(defaults[i - defaults_start])) # type: ignore
|
||||
formatted.append(arg_fd.getvalue())
|
||||
|
||||
if varargs:
|
||||
formatted.append('*' + format_arg_with_annotation(varargs))
|
||||
|
||||
if kwonlyargs:
|
||||
if not varargs:
|
||||
formatted.append('*')
|
||||
|
||||
for kwarg in kwonlyargs:
|
||||
arg_fd = StringIO()
|
||||
arg_fd.write(format_arg_with_annotation(kwarg))
|
||||
if kwonlydefaults and kwarg in kwonlydefaults:
|
||||
arg_fd.write(' = ' if kwarg in annotations else '=')
|
||||
arg_fd.write(object_description(kwonlydefaults[kwarg])) # type: ignore
|
||||
formatted.append(arg_fd.getvalue())
|
||||
|
||||
if varkw:
|
||||
formatted.append('**' + format_arg_with_annotation(varkw))
|
||||
|
||||
fd.write(', '.join(formatted))
|
||||
fd.write(')')
|
||||
|
||||
if 'return' in annotations:
|
||||
fd.write(' -> ')
|
||||
fd.write(format_annotation(get_annotation('return')))
|
||||
|
||||
return fd.getvalue()
|
@ -58,7 +58,6 @@ import os
|
||||
import posixpath
|
||||
import re
|
||||
import sys
|
||||
import warnings
|
||||
from types import ModuleType
|
||||
|
||||
from docutils import nodes
|
||||
@ -70,7 +69,6 @@ from six import text_type
|
||||
|
||||
import sphinx
|
||||
from sphinx import addnodes
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.environment.adapters.toctree import TocTree
|
||||
from sphinx.ext.autodoc import get_documenters
|
||||
from sphinx.ext.autodoc.directive import DocumenterBridge, Options
|
||||
@ -81,6 +79,7 @@ from sphinx.util import import_object, rst, logging
|
||||
from sphinx.util.docutils import (
|
||||
NullReporter, SphinxDirective, new_document, switch_source_input
|
||||
)
|
||||
from sphinx.util.matching import Matcher
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
@ -175,8 +174,8 @@ class FakeDirective(DocumenterBridge):
|
||||
super(FakeDirective, self).__init__({}, None, Options(), 0) # type: ignore
|
||||
|
||||
|
||||
def get_documenter(*args):
|
||||
# type: (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.
|
||||
|
||||
@ -185,16 +184,6 @@ def get_documenter(*args):
|
||||
belongs to.
|
||||
"""
|
||||
from sphinx.ext.autodoc import DataDocumenter, ModuleDocumenter
|
||||
if len(args) == 3:
|
||||
# new style arguments: (app, obj, parent)
|
||||
app, obj, parent = args
|
||||
else:
|
||||
# old style arguments: (obj, parent)
|
||||
app = _app
|
||||
obj, parent = args
|
||||
warnings.warn('the interface of get_documenter() has been changed. '
|
||||
'Please give application object as first argument.',
|
||||
RemovedInSphinx20Warning)
|
||||
|
||||
if inspect.ismodule(obj):
|
||||
# ModuleDocumenter.can_document_member always returns False
|
||||
@ -261,12 +250,17 @@ class Autosummary(SphinxDirective):
|
||||
|
||||
tree_prefix = self.options['toctree'].strip()
|
||||
docnames = []
|
||||
excluded = Matcher(self.config.exclude_patterns)
|
||||
for name, sig, summary, real_name in items:
|
||||
docname = posixpath.join(tree_prefix, real_name)
|
||||
docname = posixpath.normpath(posixpath.join(dirname, docname))
|
||||
if docname not in self.env.found_docs:
|
||||
self.warn('toctree references unknown document %r'
|
||||
% docname)
|
||||
if excluded(self.env.doc2path(docname, None)):
|
||||
self.warn('toctree references excluded document %r'
|
||||
% docname)
|
||||
else:
|
||||
self.warn('toctree references unknown document %r'
|
||||
% docname)
|
||||
docnames.append(docname)
|
||||
|
||||
tocnode = addnodes.toctree()
|
||||
|
@ -20,7 +20,6 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import argparse
|
||||
import codecs
|
||||
import locale
|
||||
import os
|
||||
import pydoc
|
||||
@ -43,14 +42,15 @@ from sphinx.util.rst import escape as rst_escape
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Callable, Dict, Tuple, List # NOQA
|
||||
from typing import Any, Callable, Dict, List, Tuple, Type # NOQA
|
||||
from jinja2 import BaseLoader # NOQA
|
||||
from sphinx import addnodes # NOQA
|
||||
from sphinx.builders import Builder # NOQA
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
from sphinx.ext.autodoc import Documenter # NOQA
|
||||
|
||||
|
||||
class DummyApplication(object):
|
||||
class DummyApplication:
|
||||
"""Dummy Application class for sphinx-autogen command."""
|
||||
|
||||
def __init__(self):
|
||||
@ -69,7 +69,7 @@ def setup_documenters(app):
|
||||
ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter,
|
||||
FunctionDocumenter, MethodDocumenter, AttributeDocumenter,
|
||||
InstanceAttributeDocumenter
|
||||
]
|
||||
] # type: List[Type[Documenter]]
|
||||
for documenter in documenters:
|
||||
app.registry.add_documenter(documenter.objtype, documenter)
|
||||
|
||||
@ -248,8 +248,8 @@ def find_autosummary_in_files(filenames):
|
||||
"""
|
||||
documented = [] # type: List[Tuple[unicode, unicode, unicode]]
|
||||
for filename in filenames:
|
||||
with codecs.open(filename, 'r', encoding='utf-8', # type: ignore
|
||||
errors='ignore') as f:
|
||||
with open(filename, 'r', encoding='utf-8', # type: ignore
|
||||
errors='ignore') as f:
|
||||
lines = f.read().splitlines()
|
||||
documented.extend(find_autosummary_in_lines(lines, filename=filename))
|
||||
return documented
|
||||
|
@ -12,12 +12,10 @@
|
||||
|
||||
import glob
|
||||
import inspect
|
||||
import pickle
|
||||
import re
|
||||
from os import path
|
||||
|
||||
from six import iteritems
|
||||
from six.moves import cPickle as pickle
|
||||
|
||||
import sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.locale import __
|
||||
@ -73,7 +71,7 @@ class CoverageBuilder(Builder):
|
||||
logger.warning(__('invalid regex %r in coverage_c_regexes'), exp)
|
||||
|
||||
self.c_ignorexps = {} # type: Dict[unicode, List[Pattern]]
|
||||
for (name, exps) in iteritems(self.config.coverage_ignore_c_items):
|
||||
for (name, exps) in self.config.coverage_ignore_c_items.items():
|
||||
self.c_ignorexps[name] = compile_regex_list('coverage_ignore_c_items',
|
||||
exps)
|
||||
self.mod_ignorexps = compile_regex_list('coverage_ignore_modules',
|
||||
@ -127,7 +125,7 @@ class CoverageBuilder(Builder):
|
||||
write_header(op, 'Undocumented C API elements', '=')
|
||||
op.write('\n')
|
||||
|
||||
for filename, undoc in iteritems(self.c_undoc):
|
||||
for filename, undoc in self.c_undoc.items():
|
||||
write_header(op, filename)
|
||||
for typ, name in sorted(undoc):
|
||||
op.write(' * %-50s [%9s]\n' % (name, typ))
|
||||
@ -247,7 +245,7 @@ class CoverageBuilder(Builder):
|
||||
if undoc['classes']:
|
||||
op.write('Classes:\n')
|
||||
for name, methods in sorted(
|
||||
iteritems(undoc['classes'])):
|
||||
undoc['classes'].items()):
|
||||
if not methods:
|
||||
op.write(' * %s\n' % name)
|
||||
else:
|
||||
|
@ -11,27 +11,28 @@
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
|
||||
import codecs
|
||||
import doctest
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
import warnings
|
||||
from os import path
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import directives
|
||||
from packaging.specifiers import SpecifierSet, InvalidSpecifier
|
||||
from packaging.version import Version
|
||||
from six import itervalues, StringIO, binary_type, text_type, PY2
|
||||
from six import StringIO, binary_type
|
||||
|
||||
import sphinx
|
||||
from sphinx.builders import Builder
|
||||
from sphinx.deprecation import RemovedInSphinx40Warning
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import force_decode, logging
|
||||
from sphinx.util.console import bold # type: ignore
|
||||
from sphinx.util.docutils import SphinxDirective
|
||||
from sphinx.util.nodes import set_source_info
|
||||
from sphinx.util.osutil import fs_encoding, relpath
|
||||
from sphinx.util.osutil import relpath
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
@ -43,18 +44,12 @@ logger = logging.getLogger(__name__)
|
||||
blankline_re = re.compile(r'^\s*<BLANKLINE>', re.MULTILINE)
|
||||
doctestopt_re = re.compile(r'#\s*doctest:.+$', re.MULTILINE)
|
||||
|
||||
if PY2:
|
||||
def doctest_encode(text, encoding):
|
||||
# type: (str, unicode) -> unicode
|
||||
if isinstance(text, text_type):
|
||||
text = text.encode(encoding)
|
||||
if text.startswith(codecs.BOM_UTF8):
|
||||
text = text[len(codecs.BOM_UTF8):]
|
||||
return text
|
||||
else:
|
||||
def doctest_encode(text, encoding):
|
||||
# type: (unicode, unicode) -> unicode
|
||||
return text
|
||||
|
||||
def doctest_encode(text, encoding):
|
||||
# type: (unicode, unicode) -> unicode
|
||||
warnings.warn('doctest_encode() is deprecated.',
|
||||
RemovedInSphinx40Warning)
|
||||
return text
|
||||
|
||||
|
||||
def is_allowed_version(spec, version):
|
||||
@ -90,6 +85,16 @@ class TestDirective(SphinxDirective):
|
||||
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
if 'skipif' in self.options:
|
||||
condition = self.options['skipif']
|
||||
context = {} # type: Dict[str, Any]
|
||||
if self.config.doctest_global_setup:
|
||||
exec(self.config.doctest_global_setup, context)
|
||||
should_skip = eval(condition, context)
|
||||
if self.config.doctest_global_cleanup:
|
||||
exec(self.config.doctest_global_cleanup, context)
|
||||
if should_skip:
|
||||
return []
|
||||
# use ordinary docutils nodes for test code: they get special attributes
|
||||
# so that our builder recognizes them, and the other builders are happy.
|
||||
code = '\n'.join(self.content)
|
||||
@ -143,7 +148,7 @@ class TestDirective(SphinxDirective):
|
||||
if self.name == 'doctest' and 'pyversion' in self.options:
|
||||
try:
|
||||
spec = self.options['pyversion']
|
||||
python_version = '.'.join(str(v) for v in sys.version_info[:3])
|
||||
python_version = '.'.join([str(v) for v in sys.version_info[:3]])
|
||||
if not is_allowed_version(spec, python_version):
|
||||
flag = doctest.OPTIONFLAGS_BY_NAME['SKIP']
|
||||
node['options'][flag] = True # Skip the test
|
||||
@ -155,11 +160,11 @@ class TestDirective(SphinxDirective):
|
||||
|
||||
|
||||
class TestsetupDirective(TestDirective):
|
||||
option_spec = {} # type: Dict
|
||||
option_spec = {'skipif': directives.unchanged_required} # type: Dict
|
||||
|
||||
|
||||
class TestcleanupDirective(TestDirective):
|
||||
option_spec = {} # type: Dict
|
||||
option_spec = {'skipif': directives.unchanged_required} # type: Dict
|
||||
|
||||
|
||||
class DoctestDirective(TestDirective):
|
||||
@ -167,6 +172,7 @@ class DoctestDirective(TestDirective):
|
||||
'hide': directives.flag,
|
||||
'options': directives.unchanged,
|
||||
'pyversion': directives.unchanged_required,
|
||||
'skipif': directives.unchanged_required,
|
||||
}
|
||||
|
||||
|
||||
@ -174,6 +180,7 @@ class TestcodeDirective(TestDirective):
|
||||
option_spec = {
|
||||
'hide': directives.flag,
|
||||
'pyversion': directives.unchanged_required,
|
||||
'skipif': directives.unchanged_required,
|
||||
}
|
||||
|
||||
|
||||
@ -182,6 +189,7 @@ class TestoutputDirective(TestDirective):
|
||||
'hide': directives.flag,
|
||||
'options': directives.unchanged,
|
||||
'pyversion': directives.unchanged_required,
|
||||
'skipif': directives.unchanged_required,
|
||||
}
|
||||
|
||||
|
||||
@ -190,7 +198,7 @@ parser = doctest.DocTestParser()
|
||||
|
||||
# helper classes
|
||||
|
||||
class TestGroup(object):
|
||||
class TestGroup:
|
||||
def __init__(self, name):
|
||||
# type: (unicode) -> None
|
||||
self.name = name
|
||||
@ -223,7 +231,7 @@ class TestGroup(object):
|
||||
self.name, self.setup, self.cleanup, self.tests)
|
||||
|
||||
|
||||
class TestCode(object):
|
||||
class TestCode:
|
||||
def __init__(self, code, type, filename, lineno, options=None):
|
||||
# type: (unicode, unicode, Optional[str], int, Optional[Dict]) -> None
|
||||
self.code = code
|
||||
@ -305,8 +313,8 @@ class DocTestBuilder(Builder):
|
||||
date = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||
|
||||
self.outfile = None # type: IO
|
||||
self.outfile = codecs.open(path.join(self.outdir, 'output.txt'), # type: ignore
|
||||
'w', encoding='utf-8')
|
||||
self.outfile = open(path.join(self.outdir, 'output.txt'), # type: ignore
|
||||
'w', encoding='utf-8')
|
||||
self.outfile.write(('Results of doctest builder run on %s\n'
|
||||
'==================================%s\n') %
|
||||
(date, '=' * len(date)))
|
||||
@ -369,7 +377,7 @@ Doctest summary
|
||||
self.test_doc(docname, doctree)
|
||||
|
||||
def get_filename_for_node(self, node, docname):
|
||||
# type: (nodes.Node, unicode) -> str
|
||||
# type: (nodes.Node, unicode) -> unicode
|
||||
"""Try to get the file which actually contains the doctest, not the
|
||||
filename of the document it's included in."""
|
||||
try:
|
||||
@ -377,8 +385,6 @@ Doctest summary
|
||||
.rsplit(':docstring of ', maxsplit=1)[0]
|
||||
except Exception:
|
||||
filename = self.env.doc2path(docname, base=None)
|
||||
if PY2:
|
||||
return filename.encode(fs_encoding)
|
||||
return filename
|
||||
|
||||
@staticmethod
|
||||
@ -431,7 +437,7 @@ Doctest summary
|
||||
logger.warning(__('no code/output in %s block at %s:%s'),
|
||||
node.get('testnodetype', 'doctest'),
|
||||
filename, line_number)
|
||||
code = TestCode(source, type=node.get('testnodetype', 'doctest'),
|
||||
code = TestCode(source, type=node.get('testnodetype', 'doctest'), # type: ignore
|
||||
filename=filename, lineno=line_number,
|
||||
options=node.get('options'))
|
||||
node_groups = node.get('groups', ['default'])
|
||||
@ -443,24 +449,24 @@ Doctest summary
|
||||
groups[groupname] = TestGroup(groupname)
|
||||
groups[groupname].add_code(code)
|
||||
for code in add_to_all_groups:
|
||||
for group in itervalues(groups):
|
||||
for group in groups.values():
|
||||
group.add_code(code)
|
||||
if self.config.doctest_global_setup:
|
||||
code = TestCode(self.config.doctest_global_setup,
|
||||
'testsetup', filename=None, lineno=0)
|
||||
for group in itervalues(groups):
|
||||
for group in groups.values():
|
||||
group.add_code(code, prepend=True)
|
||||
if self.config.doctest_global_cleanup:
|
||||
code = TestCode(self.config.doctest_global_cleanup,
|
||||
'testcleanup', filename=None, lineno=0)
|
||||
for group in itervalues(groups):
|
||||
for group in groups.values():
|
||||
group.add_code(code)
|
||||
if not groups:
|
||||
return
|
||||
|
||||
self._out('\nDocument: %s\n----------%s\n' %
|
||||
(docname, '-' * len(docname)))
|
||||
for group in itervalues(groups):
|
||||
for group in groups.values():
|
||||
self.test_group(group)
|
||||
# Separately count results from setup code
|
||||
res_f, res_t = self.setup_runner.summarize(self._out, verbose=False)
|
||||
@ -488,9 +494,9 @@ Doctest summary
|
||||
# type: (Any, List[TestCode], Any) -> bool
|
||||
examples = []
|
||||
for testcode in testcodes:
|
||||
examples.append(doctest.Example( # type: ignore
|
||||
doctest_encode(testcode.code, self.env.config.source_encoding), '', # type: ignore # NOQA
|
||||
lineno=testcode.lineno))
|
||||
example = doctest.Example(testcode.code, '', # type: ignore
|
||||
lineno=testcode.lineno)
|
||||
examples.append(example)
|
||||
if not examples:
|
||||
return True
|
||||
# simulate a doctest with the code
|
||||
@ -515,9 +521,8 @@ Doctest summary
|
||||
if len(code) == 1:
|
||||
# ordinary doctests (code/output interleaved)
|
||||
try:
|
||||
test = parser.get_doctest( # type: ignore
|
||||
doctest_encode(code[0].code, self.env.config.source_encoding), {}, # type: ignore # NOQA
|
||||
group.name, code[0].filename, code[0].lineno)
|
||||
test = parser.get_doctest(code[0].code, {}, group.name, # type: ignore
|
||||
code[0].filename, code[0].lineno)
|
||||
except Exception:
|
||||
logger.warning(__('ignoring invalid doctest code: %r'), code[0].code,
|
||||
location=(code[0].filename, code[0].lineno))
|
||||
@ -542,11 +547,10 @@ Doctest summary
|
||||
exc_msg = m.group('msg')
|
||||
else:
|
||||
exc_msg = None
|
||||
example = doctest.Example( # type: ignore
|
||||
doctest_encode(code[0].code, self.env.config.source_encoding), output, # type: ignore # NOQA
|
||||
exc_msg=exc_msg,
|
||||
lineno=code[0].lineno,
|
||||
options=options)
|
||||
example = doctest.Example(code[0].code, output, # type: ignore
|
||||
exc_msg=exc_msg,
|
||||
lineno=code[0].lineno,
|
||||
options=options)
|
||||
test = doctest.DocTest([example], {}, group.name, # type: ignore
|
||||
code[0].filename, code[0].lineno, None)
|
||||
self.type = 'exec' # multiple statements again
|
||||
|
@ -25,7 +25,6 @@
|
||||
"""
|
||||
|
||||
from docutils import nodes, utils
|
||||
from six import iteritems
|
||||
|
||||
import sphinx
|
||||
from sphinx.util.nodes import split_explicit_title
|
||||
@ -64,7 +63,7 @@ def make_link_role(base_url, prefix):
|
||||
|
||||
def setup_link_roles(app):
|
||||
# type: (Sphinx) -> None
|
||||
for name, (base_url, prefix) in iteritems(app.config.extlinks):
|
||||
for name, (base_url, prefix) in app.config.extlinks.items():
|
||||
app.add_role(name, make_link_role(base_url, prefix))
|
||||
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import codecs
|
||||
import posixpath
|
||||
import re
|
||||
from hashlib import sha1
|
||||
@ -44,7 +43,7 @@ class GraphvizError(SphinxError):
|
||||
category = 'Graphviz error'
|
||||
|
||||
|
||||
class ClickableMapDefinition(object):
|
||||
class ClickableMapDefinition:
|
||||
"""A manipulator for clickable map file of graphviz."""
|
||||
maptag_re = re.compile('<map id="(.*?)"')
|
||||
href_re = re.compile('href=".*?"')
|
||||
@ -142,7 +141,7 @@ class Graphviz(SphinxDirective):
|
||||
rel_filename, filename = self.env.relfn2path(argument)
|
||||
self.env.note_dependency(rel_filename)
|
||||
try:
|
||||
with codecs.open(filename, 'r', 'utf-8') as fp: # type: ignore
|
||||
with open(filename, 'r', encoding='utf-8') as fp: # type: ignore
|
||||
dotcode = fp.read()
|
||||
except (IOError, OSError):
|
||||
return [document.reporter.warning(
|
||||
@ -156,9 +155,7 @@ class Graphviz(SphinxDirective):
|
||||
line=self.lineno)]
|
||||
node = graphviz()
|
||||
node['code'] = dotcode
|
||||
node['options'] = {
|
||||
'docname': path.splitext(self.state.document.current_source)[0],
|
||||
}
|
||||
node['options'] = {'docname': self.env.docname}
|
||||
|
||||
if 'graphviz_dot' in self.options:
|
||||
node['options']['graphviz_dot'] = self.options['graphviz_dot']
|
||||
@ -311,7 +308,7 @@ def render_dot_html(self, node, code, options, prefix='graphviz',
|
||||
self.body.append('<p class="warning">%s</p>' % alt)
|
||||
self.body.append('</object></div>\n')
|
||||
else:
|
||||
with codecs.open(outfn + '.map', 'r', encoding='utf-8') as mapfile: # type: ignore
|
||||
with open(outfn + '.map', 'r', encoding='utf-8') as mapfile: # type: ignore
|
||||
imgmap = ClickableMapDefinition(outfn + '.map', mapfile.read(), dot=code)
|
||||
if imgmap.clickable:
|
||||
# has a map
|
||||
|
@ -9,7 +9,6 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import codecs
|
||||
import posixpath
|
||||
import re
|
||||
import shutil
|
||||
@ -123,7 +122,7 @@ def compile_math(latex, builder):
|
||||
"""Compile LaTeX macros for math to DVI."""
|
||||
tempdir = ensure_tempdir(builder)
|
||||
filename = path.join(tempdir, 'math.tex')
|
||||
with codecs.open(filename, 'w', 'utf-8') as f: # type: ignore
|
||||
with open(filename, 'w', encoding='utf-8') as f: # type: ignore
|
||||
f.write(latex)
|
||||
|
||||
# build latex command; old versions of latex don't have the
|
||||
@ -318,8 +317,7 @@ def html_visit_displaymath(self, node):
|
||||
if node['nowrap']:
|
||||
latex = node.astext()
|
||||
else:
|
||||
latex = wrap_displaymath(node.astext(), None,
|
||||
self.builder.config.math_number_all)
|
||||
latex = wrap_displaymath(node.astext(), None, False)
|
||||
try:
|
||||
fname, depth = render_math(self, latex)
|
||||
except MathExtError as exc:
|
||||
|
@ -36,6 +36,7 @@ r"""
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import builtins
|
||||
import inspect
|
||||
import re
|
||||
import sys
|
||||
@ -44,7 +45,6 @@ from hashlib import md5
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import directives
|
||||
from six import text_type
|
||||
from six.moves import builtins
|
||||
|
||||
import sphinx
|
||||
from sphinx.ext.graphviz import render_dot_html, render_dot_latex, \
|
||||
@ -129,7 +129,7 @@ class InheritanceException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class InheritanceGraph(object):
|
||||
class InheritanceGraph:
|
||||
"""
|
||||
Given a list of classes, determines the set of classes that they inherit
|
||||
from all the way to the root "object", and then is able to generate a
|
||||
|
@ -30,17 +30,15 @@ import functools
|
||||
import posixpath
|
||||
import sys
|
||||
import time
|
||||
import warnings
|
||||
from os import path
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.utils import relative_path
|
||||
from six import PY3, iteritems, string_types
|
||||
from six import string_types, text_type
|
||||
from six.moves.urllib.parse import urlsplit, urlunsplit
|
||||
|
||||
import sphinx
|
||||
from sphinx.builders.html import INVENTORY_FILENAME
|
||||
from sphinx.deprecation import RemovedInSphinx20Warning
|
||||
from sphinx.locale import _, __
|
||||
from sphinx.util import requests, logging
|
||||
from sphinx.util.inventory import InventoryFile
|
||||
@ -52,15 +50,12 @@ if False:
|
||||
from sphinx.config import Config # NOQA
|
||||
from sphinx.environment import BuildEnvironment # NOQA
|
||||
|
||||
if PY3:
|
||||
unicode = str
|
||||
|
||||
Inventory = Dict[unicode, Dict[unicode, Tuple[unicode, unicode, unicode, unicode]]]
|
||||
Inventory = Dict[text_type, Dict[text_type, Tuple[text_type, text_type, text_type, text_type]]] # NOQA
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class InventoryAdapter(object):
|
||||
class InventoryAdapter:
|
||||
"""Inventory adapter for environment"""
|
||||
|
||||
def __init__(self, env):
|
||||
@ -214,7 +209,7 @@ def load_mappings(app):
|
||||
cache_time = now - app.config.intersphinx_cache_limit * 86400
|
||||
inventories = InventoryAdapter(app.builder.env)
|
||||
update = False
|
||||
for key, value in iteritems(app.config.intersphinx_mapping):
|
||||
for key, value in app.config.intersphinx_mapping.items():
|
||||
name = None # type: unicode
|
||||
uri = None # type: unicode
|
||||
inv = None # type: Union[unicode, Tuple[unicode, ...]]
|
||||
@ -286,7 +281,7 @@ def load_mappings(app):
|
||||
for name, _x, invdata in named_vals + unnamed_vals:
|
||||
if name:
|
||||
inventories.named_inventory[name] = invdata
|
||||
for type, objects in iteritems(invdata):
|
||||
for type, objects in invdata.items():
|
||||
inventories.main_inventory.setdefault(type, {}).update(objects)
|
||||
|
||||
|
||||
@ -380,15 +375,6 @@ def setup(app):
|
||||
}
|
||||
|
||||
|
||||
def debug(argv):
|
||||
# type: (List[unicode]) -> None
|
||||
"""Debug functionality to print out an inventory"""
|
||||
warnings.warn('sphinx.ext.intersphinx.debug() is deprecated. '
|
||||
'Please use inspect_main() instead',
|
||||
RemovedInSphinx20Warning)
|
||||
inspect_main(argv[1:])
|
||||
|
||||
|
||||
def inspect_main(argv):
|
||||
# type: (List[unicode]) -> None
|
||||
"""Debug functionality to print out an inventory"""
|
||||
@ -398,11 +384,11 @@ def inspect_main(argv):
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
class MockConfig(object):
|
||||
class MockConfig:
|
||||
intersphinx_timeout = None # type: int
|
||||
tls_verify = False
|
||||
|
||||
class MockApp(object):
|
||||
class MockApp:
|
||||
srcdir = ''
|
||||
config = MockConfig()
|
||||
|
||||
@ -410,18 +396,23 @@ def inspect_main(argv):
|
||||
# type: (unicode) -> None
|
||||
print(msg, file=sys.stderr)
|
||||
|
||||
filename = argv[0]
|
||||
invdata = fetch_inventory(MockApp(), '', filename) # type: ignore
|
||||
for key in sorted(invdata or {}):
|
||||
print(key)
|
||||
for entry, einfo in sorted(invdata[key].items()):
|
||||
print('\t%-40s %s%s' % (entry,
|
||||
einfo[3] != '-' and '%-40s: ' % einfo[3] or '',
|
||||
einfo[2]))
|
||||
try:
|
||||
filename = argv[0]
|
||||
invdata = fetch_inventory(MockApp(), '', filename) # type: ignore
|
||||
for key in sorted(invdata or {}):
|
||||
print(key)
|
||||
for entry, einfo in sorted(invdata[key].items()):
|
||||
print('\t%-40s %s%s' % (entry,
|
||||
einfo[3] != '-' and '%-40s: ' % einfo[3] or '',
|
||||
einfo[2]))
|
||||
except ValueError as exc:
|
||||
print(exc.args[0] % exc.args[1:])
|
||||
except Exception as exc:
|
||||
print('Unknown error: %r' % exc)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import logging # type: ignore
|
||||
logging.basicConfig()
|
||||
logging.basicConfig() # type: ignore
|
||||
|
||||
inspect_main(argv=sys.argv[1:]) # type: ignore
|
||||
|
@ -12,10 +12,12 @@
|
||||
import warnings
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst.roles import math_role as math_role_base
|
||||
|
||||
from sphinx.addnodes import math, math_block as displaymath # NOQA # to keep compatibility
|
||||
from sphinx.builders.latex.nodes import math_reference as eqref # NOQA # to keep compatibility
|
||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||
from sphinx.directives.patches import MathDirective as MathDirectiveBase
|
||||
from sphinx.domains.math import MathDomain # NOQA # to keep compatibility
|
||||
from sphinx.domains.math import MathReferenceRole as EqXRefRole # NOQA # to keep compatibility
|
||||
|
||||
@ -26,6 +28,21 @@ if False:
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
|
||||
|
||||
class MathDirective(MathDirectiveBase):
|
||||
def run(self):
|
||||
warnings.warn('sphinx.ext.mathbase.MathDirective is moved to '
|
||||
'sphinx.directives.patches package.',
|
||||
RemovedInSphinx30Warning)
|
||||
return super(MathDirective, self).run()
|
||||
|
||||
|
||||
def math_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
|
||||
warnings.warn('sphinx.ext.mathbase.math_role() is deprecated. '
|
||||
'Please use docutils.parsers.rst.roles.math_role() instead.',
|
||||
RemovedInSphinx30Warning)
|
||||
return math_role_base(role, rawtext, text, lineno, inliner, options, content)
|
||||
|
||||
|
||||
def get_node_equation_number(writer, node):
|
||||
# type: (Writer, nodes.Node) -> unicode
|
||||
warnings.warn('sphinx.ext.mathbase.get_node_equation_number() is moved to '
|
||||
|
@ -9,11 +9,7 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
from six import PY2, iteritems
|
||||
|
||||
import sphinx
|
||||
from sphinx import __display_version__ as __version__
|
||||
from sphinx.application import Sphinx
|
||||
from sphinx.ext.napoleon.docstring import GoogleDocstring, NumpyDocstring
|
||||
|
||||
@ -22,7 +18,7 @@ if False:
|
||||
from typing import Any, Dict, List # NOQA
|
||||
|
||||
|
||||
class Config(object):
|
||||
class Config:
|
||||
"""Sphinx napoleon extension settings in `conf.py`.
|
||||
|
||||
Listed below are all the settings used by napoleon and their default
|
||||
@ -176,10 +172,10 @@ class Config(object):
|
||||
|
||||
.. attribute:: attr1
|
||||
|
||||
*int*
|
||||
|
||||
Description of `attr1`
|
||||
|
||||
:type: int
|
||||
|
||||
napoleon_use_param : :obj:`bool` (Defaults to True)
|
||||
True to use a ``:param:`` role for each function parameter. False to
|
||||
use a single ``:parameters:`` role for all the parameters.
|
||||
@ -274,9 +270,9 @@ class Config(object):
|
||||
|
||||
def __init__(self, **settings):
|
||||
# type: (Any) -> None
|
||||
for name, (default, rebuild) in iteritems(self._config_values):
|
||||
for name, (default, rebuild) in self._config_values.items():
|
||||
setattr(self, name, default)
|
||||
for name, value in iteritems(settings):
|
||||
for name, value in settings.items():
|
||||
setattr(self, name, value)
|
||||
|
||||
|
||||
@ -304,7 +300,8 @@ def setup(app):
|
||||
|
||||
"""
|
||||
if not isinstance(app, Sphinx):
|
||||
return # probably called by tests
|
||||
# probably called by tests
|
||||
return {'version': __version__, 'parallel_read_safe': True}
|
||||
|
||||
_patch_python_domain()
|
||||
|
||||
@ -312,9 +309,9 @@ def setup(app):
|
||||
app.connect('autodoc-process-docstring', _process_docstring)
|
||||
app.connect('autodoc-skip-member', _skip_member)
|
||||
|
||||
for name, (default, rebuild) in iteritems(Config._config_values):
|
||||
for name, (default, rebuild) in Config._config_values.items():
|
||||
app.add_config_value(name, default, rebuild)
|
||||
return {'version': sphinx.__display_version__, 'parallel_read_safe': True}
|
||||
return {'version': __version__, 'parallel_read_safe': True}
|
||||
|
||||
|
||||
def _patch_python_domain():
|
||||
@ -435,34 +432,26 @@ def _skip_member(app, what, name, obj, skip, options):
|
||||
if name != '__weakref__' and has_doc and is_member:
|
||||
cls_is_owner = False
|
||||
if what == 'class' or what == 'exception':
|
||||
if PY2:
|
||||
cls = getattr(obj, 'im_class', getattr(obj, '__objclass__',
|
||||
None))
|
||||
cls_is_owner = (cls and hasattr(cls, name) and
|
||||
name in cls.__dict__)
|
||||
elif sys.version_info >= (3, 3):
|
||||
qualname = getattr(obj, '__qualname__', '')
|
||||
cls_path, _, _ = qualname.rpartition('.')
|
||||
if cls_path:
|
||||
try:
|
||||
if '.' in cls_path:
|
||||
import importlib
|
||||
import functools
|
||||
qualname = getattr(obj, '__qualname__', '')
|
||||
cls_path, _, _ = qualname.rpartition('.')
|
||||
if cls_path:
|
||||
try:
|
||||
if '.' in cls_path:
|
||||
import importlib
|
||||
import functools
|
||||
|
||||
mod = importlib.import_module(obj.__module__)
|
||||
mod_path = cls_path.split('.')
|
||||
cls = functools.reduce(getattr, mod_path, mod)
|
||||
else:
|
||||
cls = obj.__globals__[cls_path]
|
||||
except Exception:
|
||||
cls_is_owner = False
|
||||
mod = importlib.import_module(obj.__module__)
|
||||
mod_path = cls_path.split('.')
|
||||
cls = functools.reduce(getattr, mod_path, mod)
|
||||
else:
|
||||
cls_is_owner = (cls and hasattr(cls, name) and
|
||||
name in cls.__dict__)
|
||||
else:
|
||||
cls = obj.__globals__[cls_path]
|
||||
except Exception:
|
||||
cls_is_owner = False
|
||||
else:
|
||||
cls_is_owner = (cls and hasattr(cls, name) and # type: ignore
|
||||
name in cls.__dict__)
|
||||
else:
|
||||
cls_is_owner = True
|
||||
cls_is_owner = False
|
||||
|
||||
if what == 'module' or cls_is_owner:
|
||||
is_init = (name == '__init__')
|
||||
|
@ -11,13 +11,12 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
import collections
|
||||
import inspect
|
||||
import re
|
||||
from collections.abc import Callable
|
||||
from functools import partial
|
||||
|
||||
from six import string_types, u
|
||||
from six.moves import range
|
||||
|
||||
from sphinx.ext.napoleon.iterators import modify_iter
|
||||
from sphinx.locale import _
|
||||
@ -25,7 +24,7 @@ from sphinx.util.pycompat import UnicodeMixin
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Any, Callable, Dict, List, Tuple, Union # NOQA
|
||||
from typing import Any, Dict, List, Tuple, Type, Union # NOQA
|
||||
from sphinx.application import Sphinx # NOQA
|
||||
from sphinx.config import Config as SphinxConfig # NOQA
|
||||
|
||||
@ -105,6 +104,10 @@ class GoogleDocstring(UnicodeMixin):
|
||||
<BLANKLINE>
|
||||
|
||||
"""
|
||||
|
||||
_name_rgx = re.compile(r"^\s*(:(?P<role>\w+):`(?P<name>[a-zA-Z0-9_.-]+)`|"
|
||||
r" (?P<name2>[a-zA-Z0-9_.-]+))\s*", re.X)
|
||||
|
||||
def __init__(self, docstring, config=None, app=None, what='', name='',
|
||||
obj=None, options=None):
|
||||
# type: (Union[unicode, List[unicode]], SphinxConfig, Sphinx, unicode, unicode, Any, Any) -> None # NOQA
|
||||
@ -120,7 +123,7 @@ class GoogleDocstring(UnicodeMixin):
|
||||
what = 'class'
|
||||
elif inspect.ismodule(obj):
|
||||
what = 'module'
|
||||
elif isinstance(obj, collections.Callable): # type: ignore
|
||||
elif isinstance(obj, Callable):
|
||||
what = 'function'
|
||||
else:
|
||||
what = 'object'
|
||||
@ -264,8 +267,9 @@ class GoogleDocstring(UnicodeMixin):
|
||||
# type: () -> Tuple[unicode, List[unicode]]
|
||||
line = next(self._line_iter)
|
||||
_type, colon, _desc = self._partition_field_on_colon(line)
|
||||
if not colon:
|
||||
if not colon or not _desc:
|
||||
_type, _desc = _desc, _type
|
||||
_desc += colon
|
||||
_descs = [_desc] + self._dedent(self._consume_to_end())
|
||||
_descs = self.__class__(_descs, self._config).lines()
|
||||
return _type, _descs
|
||||
@ -604,6 +608,7 @@ class GoogleDocstring(UnicodeMixin):
|
||||
lines = []
|
||||
for _name, _type, _desc in self._consume_fields():
|
||||
if self._config.napoleon_use_ivar:
|
||||
_name = self._qualify_name(_name, self._obj)
|
||||
field = ':ivar %s: ' % _name # type: unicode
|
||||
lines.extend(self._format_block(field, _desc))
|
||||
if _type:
|
||||
@ -697,39 +702,16 @@ class GoogleDocstring(UnicodeMixin):
|
||||
def _parse_raises_section(self, section):
|
||||
# type: (unicode) -> List[unicode]
|
||||
fields = self._consume_fields(parse_type=False, prefer_type=True)
|
||||
field_type = ':raises:'
|
||||
padding = ' ' * len(field_type)
|
||||
multi = len(fields) > 1
|
||||
lines = [] # type: List[unicode]
|
||||
for _name, _type, _desc in fields:
|
||||
m = self._name_rgx.match(_type).groupdict() # type: ignore
|
||||
if m['role']:
|
||||
_type = m['name']
|
||||
_type = ' ' + _type if _type else ''
|
||||
_desc = self._strip_empty(_desc)
|
||||
has_desc = any(_desc)
|
||||
separator = has_desc and ' -- ' or ''
|
||||
if _type:
|
||||
has_refs = '`' in _type or ':' in _type
|
||||
has_space = any(c in ' \t\n\v\f ' for c in _type)
|
||||
|
||||
if not has_refs and not has_space:
|
||||
_type = ':exc:`%s`%s' % (_type, separator)
|
||||
elif has_desc and has_space:
|
||||
_type = '*%s*%s' % (_type, separator)
|
||||
else:
|
||||
_type = '%s%s' % (_type, separator)
|
||||
|
||||
if has_desc:
|
||||
field = [_type + _desc[0]] + _desc[1:]
|
||||
else:
|
||||
field = [_type]
|
||||
else:
|
||||
field = _desc
|
||||
if multi:
|
||||
if lines:
|
||||
lines.extend(self._format_block(padding + ' * ', field))
|
||||
else:
|
||||
lines.extend(self._format_block(field_type + ' * ', field))
|
||||
else:
|
||||
lines.extend(self._format_block(field_type + ' ', field))
|
||||
if lines and lines[-1]:
|
||||
_descs = ' ' + '\n '.join(_desc) if any(_desc) else ''
|
||||
lines.append(':raises%s:%s' % (_type, _descs))
|
||||
if lines:
|
||||
lines.append('')
|
||||
return lines
|
||||
|
||||
@ -803,6 +785,18 @@ class GoogleDocstring(UnicodeMixin):
|
||||
colon,
|
||||
"".join(after_colon).strip())
|
||||
|
||||
def _qualify_name(self, attr_name, klass):
|
||||
# type: (unicode, Type) -> unicode
|
||||
if klass and '.' not in attr_name:
|
||||
if attr_name.startswith('~'):
|
||||
attr_name = attr_name[1:]
|
||||
try:
|
||||
q = klass.__qualname__
|
||||
except AttributeError:
|
||||
q = klass.__name__
|
||||
return '~%s.%s' % (q, attr_name)
|
||||
return attr_name
|
||||
|
||||
def _strip_empty(self, lines):
|
||||
# type: (List[unicode]) -> List[unicode]
|
||||
if lines:
|
||||
@ -976,9 +970,6 @@ class NumpyDocstring(GoogleDocstring):
|
||||
return True
|
||||
return False
|
||||
|
||||
_name_rgx = re.compile(r"^\s*(:(?P<role>\w+):`(?P<name>[a-zA-Z0-9_.-]+)`|"
|
||||
r" (?P<name2>[a-zA-Z0-9_.-]+))\s*", re.X)
|
||||
|
||||
def _parse_see_also_section(self, section):
|
||||
# type: (unicode) -> List[unicode]
|
||||
lines = self._consume_to_next_section()
|
||||
|
@ -18,7 +18,7 @@ if False:
|
||||
from typing import Any, Iterable # NOQA
|
||||
|
||||
|
||||
class peek_iter(object):
|
||||
class peek_iter:
|
||||
"""An iterator object that supports peeking ahead.
|
||||
|
||||
Parameters
|
||||
|
@ -13,7 +13,7 @@ import traceback
|
||||
import warnings
|
||||
|
||||
from docutils import nodes
|
||||
from six import iteritems, text_type
|
||||
from six import text_type
|
||||
|
||||
import sphinx
|
||||
from sphinx import addnodes
|
||||
@ -104,7 +104,12 @@ def doctree_read(app, doctree):
|
||||
fullname = signode.get('fullname')
|
||||
refname = modname
|
||||
if env.config.viewcode_follow_imported_members:
|
||||
modname = _get_full_modname(app, modname, fullname)
|
||||
new_modname = app.emit_firstresult(
|
||||
'viewcode-follow-imported', modname, fullname,
|
||||
)
|
||||
if not new_modname:
|
||||
new_modname = _get_full_modname(app, modname, fullname)
|
||||
modname = new_modname
|
||||
if not modname:
|
||||
continue
|
||||
fullname = signode.get('fullname')
|
||||
@ -158,7 +163,7 @@ def collect_pages(app):
|
||||
# len(env._viewcode_modules), nonl=1)
|
||||
|
||||
for modname, entry in status_iterator(
|
||||
sorted(iteritems(env._viewcode_modules)), # type: ignore
|
||||
sorted(env._viewcode_modules.items()), # type: ignore
|
||||
'highlighting module code... ', "blue",
|
||||
len(env._viewcode_modules), # type: ignore
|
||||
app.verbosity, lambda x: x[0]):
|
||||
@ -183,7 +188,7 @@ def collect_pages(app):
|
||||
# the collected tags (HACK: this only works if the tag boundaries are
|
||||
# properly nested!)
|
||||
maxindex = len(lines) - 1
|
||||
for name, docname in iteritems(used):
|
||||
for name, docname in used.items():
|
||||
type, start, end = tags[name]
|
||||
backlink = urito(pagename, docname) + '#' + refname + '.' + name
|
||||
lines[start] = (
|
||||
@ -262,6 +267,7 @@ def setup(app):
|
||||
# app.add_config_value('viewcode_include_modules', [], 'env')
|
||||
# app.add_config_value('viewcode_exclude_modules', [], 'env')
|
||||
app.add_event('viewcode-find-source')
|
||||
app.add_event('viewcode-follow-imported')
|
||||
return {
|
||||
'version': sphinx.__display_version__,
|
||||
'env_version': 1,
|
||||
|
@ -9,8 +9,6 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from six import iteritems
|
||||
|
||||
from sphinx.errors import VersionRequirementError
|
||||
from sphinx.locale import __
|
||||
from sphinx.util import logging
|
||||
@ -24,7 +22,7 @@ if False:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Extension(object):
|
||||
class Extension:
|
||||
def __init__(self, name, module, **kwargs):
|
||||
# type: (unicode, Any, Any) -> None
|
||||
self.name = name
|
||||
@ -49,7 +47,7 @@ def verify_needs_extensions(app, config):
|
||||
if config.needs_extensions is None:
|
||||
return
|
||||
|
||||
for extname, reqversion in iteritems(config.needs_extensions):
|
||||
for extname, reqversion in config.needs_extensions.items():
|
||||
extension = app.extensions.get(extname)
|
||||
if extension is None:
|
||||
logger.warning(__('The %s extension is required by needs_extensions settings, '
|
||||
|
@ -62,7 +62,7 @@ _LATEX_ADD_STYLES = r'''
|
||||
'''
|
||||
|
||||
|
||||
class PygmentsBridge(object):
|
||||
class PygmentsBridge:
|
||||
# Set these attributes if you want to have different Pygments formatters
|
||||
# than the default ones.
|
||||
html_formatter = HtmlFormatter
|
||||
|
30
sphinx/io.py
30
sphinx/io.py
@ -10,6 +10,7 @@
|
||||
"""
|
||||
import codecs
|
||||
import re
|
||||
import warnings
|
||||
|
||||
from docutils.core import Publisher
|
||||
from docutils.io import FileInput, NullOutput
|
||||
@ -17,9 +18,10 @@ from docutils.parsers.rst import Parser as RSTParser
|
||||
from docutils.readers import standalone
|
||||
from docutils.statemachine import StringList, string2lines
|
||||
from docutils.writers import UnfilteredWriter
|
||||
from six import text_type, iteritems
|
||||
from six import text_type
|
||||
from typing import Any, Union # NOQA
|
||||
|
||||
from sphinx.deprecation import RemovedInSphinx30Warning
|
||||
from sphinx.locale import __
|
||||
from sphinx.transforms import (
|
||||
ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences,
|
||||
@ -116,7 +118,6 @@ class SphinxI18nReader(SphinxBaseReader):
|
||||
Because the translated texts are partial and they don't have correct line numbers.
|
||||
"""
|
||||
|
||||
lineno = None # type: int
|
||||
transforms = [ApplySourceWorkaround, ExtraTranslatableNodes, CitationReferences,
|
||||
DefaultSubstitutions, MoveModuleTargets, HandleCodeBlocks,
|
||||
AutoNumbering, SortIds, RemoveTranslatableInline,
|
||||
@ -127,22 +128,15 @@ class SphinxI18nReader(SphinxBaseReader):
|
||||
def set_lineno_for_reporter(self, lineno):
|
||||
# type: (int) -> None
|
||||
"""Stores the source line number of original text."""
|
||||
self.lineno = lineno
|
||||
warnings.warn('SphinxI18nReader.set_lineno_for_reporter() is deprecated.',
|
||||
RemovedInSphinx30Warning)
|
||||
|
||||
def new_document(self):
|
||||
# type: () -> nodes.document
|
||||
"""Creates a new document object which having a special reporter object for
|
||||
translation.
|
||||
"""
|
||||
document = SphinxBaseReader.new_document(self)
|
||||
reporter = document.reporter
|
||||
|
||||
def get_source_and_line(lineno=None):
|
||||
# type: (int) -> Tuple[unicode, int]
|
||||
return reporter.source, self.lineno
|
||||
|
||||
reporter.get_source_and_line = get_source_and_line
|
||||
return document
|
||||
@property
|
||||
def line(self):
|
||||
# type: () -> int
|
||||
warnings.warn('SphinxI18nReader.line is deprecated.',
|
||||
RemovedInSphinx30Warning)
|
||||
return 0
|
||||
|
||||
|
||||
class SphinxDummyWriter(UnfilteredWriter):
|
||||
@ -288,7 +282,7 @@ class FiletypeNotFoundError(Exception):
|
||||
|
||||
def get_filetype(source_suffix, filename):
|
||||
# type: (Dict[unicode, unicode], unicode) -> unicode
|
||||
for suffix, filetype in iteritems(source_suffix):
|
||||
for suffix, filetype in source_suffix.items():
|
||||
if filename.endswith(suffix):
|
||||
# If default filetype (None), considered as restructuredtext.
|
||||
return filetype or 'restructuredtext'
|
||||
|
@ -98,7 +98,7 @@ def accesskey(context, key):
|
||||
return ''
|
||||
|
||||
|
||||
class idgen(object):
|
||||
class idgen:
|
||||
def __init__(self):
|
||||
# type: () -> None
|
||||
self.id = 0
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user