Merge branch '2.0'

This commit is contained in:
Takeshi KOMIYA 2019-05-29 00:51:25 +09:00
commit b9d7239d90
55 changed files with 972 additions and 342 deletions

View File

@ -25,6 +25,8 @@ matrix:
env: TOXENV=py38 env: TOXENV=py38
- python: '3.6' - python: '3.6'
env: TOXENV=docs env: TOXENV=docs
- python: '3.6'
env: TOXENV=docslint
- python: '3.6' - python: '3.6'
env: TOXENV=mypy env: TOXENV=mypy
- python: '3.6' - python: '3.6'

View File

@ -82,6 +82,7 @@ Other contributors, listed alphabetically, are:
* Stephen Finucane -- setup command improvements and documentation * Stephen Finucane -- setup command improvements and documentation
* Daniel Pizetta -- inheritance diagram improvements * Daniel Pizetta -- inheritance diagram improvements
* KINEBUCHI Tomohiko -- typing Sphinx as well as docutils * KINEBUCHI Tomohiko -- typing Sphinx as well as docutils
* Adrián Chaves (Gallaecio) -- coverage builder improvements
Many thanks for all contributions! Many thanks for all contributions!

319
CHANGES
View File

@ -67,6 +67,7 @@ Deprecated
* ``sphinx.environment.NoUri`` * ``sphinx.environment.NoUri``
* ``sphinx.ext.apidoc.format_directive()`` * ``sphinx.ext.apidoc.format_directive()``
* ``sphinx.ext.apidoc.format_heading()`` * ``sphinx.ext.apidoc.format_heading()``
* ``sphinx.ext.apidoc.makename()``
* ``sphinx.ext.autodoc.importer.MockFinder`` * ``sphinx.ext.autodoc.importer.MockFinder``
* ``sphinx.ext.autodoc.importer.MockLoader`` * ``sphinx.ext.autodoc.importer.MockLoader``
* ``sphinx.ext.autodoc.importer.mock()`` * ``sphinx.ext.autodoc.importer.mock()``
@ -106,12 +107,17 @@ Features added
* #6289: autodoc: :confval:`autodoc_default_options` now supports * #6289: autodoc: :confval:`autodoc_default_options` now supports
``imported-members`` option ``imported-members`` option
* #4777: autodoc: Support coroutine * #4777: autodoc: Support coroutine
* #744: autodoc: Support abstractmethod
* #6325: autodoc: Support attributes in __slots__. For dict-style __slots__,
autodoc considers values as a docstring of the attribute
* #6212 autosummary: Add :confval:`autosummary_imported_members` to display * #6212 autosummary: Add :confval:`autosummary_imported_members` to display
imported members on autosummary imported members on autosummary
* #6271: ``make clean`` is catastrophically broken if building into '.' * #6271: ``make clean`` is catastrophically broken if building into '.'
* #6363: Support ``%O%`` environment variable in make.bat
* #4777: py domain: Add ``:async:`` option to :rst:dir:`py:function` directive * #4777: py domain: Add ``:async:`` option to :rst:dir:`py:function` directive
* py domain: Add new options to :rst:dir:`py:method` directive * py domain: Add new options to :rst:dir:`py:method` directive
- ``:abstractmethod:``
- ``:async:`` - ``:async:``
- ``:classmethod:`` - ``:classmethod:``
- ``:property:`` - ``:property:``
@ -120,6 +126,10 @@ Features added
* rst domain: Add :rst:dir:`directive:option` directive to describe the option * rst domain: Add :rst:dir:`directive:option` directive to describe the option
for directive for directive
* #6306: html: Add a label to search form for accessability purposes * #6306: html: Add a label to search form for accessability purposes
* #6358: The ``rawsource`` property of ``production`` nodes now contains the
full production rule
* #6373: autosectionlabel: Allow suppression of warnings
* coverage: Support a new ``coverage_ignore_pyobjects`` option
Bugs fixed Bugs fixed
---------- ----------
@ -129,11 +139,18 @@ Bugs fixed
* #6213: ifconfig: contents after headings are not shown * #6213: ifconfig: contents after headings are not shown
* commented term in glossary directive is wrongly recognized * commented term in glossary directive is wrongly recognized
* #6299: rst domain: rst:directive directive generates waste space * #6299: rst domain: rst:directive directive generates waste space
* #6379: py domain: Module index (py-modindex.html) has duplicate titles
* #6331: man: invalid output when doctest follows rubric * #6331: man: invalid output when doctest follows rubric
* #6351: "Hyperlink target is not referenced" message is shown even if * #6351: "Hyperlink target is not referenced" message is shown even if
referenced referenced
* #6165: autodoc: ``tab_width`` setting of docutils has been ignored * #6165: autodoc: ``tab_width`` setting of docutils has been ignored
* #6311: autosummary: autosummary table gets confused by complex type hints
* #6350: autosummary: confused by an argument having some kind of default value
* Generated Makefiles lack a final EOL (refs: #6232) * Generated Makefiles lack a final EOL (refs: #6232)
* #6375: extlinks: Cannot escape angle brackets in link caption
* #6378: linkcheck: Send commonly used User-Agent
* #6387: html search: failed to search document with haiku and scrolls themes
* #6406: Wrong year is returned for ``SOURCE_DATE_EPOCH``
Testing Testing
-------- --------
@ -1598,7 +1615,8 @@ Incompatible changes
(refs #3550) (refs #3550)
* ``Builder.env`` is not filled at instantiation * ``Builder.env`` is not filled at instantiation
* #3594: LaTeX: single raw directive has been considered as block level element * #3594: LaTeX: single raw directive has been considered as block level element
* #3639: If ``html_experimental_html5_writer`` is available, epub builder use it by default. * #3639: If ``html_experimental_html5_writer`` is available, epub builder use it
by default.
* ``Sphinx.add_source_parser()`` raises an error if duplicated * ``Sphinx.add_source_parser()`` raises an error if duplicated
1.6b2 1.6b2
@ -1670,8 +1688,9 @@ Features added
* #3476: setuptools: Support multiple builders * #3476: setuptools: Support multiple builders
* latex: merged cells in LaTeX tables allow code-blocks, lists, blockquotes... * latex: merged cells in LaTeX tables allow code-blocks, lists, blockquotes...
as do normal cells (refs: #3435) as do normal cells (refs: #3435)
* HTML builder uses experimental HTML5 writer if ``html_experimental_html5_writer`` is True * HTML builder uses experimental HTML5 writer if
and docutils 0.13 or later is installed. ``html_experimental_html5_writer`` is True and docutils 0.13 or later is
installed.
* LaTeX macros to customize space before and after tables in PDF output (refs #3504) * LaTeX macros to customize space before and after tables in PDF output (refs #3504)
* #3348: Show decorators in literalinclude and viewcode directives * #3348: Show decorators in literalinclude and viewcode directives
* #3108: Show warning if :start-at: and other literalinclude options does not * #3108: Show warning if :start-at: and other literalinclude options does not
@ -1710,7 +1729,8 @@ Bugs fixed
* #1574: Paragraphs in table cell doesn't work in Latex output * #1574: Paragraphs in table cell doesn't work in Latex output
* #3288: Table with merged headers not wrapping text * #3288: Table with merged headers not wrapping text
* #3491: Inconsistent vertical space around table and longtable in PDF * #3491: Inconsistent vertical space around table and longtable in PDF
* #3506: Depart functions for all admonitions in HTML writer now properly pass ``node`` to ``depart_admonition``. * #3506: Depart functions for all admonitions in HTML writer now properly pass
``node`` to ``depart_admonition``.
* #2693: Sphinx latex style file wrongly inhibits colours for section headings * #2693: Sphinx latex style file wrongly inhibits colours for section headings
for latex+dvi(ps,pdf,pdfmx) for latex+dvi(ps,pdf,pdfmx)
* C++, properly look up ``any`` references. * C++, properly look up ``any`` references.
@ -2036,18 +2056,23 @@ Incompatible changes
``jreport`` and ``jsbook`` as docclass if :confval:`language` is ``jreport`` and ``jsbook`` as docclass if :confval:`language` is
``ja``. ``ja``.
* ``sphinx-quickstart`` now allows a project version is empty * ``sphinx-quickstart`` now allows a project version is empty
* Fix :download: role on epub/qthelp builder. They ignore the role because they don't support it. * Fix :download: role on epub/qthelp builder. They ignore the role because they
* ``sphinx.ext.viewcode`` doesn't work on epub building by default. ``viewcode_enable_epub`` option don't support it.
* ``sphinx.ext.viewcode`` doesn't work on epub building by default.
``viewcode_enable_epub`` option
* ``sphinx.ext.viewcode`` disabled on singlehtml builder. * ``sphinx.ext.viewcode`` disabled on singlehtml builder.
* Use make-mode of ``sphinx-quickstart`` by default. To disable this, use * Use make-mode of ``sphinx-quickstart`` by default. To disable this, use
``-M`` option ``-M`` option
* Fix ``genindex.html``, Sphinx's document template, link address to itself to satisfy xhtml standard. * Fix ``genindex.html``, Sphinx's document template, link address to itself to
satisfy xhtml standard.
* Use epub3 builder by default. And the old epub builder is renamed to epub2. * Use epub3 builder by default. And the old epub builder is renamed to epub2.
* Fix ``epub`` and ``epub3`` builders that contained links to ``genindex`` even if ``epub_use_index = False``. * Fix ``epub`` and ``epub3`` builders that contained links to ``genindex`` even
if ``epub_use_index = False``.
* ``html_translator_class`` is now deprecated. * ``html_translator_class`` is now deprecated.
Use `Sphinx.set_translator()` API instead. Use `Sphinx.set_translator()` API instead.
* Drop python 2.6 and 3.3 support * Drop python 2.6 and 3.3 support
* Drop epub3 builder's ``epub3_page_progression_direction`` option (use ``epub3_writing_mode``). * Drop epub3 builder's ``epub3_page_progression_direction`` option (use
``epub3_writing_mode``).
* #2877: Rename ``latex_elements['footer']`` to * #2877: Rename ``latex_elements['footer']`` to
``latex_elements['atendofbody']`` ``latex_elements['atendofbody']``
@ -2301,7 +2326,8 @@ Bugs fixed
* #3068: Allow the '=' character in the -D option of sphinx-build.py * #3068: Allow the '=' character in the -D option of sphinx-build.py
* #3074: ``add_source_parser()`` crashes in debug mode * #3074: ``add_source_parser()`` crashes in debug mode
* #3135: ``sphinx.ext.autodoc`` crashes with plain Callable * #3135: ``sphinx.ext.autodoc`` crashes with plain Callable
* #3150: Fix query word splitter in JavaScript. It behaves as same as Python's regular expression. * #3150: Fix query word splitter in JavaScript. It behaves as same as Python's
regular expression.
* #3093: gettext build broken on substituted images. * #3093: gettext build broken on substituted images.
* #3093: gettext build broken on image node under ``note`` directive. * #3093: gettext build broken on image node under ``note`` directive.
* imgmath: crashes on showing error messages if image generation failed * imgmath: crashes on showing error messages if image generation failed
@ -2329,10 +2355,13 @@ Bugs fixed
* #2902: jsdump.loads fails to load search index if keywords starts with * #2902: jsdump.loads fails to load search index if keywords starts with
underscore underscore
* #2900: Fix epub content.opf: add auto generated orphan files to spine. * #2900: Fix epub content.opf: add auto generated orphan files to spine.
* #2899: Fix ``hasdoc()`` function in Jinja2 template. It will detect ``genindex``, ``search`` also. * #2899: Fix ``hasdoc()`` function in Jinja2 template. It will detect
* #2901: Fix epub result: skip creating links from image tags to original image files. ``genindex``, ``search`` also.
* #2901: Fix epub result: skip creating links from image tags to original image
files.
* #2917: inline code is hyphenated on HTML * #2917: inline code is hyphenated on HTML
* #1462: autosummary warns for namedtuple with attribute with trailing underscore * #1462: autosummary warns for namedtuple with attribute with trailing
underscore
* Could not reference equations if ``:nowrap:`` option specified * Could not reference equations if ``:nowrap:`` option specified
* #2873: code-block overflow in latex (due to commas) * #2873: code-block overflow in latex (due to commas)
* #1060, #2056: sphinx.ext.intersphinx: broken links are generated if relative * #1060, #2056: sphinx.ext.intersphinx: broken links are generated if relative
@ -2349,29 +2378,35 @@ Release 1.4.6 (released Aug 20, 2016)
Incompatible changes Incompatible changes
-------------------- --------------------
* #2867: linkcheck builder crashes with six-1.4. Now Sphinx depends on six-1.5 or * #2867: linkcheck builder crashes with six-1.4. Now Sphinx depends on six-1.5
later or later
Bugs fixed Bugs fixed
---------- ----------
* applehelp: Sphinx crashes if ``hiutil`` or ``codesign`` commands not found * applehelp: Sphinx crashes if ``hiutil`` or ``codesign`` commands not found
* Fix ``make clean`` abort issue when build dir contains regular files like ``DS_Store``. * Fix ``make clean`` abort issue when build dir contains regular files like
``DS_Store``.
* Reduce epubcheck warnings/errors: * Reduce epubcheck warnings/errors:
* Fix DOCTYPE to html5 * Fix DOCTYPE to html5
* Change extension from .html to .xhtml. * Change extension from .html to .xhtml.
* Disable search page on epub results * Disable search page on epub results
* #2778: Fix autodoc crashes if obj.__dict__ is a property method and raises exception * #2778: Fix autodoc crashes if obj.__dict__ is a property method and raises
exception
* Fix duplicated toc in epub3 output. * Fix duplicated toc in epub3 output.
* #2775: Fix failing linkcheck with servers not supporting identity encoding * #2775: Fix failing linkcheck with servers not supporting identity encoding
* #2833: Fix formatting instance annotations in ext.autodoc. * #2833: Fix formatting instance annotations in ext.autodoc.
* #1911: ``-D`` option of ``sphinx-build`` does not override the ``extensions`` variable * #1911: ``-D`` option of ``sphinx-build`` does not override the ``extensions``
* #2789: `sphinx.ext.intersphinx` generates wrong hyperlinks if the inventory is given variable
* parsing errors for caption of code-blocks are displayed in document (ref: #2845) * #2789: `sphinx.ext.intersphinx` generates wrong hyperlinks if the inventory is
given
* parsing errors for caption of code-blocks are displayed in document
(ref: #2845)
* #2846: ``singlehtml`` builder does not include figure numbers * #2846: ``singlehtml`` builder does not include figure numbers
* #2816: Fix data from builds cluttering the ``Domain.initial_data`` class attributes * #2816: Fix data from builds cluttering the ``Domain.initial_data`` class
attributes
Release 1.4.5 (released Jul 13, 2016) Release 1.4.5 (released Jul 13, 2016)
===================================== =====================================
@ -2400,7 +2435,8 @@ Bugs fixed
* jsdump fix for python 3: fixes the HTML search on python > 3 * jsdump fix for python 3: fixes the HTML search on python > 3
* #2676: (latex) Error with verbatim text in captions since Sphinx 1.4.4 * #2676: (latex) Error with verbatim text in captions since Sphinx 1.4.4
* #2629: memoir class crashes LaTeX. Fixed ``by latex_keep_old_macro_names=False`` (ref 2675) * #2629: memoir class crashes LaTeX. Fixed by
``latex_keep_old_macro_names=False`` (ref 2675)
* #2684: `sphinx.ext.intersphinx` crashes with six-1.4.1 * #2684: `sphinx.ext.intersphinx` crashes with six-1.4.1
* #2679: ``float`` package needed for ``'figure_align': 'H'`` latex option * #2679: ``float`` package needed for ``'figure_align': 'H'`` latex option
* #2671: image directive may lead to inconsistent spacing in pdf * #2671: image directive may lead to inconsistent spacing in pdf
@ -2408,10 +2444,12 @@ Bugs fixed
* #2479: `sphinx.ext.viewcode` uses python2 highlighter by default * #2479: `sphinx.ext.viewcode` uses python2 highlighter by default
* #2700: HtmlHelp builder has hard coded index.html * #2700: HtmlHelp builder has hard coded index.html
* latex, since 1.4.4 inline literal text is followed by spurious space * latex, since 1.4.4 inline literal text is followed by spurious space
* #2722: C++, fix id generation for var/member declarations to include namespaces. * #2722: C++, fix id generation for var/member declarations to include
namespaces.
* latex, images (from image directive) in lists or quoted blocks did not obey * latex, images (from image directive) in lists or quoted blocks did not obey
indentation (fixed together with #2671) indentation (fixed together with #2671)
* #2733: since Sphinx-1.4.4 ``make latexpdf`` generates lots of hyperref warnings * #2733: since Sphinx-1.4.4 ``make latexpdf`` generates lots of hyperref
warnings
* #2731: `sphinx.ext.autodoc` does not access propertymethods which raises any * #2731: `sphinx.ext.autodoc` does not access propertymethods which raises any
exceptions exceptions
* #2666: C++, properly look up nested names involving constructors. * #2666: C++, properly look up nested names involving constructors.
@ -2459,13 +2497,16 @@ Bugs fixed
* #2530: got "Counter too large" error on building PDF if large numbered * #2530: got "Counter too large" error on building PDF if large numbered
footnotes existed in admonitions footnotes existed in admonitions
* ``width`` option of figure directive does not work if ``align`` option specified at same time (ref: #2595) * ``width`` option of figure directive does not work if ``align`` option
specified at same time (ref: #2595)
* #2590: The ``inputenc`` package breaks compiling under lualatex and xelatex * #2590: The ``inputenc`` package breaks compiling under lualatex and xelatex
* #2540: date on latex front page use different font * #2540: date on latex front page use different font
* Suppress "document isn't included in any toctree" warning if the document is included (ref: #2603) * Suppress "document isn't included in any toctree" warning if the document is
included (ref: #2603)
* #2614: Some tables in PDF output will end up shifted if user sets non zero * #2614: Some tables in PDF output will end up shifted if user sets non zero
\parindent in preamble \parindent in preamble
* #2602: URL redirection breaks the hyperlinks generated by `sphinx.ext.intersphinx` * #2602: URL redirection breaks the hyperlinks generated by
`sphinx.ext.intersphinx`
* #2613: Show warnings if merged extensions are loaded * #2613: Show warnings if merged extensions are loaded
* #2619: make sure amstext LaTeX package always loaded (ref: d657225, 488ee52, * #2619: make sure amstext LaTeX package always loaded (ref: d657225, 488ee52,
9d82cad and #2615) 9d82cad and #2615)
@ -2478,7 +2519,8 @@ Release 1.4.2 (released May 29, 2016)
Features added Features added
-------------- --------------
* Now :confval:`suppress_warnings` accepts following configurations (ref: #2451, #2466): * Now :confval:`suppress_warnings` accepts following configurations
(ref: #2451, #2466):
- ``app.add_node`` - ``app.add_node``
- ``app.add_directive`` - ``app.add_directive``
@ -2505,14 +2547,17 @@ Bugs fixed
* #2370: the equations are slightly misaligned in LaTeX writer * #2370: the equations are slightly misaligned in LaTeX writer
* #1817, #2077: suppress pep8 warnings on conf.py generated by sphinx-quickstart * #1817, #2077: suppress pep8 warnings on conf.py generated by sphinx-quickstart
* #2407: building docs crash if document includes large data image URIs * #2407: building docs crash if document includes large data image URIs
* #2436: Sphinx does not check version by :confval:`needs_sphinx` if loading extensions failed * #2436: Sphinx does not check version by :confval:`needs_sphinx` if loading
extensions failed
* #2397: Setup shorthandoff for Turkish documents * #2397: Setup shorthandoff for Turkish documents
* #2447: VerbatimBorderColor wrongly used also for captions of PDF * #2447: VerbatimBorderColor wrongly used also for captions of PDF
* #2456: C++, fix crash related to document merging (e.g., singlehtml and Latex builders). * #2456: C++, fix crash related to document merging (e.g., singlehtml and Latex
builders).
* #2446: latex(pdf) sets local tables of contents (or more generally topic * #2446: latex(pdf) sets local tables of contents (or more generally topic
nodes) in unbreakable boxes, causes overflow at bottom nodes) in unbreakable boxes, causes overflow at bottom
* #2476: Omit MathJax markers if :nowrap: is given * #2476: Omit MathJax markers if :nowrap: is given
* #2465: latex builder fails in case no caption option is provided to toctree directive * #2465: latex builder fails in case no caption option is provided to toctree
directive
* Sphinx crashes if self referenced toctree found * Sphinx crashes if self referenced toctree found
* #2481: spelling mistake for mecab search splitter. Thanks to Naoki Sato. * #2481: spelling mistake for mecab search splitter. Thanks to Naoki Sato.
* #2309: Fix could not refer "indirect hyperlink targets" by ref-role * #2309: Fix could not refer "indirect hyperlink targets" by ref-role
@ -2522,22 +2567,28 @@ Bugs fixed
* #1534: Word wrap long lines in Latex verbatim blocks * #1534: Word wrap long lines in Latex verbatim blocks
* #2460: too much white space on top of captioned literal blocks in PDF output * #2460: too much white space on top of captioned literal blocks in PDF output
* Show error reason when multiple math extensions are loaded (ref: #2499) * Show error reason when multiple math extensions are loaded (ref: #2499)
* #2483: any figure number was not assigned if figure title contains only non text objects * #2483: any figure number was not assigned if figure title contains only non
text objects
* #2501: Unicode subscript numbers are normalized in LaTeX * #2501: Unicode subscript numbers are normalized in LaTeX
* #2492: Figure directive with :figwidth: generates incorrect Latex-code * #2492: Figure directive with :figwidth: generates incorrect Latex-code
* The caption of figure is always put on center even if ``:align:`` was specified * The caption of figure is always put on center even if ``:align:`` was
specified
* #2526: LaTeX writer crashes if the section having only images * #2526: LaTeX writer crashes if the section having only images
* #2522: Sphinx touches mo files under installed directory that caused permission error. * #2522: Sphinx touches mo files under installed directory that caused
* #2536: C++, fix crash when an immediately nested scope has the same name as the current scope. permission error.
* #2536: C++, fix crash when an immediately nested scope has the same name as
the current scope.
* #2555: Fix crash on any-references with unicode. * #2555: Fix crash on any-references with unicode.
* #2517: wrong bookmark encoding in PDF if using LuaLaTeX * #2517: wrong bookmark encoding in PDF if using LuaLaTeX
* #2521: generated Makefile causes BSD make crashed if sphinx-build not found * #2521: generated Makefile causes BSD make crashed if sphinx-build not found
* #2470: ``typing`` backport package causes autodoc errors with python 2.7 * #2470: ``typing`` backport package causes autodoc errors with python 2.7
* ``sphinx.ext.intersphinx`` crashes if non-string value is used for key of `intersphinx_mapping` * ``sphinx.ext.intersphinx`` crashes if non-string value is used for key of
`intersphinx_mapping`
* #2518: `intersphinx_mapping` disallows non alphanumeric keys * #2518: `intersphinx_mapping` disallows non alphanumeric keys
* #2558: unpack error on devhelp builder * #2558: unpack error on devhelp builder
* #2561: Info builder crashes when a footnote contains a link * #2561: Info builder crashes when a footnote contains a link
* #2565: The descriptions of objects generated by ``sphinx.ext.autosummary`` overflow lines at LaTeX writer * #2565: The descriptions of objects generated by ``sphinx.ext.autosummary``
overflow lines at LaTeX writer
* Extend pdflatex config in sphinx.sty to subparagraphs (ref: #2551) * Extend pdflatex config in sphinx.sty to subparagraphs (ref: #2551)
* #2445: `rst_prolog` and `rst_epilog` affect to non reST sources * #2445: `rst_prolog` and `rst_epilog` affect to non reST sources
* #2576: ``sphinx.ext.imgmath`` crashes if subprocess raises error * #2576: ``sphinx.ext.imgmath`` crashes if subprocess raises error
@ -2572,8 +2623,8 @@ Bugs fixed
---------- ----------
* C++, added support for ``extern`` and ``thread_local``. * C++, added support for ``extern`` and ``thread_local``.
* C++, type declarations are now using the prefixes ``typedef``, ``using``, and ``type``, * C++, type declarations are now using the prefixes ``typedef``, ``using``, and
depending on the style of declaration. ``type``, depending on the style of declaration.
* #2413: C++, fix crash on duplicate declarations * #2413: C++, fix crash on duplicate declarations
* #2394: Sphinx crashes when html_last_updated_fmt is invalid * #2394: Sphinx crashes when html_last_updated_fmt is invalid
* #2408: dummy builder not available in Makefile and make.bat * #2408: dummy builder not available in Makefile and make.bat
@ -2592,27 +2643,28 @@ Release 1.4 (released Mar 28, 2016)
Incompatible changes Incompatible changes
-------------------- --------------------
* Drop ``PorterStemmer`` package support. Use ``PyStemmer`` instead of ``PorterStemmer`` * Drop ``PorterStemmer`` package support. Use ``PyStemmer`` instead of
to accelerate stemming. ``PorterStemmer`` to accelerate stemming.
* sphinx_rtd_theme has become optional. Please install it manually. * sphinx_rtd_theme has become optional. Please install it manually.
Refs #2087, #2086, #1845 and #2097. Thanks to Victor Zverovich. Refs #2087, #2086, #1845 and #2097. Thanks to Victor Zverovich.
* #2231: Use DUrole instead of DUspan for custom roles in LaTeX writer. It enables to take * #2231: Use DUrole instead of DUspan for custom roles in LaTeX writer. It
title of roles as an argument of custom macros. enables to take title of roles as an argument of custom macros.
* #2022: 'Thumbs.db' and '.DS_Store' are added to `exclude_patterns` default values in * #2022: 'Thumbs.db' and '.DS_Store' are added to `exclude_patterns` default
conf.py that will be provided on sphinx-quickstart. values in conf.py that will be provided on sphinx-quickstart.
* #2027, #2208: The ``html_title`` accepts string values only. And The None value cannot be * #2027, #2208: The ``html_title`` accepts string values only. And The None
accepted. value cannot be accepted.
* ``sphinx.ext.graphviz``: show graph image in inline by default * ``sphinx.ext.graphviz``: show graph image in inline by default
* #2060, #2224: The ``manpage`` role now generate ``sphinx.addnodes.manpage`` node instead * #2060, #2224: The ``manpage`` role now generate ``sphinx.addnodes.manpage``
of ``sphinx.addnodes.literal_emphasis`` node. node instead of ``sphinx.addnodes.literal_emphasis`` node.
* #2022: :confval:`html_extra_path` also copies dotfiles in the extra directory, and * #2022: :confval:`html_extra_path` also copies dotfiles in the extra directory,
refers to :confval:`exclude_patterns` to exclude extra files and directories. and refers to :confval:`exclude_patterns` to exclude extra files and
* #2300: enhance autoclass:: to use the docstring of __new__ if __init__ method's is missing directories.
of empty * #2300: enhance autoclass:: to use the docstring of __new__ if __init__
* #2251: Previously, under glossary directives, multiple terms for one definition are method's is missing of empty
converted into single ``term`` node and the each terms in the term node are separated * #2251: Previously, under glossary directives, multiple terms for one
by ``termsep`` node. In new implementation, each terms are converted into individual definition are converted into single ``term`` node and the each terms in the
``term`` nodes and ``termsep`` node is removed. term node are separated by ``termsep`` node. In new implementation, each terms
are converted into individual ``term`` nodes and ``termsep`` node is removed.
By this change, output layout of every builders are changed a bit. By this change, output layout of every builders are changed a bit.
* The default highlight language is now Python 3. This means that source code * The default highlight language is now Python 3. This means that source code
is highlighted as Python 3 (which is mostly a superset of Python 2), and no is highlighted as Python 3 (which is mostly a superset of Python 2), and no
@ -2620,13 +2672,15 @@ Incompatible changes
add ``highlight_language = "python"`` to conf.py. add ``highlight_language = "python"`` to conf.py.
* `Locale Date Markup Language * `Locale Date Markup Language
<https://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`. ``"MMMM dd, YYYY"`` is default format for `today_fmt` and
However strftime format like ``"%B %d, %Y"`` is also supported for backward `html_last_updated_fmt`. However strftime format like ``"%B %d, %Y"`` is also
compatibility until Sphinx-1.5. Later format will be disabled from Sphinx-1.5. supported for backward compatibility until Sphinx-1.5. Later format will be
disabled from Sphinx-1.5.
* #2327: ``latex_use_parts`` is deprecated now. Use `latex_toplevel_sectioning` * #2327: ``latex_use_parts`` is deprecated now. Use `latex_toplevel_sectioning`
instead. instead.
* #2337: Use ``\url{URL}`` macro instead of ``\href{URL}{URL}`` in LaTeX writer. * #2337: Use ``\url{URL}`` macro instead of ``\href{URL}{URL}`` in LaTeX writer.
* #1498: manpage writer: don't make whole of item in definition list bold if it includes strong node. * #1498: manpage writer: don't make whole of item in definition list bold if it
includes strong node.
* #582: Remove hint message from quick search box for html output. * #582: Remove hint message from quick search box for html output.
* #2378: Sphinx now bundles newfloat.sty * #2378: Sphinx now bundles newfloat.sty
@ -2637,8 +2691,10 @@ Features added
an element is already present (built-in or added by another extension). an element is already present (built-in or added by another extension).
* #1909: Add "doc" references to Intersphinx inventories. * #1909: Add "doc" references to Intersphinx inventories.
* C++ type alias support (e.g., ``.. type:: T = int``). * C++ type alias support (e.g., ``.. type:: T = int``).
* C++ template support for classes, functions, type aliases, and variables (#1729, #1314). * C++ template support for classes, functions, type aliases, and variables
* C++, added new scope management directives ``namespace-push`` and ``namespace-pop``. (#1729, #1314).
* C++, added new scope management directives ``namespace-push`` and
``namespace-pop``.
* #1970: Keyboard shortcuts to navigate Next and Previous topics * #1970: Keyboard shortcuts to navigate Next and Previous topics
* Intersphinx: Added support for fetching Intersphinx inventories with URLs * Intersphinx: Added support for fetching Intersphinx inventories with URLs
using HTTP basic auth. using HTTP basic auth.
@ -2652,43 +2708,54 @@ Features added
* #2170: Support for Chinese language search index. * #2170: Support for Chinese language search index.
* #2214: Add sphinx.ext.githubpages to publish the docs on GitHub Pages * #2214: Add sphinx.ext.githubpages to publish the docs on GitHub Pages
* #1030: Make page reference names for latex_show_pagerefs translatable * #1030: Make page reference names for latex_show_pagerefs translatable
* #2162: Add Sphinx.add_source_parser() to add source_suffix and source_parsers from extension * #2162: Add Sphinx.add_source_parser() to add source_suffix and source_parsers
from extension
* #2207: Add sphinx.parsers.Parser class; a base class for new parsers * #2207: Add sphinx.parsers.Parser class; a base class for new parsers
* #656: Add ``graphviz_dot`` option to graphviz directives to switch the ``dot`` command * #656: Add ``graphviz_dot`` option to graphviz directives to switch the ``dot``
command
* #1939: Added the ``dummy`` builder: syntax check without output. * #1939: Added the ``dummy`` builder: syntax check without output.
* #2230: Add ``math_number_all`` option to number all displayed math in math extensions * #2230: Add ``math_number_all`` option to number all displayed math in math
extensions
* #2235: ``needs_sphinx`` supports micro version comparison * #2235: ``needs_sphinx`` supports micro version comparison
* #2282: Add "language" attribute to html tag in the "basic" theme * #2282: Add "language" attribute to html tag in the "basic" theme
* #1779: Add EPUB 3 builder * #1779: Add EPUB 3 builder
* #1751: Add :confval:`todo_link_only` to avoid file path and line indication on * #1751: Add :confval:`todo_link_only` to avoid file path and line indication on
:rst:dir:`todolist`. Thanks to Francesco Montesano. :rst:dir:`todolist`. Thanks to Francesco Montesano.
* #2199: Use ``imagesize`` package to obtain size of images. * #2199: Use ``imagesize`` package to obtain size of images.
* #1099: Add configurable retries to the linkcheck builder. Thanks to Alex Gaynor. * #1099: Add configurable retries to the linkcheck builder. Thanks to Alex
Also don't check anchors starting with ``!``. Gaynor. Also don't check anchors starting with ``!``.
* #2300: enhance autoclass:: to use the docstring of __new__ if __init__ method's is missing * #2300: enhance autoclass:: to use the docstring of __new__ if __init__
of empty method's is missing of empty
* #1858: Add Sphinx.add_enumerable_node() to add enumerable nodes for numfig feature * #1858: Add Sphinx.add_enumerable_node() to add enumerable nodes for numfig
feature
* #1286, #2099: Add ``sphinx.ext.autosectionlabel`` extension to allow reference * #1286, #2099: Add ``sphinx.ext.autosectionlabel`` extension to allow reference
sections using its title. Thanks to Tadhg O'Higgins. sections using its title. Thanks to Tadhg O'Higgins.
* #1854: Allow to choose Janome for Japanese splitter. * #1854: Allow to choose Janome for Japanese splitter.
* #1853: support custom text splitter on html search with ``language='ja'``. * #1853: support custom text splitter on html search with ``language='ja'``.
* #2320: classifier of glossary terms can be used for index entries grouping key. * #2320: classifier of glossary terms can be used for index entries grouping key
The classifier also be used for translation. See also :ref:`glossary-directive`. The classifier also be used for translation. See also
* #2308: Define ``\tablecontinued`` macro to redefine the style of continued label for :ref:`glossary-directive`.
longtables. * #2308: Define ``\tablecontinued`` macro to redefine the style of continued
* Select an image by similarity if multiple images are globbed by ``.. image:: filename.*`` label for longtables.
* #1921: Support figure substitutions by :confval:`language` and :confval:`figure_language_filename` * Select an image by similarity if multiple images are globbed by
* #2245: Add ``latex_elements["passoptionstopackages"]`` option to call PassOptionsToPackages ``.. image:: filename.*``
in early stage of preambles. * #1921: Support figure substitutions by :confval:`language` and
:confval:`figure_language_filename`
* #2245: Add ``latex_elements["passoptionstopackages"]`` option to call
PassOptionsToPackages in early stage of preambles.
* #2340: Math extension: support alignment of multiple equations for MathJax. * #2340: Math extension: support alignment of multiple equations for MathJax.
* #2338: Define ``\titleref`` macro to redefine the style of ``title-reference`` roles. * #2338: Define ``\titleref`` macro to redefine the style of ``title-reference``
* Define ``\menuselection`` and ``\accelerator`` macros to redefine the style of `menuselection` roles. roles.
* Define ``\menuselection`` and ``\accelerator`` macros to redefine the style of
`menuselection` roles.
* Define ``\crossref`` macro to redefine the style of references * Define ``\crossref`` macro to redefine the style of references
* #2301: Texts in the classic html theme should be hyphenated. * #2301: Texts in the classic html theme should be hyphenated.
* #2355: Define ``\termref`` macro to redefine the style of ``term`` roles. * #2355: Define ``\termref`` macro to redefine the style of ``term`` roles.
* Add :confval:`suppress_warnings` to suppress arbitrary warning message (experimental) * Add :confval:`suppress_warnings` to suppress arbitrary warning message
(experimental)
* #2229: Fix no warning is given for unknown options * #2229: Fix no warning is given for unknown options
* #2327: Add `latex_toplevel_sectioning` to switch the top level sectioning of LaTeX document. * #2327: Add `latex_toplevel_sectioning` to switch the top level sectioning of
LaTeX document.
Bugs fixed Bugs fixed
---------- ----------
@ -2715,14 +2782,16 @@ Bugs fixed
* #794: Fix date formatting in latex output is not localized * #794: Fix date formatting in latex output is not localized
* Remove ``image/gif`` from supported_image_types of LaTeX writer (#2272) * Remove ``image/gif`` from supported_image_types of LaTeX writer (#2272)
* Fix ValueError is raised if LANGUAGE is empty string * Fix ValueError is raised if LANGUAGE is empty string
* Fix unpack warning is shown when the directives generated from ``Sphinx.add_crossref_type`` is used * Fix unpack warning is shown when the directives generated from
``Sphinx.add_crossref_type`` is used
* The default highlight language is now ``default``. This means that source code * The default highlight language is now ``default``. This means that source code
is highlighted as Python 3 (which is mostly a superset of Python 2) if possible. is highlighted as Python 3 (which is mostly a superset of Python 2) if possible.
To get the old behavior back, add ``highlight_language = "python"`` to conf.py. To get the old behavior back, add ``highlight_language = "python"`` to conf.py.
* #2329: Refresh environment forcedly if source directory has changed. * #2329: Refresh environment forcedly if source directory has changed.
* #2331: Fix code-blocks are filled by block in dvi; remove ``xcdraw`` option from * #2331: Fix code-blocks are filled by block in dvi; remove ``xcdraw`` option from
xcolor package xcolor package
* Fix the confval type checker emits warnings if unicode is given to confvals which expects string value * Fix the confval type checker emits warnings if unicode is given to confvals
which expects string value
* #2360: Fix numref in LaTeX output is broken * #2360: Fix numref in LaTeX output is broken
* #2361: Fix additional paragraphs inside the "compound" directive are indented * #2361: Fix additional paragraphs inside the "compound" directive are indented
* #2364: Fix KeyError 'rootSymbol' on Sphinx upgrade from older version. * #2364: Fix KeyError 'rootSymbol' on Sphinx upgrade from older version.
@ -2760,13 +2829,16 @@ Bugs fixed
* #2265: Fix babel is used in spite of disabling it on ``latex_elements`` * #2265: Fix babel is used in spite of disabling it on ``latex_elements``
* #2295: Avoid mutating dictionary errors while enumerating members in autodoc * #2295: Avoid mutating dictionary errors while enumerating members in autodoc
with Python 3 with Python 3
* #2291: Fix pdflatex "Counter too large" error from footnotes inside tables of contents * #2291: Fix pdflatex "Counter too large" error from footnotes inside tables of
contents
* #2292: Fix some footnotes disappear from LaTeX output * #2292: Fix some footnotes disappear from LaTeX output
* #2287: ``sphinx.transforms.Locale`` always uses rst parser. Sphinx i18n feature should * #2287: ``sphinx.transforms.Locale`` always uses rst parser. Sphinx i18n
support parsers that specified source_parsers. feature should support parsers that specified source_parsers.
* #2290: Fix ``sphinx.ext.mathbase`` use of amsfonts may break user choice of math fonts * #2290: Fix ``sphinx.ext.mathbase`` use of amsfonts may break user choice of
math fonts
* #2324: Print a hint how to increase the recursion limit when it is hit. * #2324: Print a hint how to increase the recursion limit when it is hit.
* #1565, #2229: Revert new warning; the new warning will be triggered from version 1.4 on. * #1565, #2229: Revert new warning; the new warning will be triggered from
version 1.4 on.
* #2329: Refresh environment forcedly if source directory has changed. * #2329: Refresh environment forcedly if source directory has changed.
* #2019: Fix the domain objects in search result are not escaped * #2019: Fix the domain objects in search result are not escaped
@ -2808,20 +2880,23 @@ Bugs fixed
* #2168: Fix raw directive does not work for text writer * #2168: Fix raw directive does not work for text writer
* #2171: Fix cannot linkcheck url with unicode * #2171: Fix cannot linkcheck url with unicode
* #2182: LaTeX: support image file names with more than 1 dots * #2182: LaTeX: support image file names with more than 1 dots
* #2189: Fix previous sibling link for first file in subdirectory uses last file, not * #2189: Fix previous sibling link for first file in subdirectory uses last
intended previous from root toctree file, not intended previous from root toctree
* #2003: Fix decode error under python2 (only) when ``make linkcheck`` is run * #2003: Fix decode error under python2 (only) when ``make linkcheck`` is run
* #2186: Fix LaTeX output of \mathbb in math * #2186: Fix LaTeX output of \mathbb in math
* #1480, #2188: LaTeX: Support math in section titles * #1480, #2188: LaTeX: Support math in section titles
* #2071: Fix same footnote in more than two section titles => LaTeX/PDF Bug * #2071: Fix same footnote in more than two section titles => LaTeX/PDF Bug
* #2040: Fix UnicodeDecodeError in sphinx-apidoc when author contains non-ascii characters * #2040: Fix UnicodeDecodeError in sphinx-apidoc when author contains non-ascii
* #2193: Fix shutil.SameFileError if source directory and destination directory are same characters
* #2178: Fix unparsable C++ cross-reference when referencing a function with :cpp:any: * #2193: Fix shutil.SameFileError if source directory and destination directory
are same
* #2178: Fix unparsable C++ cross-reference when referencing a function with
:cpp:any:
* #2206: Fix Sphinx latex doc build failed due to a footnotes * #2206: Fix Sphinx latex doc build failed due to a footnotes
* #2201: Fix wrong table caption for tables with over 30 rows * #2201: Fix wrong table caption for tables with over 30 rows
* #2213: Set <blockquote> in the classic theme to fit with <p> * #2213: Set <blockquote> in the classic theme to fit with <p>
* #1815: Fix linkcheck does not raise an exception if warniserror set to true and link is * #1815: Fix linkcheck does not raise an exception if warniserror set to true
broken and link is broken
* #2197: Fix slightly cryptic error message for missing index.rst file * #2197: Fix slightly cryptic error message for missing index.rst file
* #1894: Unlisted phony targets in quickstart Makefile * #1894: Unlisted phony targets in quickstart Makefile
* #2125: Fix unifies behavior of collapsed fields (``GroupedField`` and ``TypedField``) * #2125: Fix unifies behavior of collapsed fields (``GroupedField`` and ``TypedField``)
@ -2900,36 +2975,40 @@ Bugs fixed
* #1923: Use babel features only if the babel latex element is nonempty. * #1923: Use babel features only if the babel latex element is nonempty.
* #1942: Fix a KeyError in websupport. * #1942: Fix a KeyError in websupport.
* #1903: Fix strange id generation for glossary terms. * #1903: Fix strange id generation for glossary terms.
* ``make text`` will crush if a definition list item has more than 1 classifiers as: * ``make text`` will crush if a definition list item has more than 1 classifiers
``term : classifier1 : classifier2``. as: ``term : classifier1 : classifier2``.
* #1855: make gettext generates broken po file for definition lists with classifier. * #1855: make gettext generates broken po file for definition lists with
* #1869: Fix problems when dealing with files containing non-ASCII characters. Thanks to classifier.
Marvin Schmidt. * #1869: Fix problems when dealing with files containing non-ASCII characters.
Thanks to Marvin Schmidt.
* #1798: Fix building LaTeX with references in titles. * #1798: Fix building LaTeX with references in titles.
* #1725: On py2 environment, doctest with using non-ASCII characters causes * #1725: On py2 environment, doctest with using non-ASCII characters causes
``'ascii' codec can't decode byte`` exception. ``'ascii' codec can't decode byte`` exception.
* #1540: Fix RuntimeError with circular referenced toctree * #1540: Fix RuntimeError with circular referenced toctree
* #1983: i18n translation feature breaks references which uses section name. * #1983: i18n translation feature breaks references which uses section name.
* #1990: Use caption of toctree to title of \tableofcontents in LaTeX * #1990: Use caption of toctree to title of \tableofcontents in LaTeX
* #1987: Fix ampersand is ignored in ``:menuselection:`` and ``:guilabel:`` on LaTeX builder * #1987: Fix ampersand is ignored in ``:menuselection:`` and ``:guilabel:``
* #1994: More supporting non-standard parser (like recommonmark parser) for Translation and on LaTeX builder
WebSupport feature. Now node.rawsource is fall backed to node.astext() during docutils * #1994: More supporting non-standard parser (like recommonmark parser) for
transforming. Translation and WebSupport feature. Now node.rawsource is fall backed to
* #1989: "make blahblah" on Windows indicate help messages for sphinx-build every time. node.astext() during docutils transforming.
It was caused by wrong make.bat that generated by Sphinx-1.3.0/1.3.1. * #1989: "make blahblah" on Windows indicate help messages for sphinx-build
* On Py2 environment, conf.py that is generated by sphinx-quickstart should have u prefixed every time. It was caused by wrong make.bat that generated by
config value for 'version' and 'release'. Sphinx-1.3.0/1.3.1.
* On Py2 environment, conf.py that is generated by sphinx-quickstart should have
u prefixed config value for 'version' and 'release'.
* #2102: On Windows + Py3, using ``|today|`` and non-ASCII date format will raise * #2102: On Windows + Py3, using ``|today|`` and non-ASCII date format will raise
UnicodeEncodeError. UnicodeEncodeError.
* #1974: UnboundLocalError: local variable 'domain' referenced before assignment when * #1974: UnboundLocalError: local variable 'domain' referenced before assignment
using `any` role and `sphinx.ext.intersphinx` in same time. when using `any` role and `sphinx.ext.intersphinx` in same time.
* #2121: multiple words search doesn't find pages when words across on the page title and * #2121: multiple words search doesn't find pages when words across on the page
the page content. title and the page content.
* #1884, #1885: plug-in html themes cannot inherit another plug-in theme. Thanks to * #1884, #1885: plug-in html themes cannot inherit another plug-in theme. Thanks
Suzumizaki. to Suzumizaki.
* #1818: `sphinx.ext.todo` directive generates broken html class attribute as * #1818: `sphinx.ext.todo` directive generates broken html class attribute as
'admonition-' when :confval:`language` is specified with non-ASCII linguistic area like 'admonition-' when :confval:`language` is specified with non-ASCII linguistic
'ru' or 'ja'. To fix this, now ``todo`` directive can use ``:class:`` option. area like 'ru' or 'ja'. To fix this, now ``todo`` directive can use
``:class:`` option.
* #2140: Fix footnotes in table has broken in LaTeX * #2140: Fix footnotes in table has broken in LaTeX
* #2127: MecabBinder for html searching feature doesn't work with Python 3. * #2127: MecabBinder for html searching feature doesn't work with Python 3.
Thanks to Tomoko Uchida. Thanks to Tomoko Uchida.
@ -2993,8 +3072,8 @@ Bugs fixed
begin with -, / or +. Thanks to Takayuki Hirai. begin with -, / or +. Thanks to Takayuki Hirai.
* #1753: C++, added missing support for more complex declarations. * #1753: C++, added missing support for more complex declarations.
* #1700: Add ``:caption:`` option for :rst:dir:`toctree`. * #1700: Add ``:caption:`` option for :rst:dir:`toctree`.
* #1742: ``:name:`` option is provided for :rst:dir:`toctree`, :rst:dir:`code-block` and * #1742: ``:name:`` option is provided for :rst:dir:`toctree`, :rst:dir:`code-block`
:rst:dir:`literalinclude` directives. and :rst:dir:`literalinclude` directives.
* #1756: Incorrect section titles in search that was introduced from 1.3b3. * #1756: Incorrect section titles in search that was introduced from 1.3b3.
* #1746: C++, fixed name lookup procedure, and added missing lookups in declarations. * #1746: C++, fixed name lookup procedure, and added missing lookups in declarations.
* #1765: C++, fix old id generation to use fully qualified names. * #1765: C++, fix old id generation to use fully qualified names.

View File

@ -46,7 +46,8 @@ This is the current list of contributed extensions in that repository:
- coffeedomain: a domain for (auto)documenting CoffeeScript source code - coffeedomain: a domain for (auto)documenting CoffeeScript source code
- context: a builder for ConTeXt - context: a builder for ConTeXt
- disqus: embed Disqus comments in documents - disqus: embed Disqus comments in documents
- documentedlist: converts a Python list to a table in the generated documentation - documentedlist: converts a Python list to a table in the generated
documentation
- doxylink: Link to external Doxygen-generated HTML documentation - doxylink: Link to external Doxygen-generated HTML documentation
- domaintools_: A tool for easy domain creation - domaintools_: A tool for easy domain creation
- email: obfuscate email addresses - email: obfuscate email addresses
@ -76,7 +77,8 @@ This is the current list of contributed extensions in that repository:
- nicovideo: embed videos from nicovideo - nicovideo: embed videos from nicovideo
- nwdiag: embed network diagrams by using nwdiag_ - nwdiag: embed network diagrams by using nwdiag_
- omegat: support tools to collaborate with OmegaT_ (Sphinx 1.1 needed) - omegat: support tools to collaborate with OmegaT_ (Sphinx 1.1 needed)
- osaka: convert standard Japanese doc to Osaka dialect (this is a joke extension) - osaka: convert standard Japanese doc to Osaka dialect (this is a joke
extension)
- paverutils: an alternate integration of Sphinx with Paver_ - paverutils: an alternate integration of Sphinx with Paver_
- phpdomain: an extension for PHP support - phpdomain: an extension for PHP support
- plantuml: embed UML diagram by using PlantUML_ - plantuml: embed UML diagram by using PlantUML_
@ -96,7 +98,8 @@ This is the current list of contributed extensions in that repository:
- sword: an extension inserting Bible verses from Sword_ - sword: an extension inserting Bible verses from Sword_
- tikz: draw pictures with the `TikZ/PGF LaTeX package`_ - tikz: draw pictures with the `TikZ/PGF LaTeX package`_
- traclinks: create TracLinks_ to a Trac_ instance from within Sphinx - traclinks: create TracLinks_ to a Trac_ instance from within Sphinx
- versioning: Sphinx extension that allows building versioned docs for self-hosting - versioning: Sphinx extension that allows building versioned docs for
self-hosting
- whooshindex: whoosh indexer extension - whooshindex: whoosh indexer extension
- youtube: embed videos from YouTube_ - youtube: embed videos from YouTube_
- zopeext: provide an ``autointerface`` directive for using `Zope interfaces`_ - zopeext: provide an ``autointerface`` directive for using `Zope interfaces`_

View File

@ -145,9 +145,9 @@ Sphinx core events
------------------ ------------------
These events are known to the core. The arguments shown are given to the These events are known to the core. The arguments shown are given to the
registered event handlers. Use :meth:`.Sphinx.connect` in an extension's ``setup`` registered event handlers. Use :meth:`.Sphinx.connect` in an extension's
function (note that ``conf.py`` can also have a ``setup`` function) to connect ``setup`` function (note that ``conf.py`` can also have a ``setup`` function) to
handlers to the events. Example: connect handlers to the events. Example:
.. code-block:: python .. code-block:: python

View File

@ -171,6 +171,11 @@ The following is a list of deprecated interfaces.
- 4.0 - 4.0
- N/A - N/A
* - ``sphinx.ext.apidoc.makename()``
- 2.1
- 4.0
- ``sphinx.ext.apidoc.module_join()``
* - ``sphinx.ext.autodoc.importer.MockFinder`` * - ``sphinx.ext.autodoc.importer.MockFinder``
- 2.1 - 2.1
- 4.0 - 4.0
@ -1066,7 +1071,9 @@ The following is a list of deprecated interfaces.
* - ``sphinx.websupport`` * - ``sphinx.websupport``
- 1.6 - 1.6
- 2.0 - 2.0
- `sphinxcontrib-websupport <https://pypi.org/project/sphinxcontrib-websupport/>`_ - `sphinxcontrib-websupport`_
.. _sphinxcontrib-websupport: https://pypi.org/project/sphinxcontrib-websupport/
* - ``StandaloneHTMLBuilder.css_files`` * - ``StandaloneHTMLBuilder.css_files``
- 1.6 - 1.6

View File

@ -56,8 +56,8 @@ Logging API
:meth:`SphinxLoggerAdapter.warning`. :meth:`SphinxLoggerAdapter.warning`.
**color** **color**
The color of logs. By default, info and verbose level logs are not colored, The color of logs. By default, info and verbose level logs are not
and debug level ones are colored as ``"darkgray"``. colored, and debug level ones are colored as ``"darkgray"``.
.. autofunction:: pending_logging() .. autofunction:: pending_logging()

View File

@ -138,8 +138,8 @@ Both APIs parse the content into a given node. They are used like this::
.. deprecated:: 1.7 .. deprecated:: 1.7
Until Sphinx-1.6, ``sphinx.ext.autodoc.AutodocReporter`` is used for this purpose. Until Sphinx-1.6, ``sphinx.ext.autodoc.AutodocReporter`` is used for this
For now, it is replaced by ``switch_source_input()``. purpose. For now, it is replaced by ``switch_source_input()``.
If you don't need the wrapping node, you can use any concrete node type and If you don't need the wrapping node, you can use any concrete node type and
return ``node.children`` from the Directive. return ``node.children`` from the Directive.

View File

@ -37,9 +37,6 @@ How do I...
You'll still need to mark up classes and such, but the headings and code You'll still need to mark up classes and such, but the headings and code
examples come through cleanly. examples come through cleanly.
... create HTML slides from Sphinx documents?
See the "Hieroglyph" package at https://github.com/nyergler/hieroglyph.
For many more extensions and other contributed stuff, see the sphinx-contrib_ For many more extensions and other contributed stuff, see the sphinx-contrib_
repository. repository.
@ -83,7 +80,8 @@ GitHub Pages
Sphinx HTML output properly. Sphinx HTML output properly.
MediaWiki MediaWiki
See https://bitbucket.org/kevindunn/sphinx-wiki/wiki/Home, a project by Kevin Dunn. See https://bitbucket.org/kevindunn/sphinx-wiki/wiki/Home, a project by
Kevin Dunn.
Google Analytics Google Analytics
You can use a custom ``layout.html`` template, like this: You can use a custom ``layout.html`` template, like this:

View File

@ -17,10 +17,10 @@ docs have a look at `Epydoc <http://epydoc.sourceforge.net/>`_, which also
understands reST. understands reST.
For a great "introduction" to writing docs in general -- the whys and hows, see For a great "introduction" to writing docs in general -- the whys and hows, see
also `Write the docs <https://write-the-docs.readthedocs.io/>`_, written by Eric also `Write the docs`_, written by Eric Holscher.
Holscher.
.. _rinohtype: https://github.com/brechtm/rinohtype .. _rinohtype: https://github.com/brechtm/rinohtype
.. _Write the docs: http://www.writethedocs.org/guide/writing/beginners-guide-to-docs/
Conversion from other systems Conversion from other systems
----------------------------- -----------------------------

View File

@ -4,7 +4,8 @@ sphinx-apidoc
Synopsis Synopsis
-------- --------
**sphinx-apidoc** [*OPTIONS*] -o <*OUTPUT_PATH*> <*MODULE_PATH*> [*EXCLUDE_PATTERN*, ...] **sphinx-apidoc** [*OPTIONS*] -o <*OUTPUT_PATH*> <*MODULE_PATH*>
[*EXCLUDE_PATTERN*, ...]
Description Description
----------- -----------

View File

@ -302,7 +302,8 @@ variables to customize behavior:
.. describe:: SPHINXOPTS .. describe:: SPHINXOPTS
Additional options for :program:`sphinx-build`. Additional options for :program:`sphinx-build`. These options can
also be set via the shortcut variable **O** (capital 'o').
.. _when-deprecation-warnings-are-displayed: .. _when-deprecation-warnings-are-displayed:

View File

@ -49,8 +49,9 @@ Python :mod:`ConfigParser` module) and has the following structure:
* The **inherit** setting gives the name of a "base theme", or ``none``. The * The **inherit** setting gives the name of a "base theme", or ``none``. The
base theme will be used to locate missing templates (most themes will not have base theme will be used to locate missing templates (most themes will not have
to supply most templates if they use ``basic`` as the base theme), its options to supply most templates if they use ``basic`` as the base theme), its options
will be inherited, and all of its static files will be used as well. If you want will be inherited, and all of its static files will be used as well. If you
to also inherit the stylesheet, include it via CSS' ``@import`` in your own. want to also inherit the stylesheet, include it via CSS' ``@import`` in your
own.
* The **stylesheet** setting gives the name of a CSS file which will be * The **stylesheet** setting gives the name of a CSS file which will be
referenced in the HTML header. If you need more than one CSS file, either referenced in the HTML header. If you need more than one CSS file, either

View File

@ -63,7 +63,7 @@ This dict can then be used as context for templates. The goal is to be easy to
integrate with your existing templating system. An example using `Jinja2 integrate with your existing templating system. An example using `Jinja2
<http://jinja.pocoo.org/>`_ is: <http://jinja.pocoo.org/>`_ is:
.. sourcecode:: html+jinja .. code-block:: html+jinja
{%- extends "layout.html" %} {%- extends "layout.html" %}

View File

@ -61,7 +61,7 @@ The builder's "name" must be given to the **-b** command-line option of
.. versionadded:: 1.0 .. versionadded:: 1.0
.. module:: sphinx.builders.htmlhelp .. module:: sphinxcontrib.htmlhelp
.. class:: HTMLHelpBuilder .. class:: HTMLHelpBuilder
This builder produces the same output as the standalone HTML builder, but This builder produces the same output as the standalone HTML builder, but

View File

@ -296,25 +296,26 @@ General configuration
Sphinx supports following warning types: Sphinx supports following warning types:
* app.add_node * ``app.add_node``
* app.add_directive * ``app.add_directive``
* app.add_role * ``app.add_role``
* app.add_generic_role * ``app.add_generic_role``
* app.add_source_parser * ``app.add_source_parser``
* download.not_readable * ``download.not_readable``
* image.not_readable * ``image.not_readable``
* ref.term * ``ref.term``
* ref.ref * ``ref.ref``
* ref.numref * ``ref.numref``
* ref.keyword * ``ref.keyword``
* ref.option * ``ref.option``
* ref.citation * ``ref.citation``
* ref.footnote * ``ref.footnote``
* ref.doc * ``ref.doc``
* ref.python * ``ref.python``
* misc.highlighting_failure * ``misc.highlighting_failure``
* toc.secnum * ``toc.secnum``
* epub.unknown_project_files * ``epub.unknown_project_files``
* ``autosectionlabel.*``
You can choose from these types. You can choose from these types.
@ -334,6 +335,10 @@ General configuration
Added ``ref.footnote`` Added ``ref.footnote``
.. versionchanged:: 2.1
Added ``autosectionlabel.*``
.. confval:: needs_sphinx .. confval:: needs_sphinx
If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will If set to a ``major.minor`` version string like ``'1.1'``, Sphinx will

View File

@ -40,10 +40,8 @@ you can also enable the :mod:`napoleon <sphinx.ext.napoleon>` extension.
:mod:`napoleon <sphinx.ext.napoleon>` is a preprocessor that converts your :mod:`napoleon <sphinx.ext.napoleon>` is a preprocessor that converts your
docstrings to correct reStructuredText before :mod:`autodoc` processes them. docstrings to correct reStructuredText before :mod:`autodoc` processes them.
.. _Google: .. _Google: https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings
https://github.com/google/styleguide/blob/gh-pages/pyguide.md#38-comments-and-docstrings .. _NumPy: https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
.. _NumPy:
https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt
Directives Directives

View File

@ -22,6 +22,16 @@ should check:
.. confval:: coverage_ignore_classes .. confval:: coverage_ignore_classes
.. confval:: coverage_ignore_pyobjects
List of `Python regular expressions`_.
If any of these regular expressions matches any part of the full import path
of a Python object, that Python object is excluded from the documentation
coverage report.
.. versionadded:: 2.1
.. confval:: coverage_c_path .. confval:: coverage_c_path
.. confval:: coverage_c_regexes .. confval:: coverage_c_regexes
@ -40,3 +50,5 @@ should check:
``False`` by default. ``False`` by default.
.. versionadded:: 1.1 .. versionadded:: 1.1
.. _Python regular expressions: https://docs.python.org/library/re

View File

@ -36,8 +36,8 @@ It adds this directive:
with ``lib.``, you can give ``:parts: -1`` to remove that prefix from the with ``lib.``, you can give ``:parts: -1`` to remove that prefix from the
displayed node names. displayed node names.
The directive also supports a ``private-bases`` flag option; if given, private base The directive also supports a ``private-bases`` flag option; if given,
classes (those whose name starts with ``_``) will be included. private base classes (those whose name starts with ``_``) will be included.
You can use ``caption`` option to give a caption to the diagram. You can use ``caption`` option to give a caption to the diagram.

View File

@ -17,8 +17,9 @@ There are two additional directives when using this extension:
``True``. ``True``.
.. versionadded:: 1.3.2 .. versionadded:: 1.3.2
This directive supports an ``class`` option that determines the class attribute This directive supports an ``class`` option that determines the class
for HTML output. If not given, the class defaults to ``admonition-todo``. attribute for HTML output. If not given, the class defaults to
``admonition-todo``.
.. rst:directive:: todolist .. rst:directive:: todolist
@ -46,8 +47,8 @@ Configuration
.. confval:: todo_link_only .. confval:: todo_link_only
If this is ``True``, :rst:dir:`todolist` produce output without file path and line, If this is ``True``, :rst:dir:`todolist` produce output without file path and
The default is ``False``. line, The default is ``False``.
.. versionadded:: 1.4 .. versionadded:: 1.4
@ -57,5 +58,5 @@ autodoc provides the following an additional event:
.. versionadded:: 1.5 .. versionadded:: 1.5
Emitted when a todo is defined. *node* is the defined ``sphinx.ext.todo.todo_node`` Emitted when a todo is defined. *node* is the defined
node. ``sphinx.ext.todo.todo_node`` node.

View File

@ -686,8 +686,8 @@ Glossary
(When the glossary is sorted, the first term determines the sort order.) (When the glossary is sorted, the first term determines the sort order.)
If you want to specify "grouping key" for general index entries, you can put a "key" If you want to specify "grouping key" for general index entries, you can put
as "term : key". For example:: a "key" as "term : key". For example::
.. glossary:: .. glossary::
@ -697,12 +697,12 @@ Glossary
Note that "key" is used for grouping key as is. Note that "key" is used for grouping key as is.
The "key" isn't normalized; key "A" and "a" become different groups. The "key" isn't normalized; key "A" and "a" become different groups.
The whole characters in "key" is used instead of a first character; it is used for The whole characters in "key" is used instead of a first character; it is
"Combining Character Sequence" and "Surrogate Pairs" grouping key. used for "Combining Character Sequence" and "Surrogate Pairs" grouping key.
In i18n situation, you can specify "localized term : key" even if original text only In i18n situation, you can specify "localized term : key" even if original
have "term" part. In this case, translated "localized term" will be categorized in text only have "term" part. In this case, translated "localized term" will be
"key" group. categorized in "key" group.
.. versionadded:: 0.6 .. versionadded:: 0.6
You can now give the glossary directive a ``:sorted:`` flag that will You can now give the glossary directive a ``:sorted:`` flag that will
@ -958,16 +958,16 @@ this reason, the following directive exists:
.. warning:: .. warning::
Tables with more than 30 rows are rendered using ``longtable``, not Tables with more than 30 rows are rendered using ``longtable``, not
``tabulary``, in order to allow pagebreaks. The ``L``, ``R``, ... specifiers ``tabulary``, in order to allow pagebreaks. The ``L``, ``R``, ...
do not work for these tables. specifiers do not work for these tables.
Tables that contain list-like elements such as object descriptions, Tables that contain list-like elements such as object descriptions,
blockquotes or any kind of lists cannot be set out of the box with blockquotes or any kind of lists cannot be set out of the box with
``tabulary``. They are therefore set with the standard LaTeX ``tabular`` (or ``tabulary``. They are therefore set with the standard LaTeX ``tabular``
``longtable``) environment if you don't give a ``tabularcolumns`` directive. (or ``longtable``) environment if you don't give a ``tabularcolumns``
If you do, the table will be set with ``tabulary`` but you must use the directive. If you do, the table will be set with ``tabulary`` but you
``p{width}`` construct (or Sphinx's ``\X`` and ``\Y`` specifiers described must use the ``p{width}`` construct (or Sphinx's ``\X`` and ``\Y``
below) for the columns containing these elements. specifiers described below) for the columns containing these elements.
Literal blocks do not work with ``tabulary`` at all, so tables containing Literal blocks do not work with ``tabulary`` at all, so tables containing
a literal block are always set with ``tabular``. The verbatim environment a literal block are always set with ``tabular``. The verbatim environment
@ -996,10 +996,11 @@ this reason, the following directive exists:
.. versionchanged:: 1.6 .. versionchanged:: 1.6
Merged cells from complex grid tables (either multi-row, multi-column, or Merged cells from complex grid tables (either multi-row, multi-column, or
both) now allow blockquotes, lists, literal blocks, ... as do regular cells. both) now allow blockquotes, lists, literal blocks, ... as do regular
cells.
Sphinx's merged cells interact well with ``p{width}``, ``\X{a}{b}``, ``Y{f}`` Sphinx's merged cells interact well with ``p{width}``, ``\X{a}{b}``,
and tabulary's columns. ``Y{f}`` and tabulary's columns.
.. note:: .. note::

View File

@ -128,17 +128,28 @@ declarations:
This directive will also cause an entry in the global module index. This directive will also cause an entry in the global module index.
The ``platform`` option, if present, is a comma-separated list of the .. rubric:: options
platforms on which the module is available (if it is available on all
platforms, the option should be omitted). The keys are short identifiers;
examples that are in use include "IRIX", "Mac", "Windows", and "Unix". It is
important to use a key which has already been used when applicable.
The ``synopsis`` option should consist of one sentence describing the .. rst:directive:option:: platform: platforms
module's purpose -- it is currently only used in the Global Module Index. :type: comma separated list
The ``deprecated`` option can be given (with no value) to mark a module as Indicate platforms which the module is available (if it is available on
deprecated; it will be designated as such in various locations then. all platforms, the option should be omitted). The keys are short
identifiers; examples that are in use include "IRIX", "Mac", "Windows"
and "Unix". It is important to use a key which has already been used when
applicable.
.. rst:directive:option:: synopsis: purpose
:type: text
Consist of one sentence describing the module's purpose -- it is currently
only used in the Global Module Index.
.. rst:directive:option:: deprecated
:type: no argument
Mark a module as deprecated; it will be designated as such in various
locations then.
.. rst:directive:: .. py:currentmodule:: name .. rst:directive:: .. py:currentmodule:: name
@ -169,12 +180,14 @@ The following directives are provided for module and class contents:
This information can (in any ``py`` directive) optionally be given in a This information can (in any ``py`` directive) optionally be given in a
structured form, see :ref:`info-field-lists`. structured form, see :ref:`info-field-lists`.
The ``async`` option can be given (with no value) to indicate the function is .. rubric:: options
an async method.
.. versionchanged:: 2.1 .. rst:directive:option:: async
:type: no value
``:async:`` option added. Indicate the function is an async function.
.. versionadded:: 2.1
.. rst:directive:: .. py:data:: name .. rst:directive:: .. py:data:: name
@ -223,19 +236,43 @@ The following directives are provided for module and class contents:
described for ``function``. See also :ref:`signatures` and described for ``function``. See also :ref:`signatures` and
:ref:`info-field-lists`. :ref:`info-field-lists`.
The ``async`` option can be given (with no value) to indicate the method is .. rubric:: options
an async method.
The ``classmethod`` option and ``staticmethod`` option can be given (with .. rst:directive:option:: abstractmethod
no value) to indicate the method is a class method (or a static method). :type: no value
The ``property`` option can be given (with no value) to indicate the method Indicate the method is an abstract method.
is a property.
.. versionchanged:: 2.1 .. versionadded:: 2.1
.. rst:directive:option:: async
:type: no value
Indicate the method is an async method.
.. versionadded:: 2.1
.. rst:directive:option:: classmethod
:type: no value
Indicate the method is a class method.
.. versionadded:: 2.1
.. rst:directive:option:: property
:type: no value
Indicate the method is a property.
.. versionadded:: 2.1
.. rst:directive:option:: staticmethod
:type: no value
Indicate the method is a static method.
.. versionadded:: 2.1
``:async:``, ``:classmethod:``, ``:property:`` and ``:staticmethod:``
options added.
.. rst:directive:: .. py:staticmethod:: name(parameters) .. rst:directive:: .. py:staticmethod:: name(parameters)
@ -720,7 +757,8 @@ visibility statement (``public``, ``private`` or ``protected``).
.. cpp:enum-struct:: protected MyScopedVisibilityEnum : std::underlying_type<MySpecificEnum>::type .. cpp:enum-struct:: protected MyScopedVisibilityEnum : std::underlying_type<MySpecificEnum>::type
A scoped enum with non-default visibility, and with a specified underlying type. A scoped enum with non-default visibility, and with a specified
underlying type.
.. rst:directive:: .. cpp:enumerator:: name .. rst:directive:: .. cpp:enumerator:: name
.. cpp:enumerator:: name = constant .. cpp:enumerator:: name = constant
@ -760,7 +798,8 @@ visibility statement (``public``, ``private`` or ``protected``).
**Valid Expressions** **Valid Expressions**
- :cpp:expr:`*r`, when :cpp:expr:`r` is dereferenceable. - :cpp:expr:`*r`, when :cpp:expr:`r` is dereferenceable.
- :cpp:expr:`++r`, with return type :cpp:expr:`It&`, when :cpp:expr:`r` is incrementable. - :cpp:expr:`++r`, with return type :cpp:expr:`It&`, when
:cpp:expr:`r` is incrementable.
This will render as follows: This will render as follows:
@ -799,11 +838,12 @@ Anonymous Entities
~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~
C++ supports anonymous namespaces, classes, enums, and unions. C++ supports anonymous namespaces, classes, enums, and unions.
For the sake of documentation they must be given some name that starts with ``@``, For the sake of documentation they must be given some name that starts with
e.g., ``@42`` or ``@data``. ``@``, e.g., ``@42`` or ``@data``.
These names can also be used in cross-references and (type) expressions, These names can also be used in cross-references and (type) expressions,
though nested symbols will be found even when omitted. though nested symbols will be found even when omitted.
The ``@...`` name will always be rendered as **[anonymous]** (possibly as a link). The ``@...`` name will always be rendered as **[anonymous]** (possibly as a
link).
Example:: Example::
@ -835,8 +875,8 @@ Explicit ref: :cpp:var:`Data::@data::a`. Short-hand ref: :cpp:var:`Data::a`.
Aliasing Declarations Aliasing Declarations
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
Sometimes it may be helpful list declarations elsewhere than their main documentation, Sometimes it may be helpful list declarations elsewhere than their main
e.g., when creating a synopsis of a class interface. documentation, e.g., when creating a synopsis of a class interface.
The following directive can be used for this purpose. The following directive can be used for this purpose.
.. rst:directive:: .. cpp:alias:: name or function signature .. rst:directive:: .. cpp:alias:: name or function signature
@ -1079,7 +1119,8 @@ These roles link to the given declaration types:
be properly qualified relative to the position of the link. be properly qualified relative to the position of the link.
.. versionadded:: 2.0 .. versionadded:: 2.0
The :rst:role:`cpp:struct` role as alias for the :rst:role:`cpp:class` role. The :rst:role:`cpp:struct` role as alias for the :rst:role:`cpp:class`
role.
.. admonition:: Note on References with Templates Parameters/Arguments .. admonition:: Note on References with Templates Parameters/Arguments
@ -1126,7 +1167,8 @@ References using the :rst:role:`cpp:func` role:
- Specific overload: ``void C::f()``, :cpp:func:`void 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(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)``, :cpp:func:`void C::f(double)`
- Specific overload: ``void C::f(double) const``, :cpp:func:`void C::f(double) const` - Specific overload: ``void C::f(double) const``,
:cpp:func:`void C::f(double) const`
Note that the :confval:`add_function_parentheses` configuration variable Note that the :confval:`add_function_parentheses` configuration variable
does not influence specific overload references. does not influence specific overload references.
@ -1155,8 +1197,8 @@ and template arguments for the prefix of qualified names. For example:
- ``template\<typename TOuter> template\<typename TInner> Wrapper::Outer<TOuter>::Inner`` - ``template\<typename TOuter> template\<typename TInner> Wrapper::Outer<TOuter>::Inner``
(:cpp:class:`template\<typename TOuter> template\<typename TInner> Wrapper::Outer<TOuter>::Inner`) (:cpp:class:`template\<typename TOuter> template\<typename TInner> Wrapper::Outer<TOuter>::Inner`)
Currently the lookup only succeed if the template parameter identifiers are equal strings. Currently the lookup only succeed if the template parameter identifiers are equal
That is, ``template\<typename UOuter> Wrapper::Outer`` will not work. strings. That is, ``template\<typename UOuter> Wrapper::Outer`` will not work.
As a shorthand notation, if a template parameter list is omitted, As a shorthand notation, if a template parameter list is omitted,
then the lookup will assume either a primary template or a non-template, then the lookup will assume either a primary template or a non-template,
@ -1447,8 +1489,8 @@ The reStructuredText domain (name **rst**) provides the following directives:
.. rubric:: options .. rubric:: options
.. rst:directive:option:: type .. rst:directive:option:: type: description of argument
:type: description for the option of directive :type: text
Describe the type of option value. Describe the type of option value.

View File

@ -343,9 +343,16 @@ class Sphinx:
status = (self.statuscode == 0 and status = (self.statuscode == 0 and
__('succeeded') or __('finished with problems')) __('succeeded') or __('finished with problems'))
if self._warncount: if self._warncount:
logger.info(bold(__('build %s, %s warning.', if self.warningiserror:
'build %s, %s warnings.', self._warncount) % msg = __('build %s, %s warning (with warnings treated as errors).',
(status, self._warncount))) 'build %s, %s warnings (with warnings treated as errors).',
self._warncount)
else:
msg = __('build %s, %s warning.',
'build %s, %s warnings.',
self._warncount)
logger.info(bold(msg % (status, self._warncount)))
else: else:
logger.info(bold(__('build %s.') % status)) logger.info(bold(__('build %s.') % status))

View File

@ -108,7 +108,8 @@ class CheckExternalLinksBuilder(Builder):
kwargs = { kwargs = {
'allow_redirects': True, 'allow_redirects': True,
'headers': { 'headers': {
'Accept': 'text/html,application/xhtml+xml;q=0.9,*/*;q=0.8' 'Accept': 'text/html,application/xhtml+xml;q=0.9,*/*;q=0.8',
'User-Agent': requests.useragent_header[0][1],
}, },
} }
if self.app.config.linkcheck_timeout: if self.app.config.linkcheck_timeout:

View File

@ -576,6 +576,7 @@ class PyMethod(PyObject):
option_spec = PyObject.option_spec.copy() option_spec = PyObject.option_spec.copy()
option_spec.update({ option_spec.update({
'abstractmethod': directives.flag,
'async': directives.flag, 'async': directives.flag,
'classmethod': directives.flag, 'classmethod': directives.flag,
'property': directives.flag, 'property': directives.flag,
@ -592,6 +593,8 @@ class PyMethod(PyObject):
def get_signature_prefix(self, sig): def get_signature_prefix(self, sig):
# type: (str) -> str # type: (str) -> str
prefix = [] prefix = []
if 'abstractmethod' in self.options:
prefix.append('abstract')
if 'async' in self.options: if 'async' in self.options:
prefix.append('async') prefix.append('async')
if 'classmethod' in self.options: if 'classmethod' in self.options:
@ -849,7 +852,6 @@ class PythonModuleIndex(Index):
last = entries[-1] last = entries[-1]
entries[-1] = IndexEntry(last[0], 1, last[2], last[3], entries[-1] = IndexEntry(last[0], 1, last[2], last[3],
last[4], last[5], last[6]) last[4], last[5], last[6])
entries.append(IndexEntry(stripped + package, 1, '', '', '', '', ''))
elif not prev_modname.startswith(package): elif not prev_modname.startswith(package):
# submodule without parent in list, add dummy entry # submodule without parent in list, add dummy entry
entries.append(IndexEntry(stripped + package, 1, '', '', '', '', '')) entries.append(IndexEntry(stripped + package, 1, '', '', '', '', ''))

View File

@ -139,6 +139,7 @@ class ReSTDirectiveOption(ReSTMarkup):
def add_target_and_index(self, name, sig, signode): def add_target_and_index(self, name, sig, signode):
# type: (str, str, addnodes.desc_signature) -> None # type: (str, str, addnodes.desc_signature) -> None
directive_name = self.current_directive
targetname = '-'.join([self.objtype, self.current_directive, name]) targetname = '-'.join([self.objtype, self.current_directive, name])
if targetname not in self.state.document.ids: if targetname not in self.state.document.ids:
signode['names'].append(targetname) signode['names'].append(targetname)
@ -146,12 +147,13 @@ class ReSTDirectiveOption(ReSTMarkup):
signode['first'] = (not self.names) signode['first'] = (not self.names)
self.state.document.note_explicit_target(signode) self.state.document.note_explicit_target(signode)
objname = ':'.join(filter(None, [directive_name, name]))
domain = cast(ReSTDomain, self.env.get_domain('rst')) domain = cast(ReSTDomain, self.env.get_domain('rst'))
domain.note_object(self.objtype, name, location=(self.env.docname, self.lineno)) domain.note_object(self.objtype, objname, location=(self.env.docname, self.lineno))
if self.current_directive: if directive_name:
key = name[0].upper() key = name[0].upper()
pair = [_('%s (directive)') % self.current_directive, pair = [_('%s (directive)') % directive_name,
_(':%s: (directive option)') % name] _(':%s: (directive option)') % name]
self.indexnode['entries'].append(('pair', '; '.join(pair), targetname, '', key)) self.indexnode['entries'].append(('pair', '; '.join(pair), targetname, '', key))
else: else:

View File

@ -442,7 +442,7 @@ class ProductionList(SphinxDirective):
name, tokens = rule.split(':', 1) name, tokens = rule.split(':', 1)
except ValueError: except ValueError:
break break
subnode = addnodes.production() subnode = addnodes.production(rule)
subnode['tokenname'] = name.strip() subnode['tokenname'] = name.strip()
if subnode['tokenname']: if subnode['tokenname']:
idname = nodes.make_id('grammar-token-%s' % subnode['tokenname']) idname = nodes.make_id('grammar-token-%s' % subnode['tokenname'])

View File

@ -56,6 +56,8 @@ template_dir = path.join(package_dir, 'templates', 'apidoc')
def makename(package, module): def makename(package, module):
# type: (str, str) -> str # type: (str, str) -> str
"""Join package and module with a dot.""" """Join package and module with a dot."""
warnings.warn('makename() is deprecated.',
RemovedInSphinx40Warning)
# Both package and module can be None/empty. # Both package and module can be None/empty.
if package: if package:
name = package name = package
@ -66,6 +68,12 @@ def makename(package, module):
return name return name
def module_join(*modnames):
# type: (*str) -> str
"""Join module names with dots."""
return '.'.join(filter(None, modnames))
def write_file(name, text, opts): def write_file(name, text, opts):
# type: (str, str, Any) -> None # type: (str, str, Any) -> None
"""Write the output file for module/package <name>.""" """Write the output file for module/package <name>."""
@ -97,7 +105,7 @@ def format_directive(module, package=None):
"""Create the automodule directive and add the options.""" """Create the automodule directive and add the options."""
warnings.warn('format_directive() is deprecated.', warnings.warn('format_directive() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning)
directive = '.. automodule:: %s\n' % makename(package, module) directive = '.. automodule:: %s\n' % module_join(package, module)
for option in OPTIONS: for option in OPTIONS:
directive += ' :%s:\n' % option directive += ' :%s:\n' % option
return directive return directive
@ -106,7 +114,7 @@ def format_directive(module, package=None):
def create_module_file(package, basename, opts): def create_module_file(package, basename, opts):
# type: (str, str, Any) -> None # type: (str, str, Any) -> None
"""Build the text of the file and write the file.""" """Build the text of the file and write the file."""
qualname = makename(package, basename) qualname = module_join(package, basename)
context = { context = {
'show_headings': not opts.noheadings, 'show_headings': not opts.noheadings,
'basename': basename, 'basename': basename,
@ -123,17 +131,18 @@ def create_package_file(root, master_package, subroot, py_files, opts, subs, is_
# build a list of sub packages (directories containing an INITPY file) # build a list of sub packages (directories containing an INITPY file)
subpackages = [sub for sub in subs if not subpackages = [sub for sub in subs if not
shall_skip(path.join(root, sub, INITPY), opts, excludes)] shall_skip(path.join(root, sub, INITPY), opts, excludes)]
subpackages = [makename(makename(master_package, subroot), pkgname) subpackages = [module_join(master_package, subroot, pkgname)
for pkgname in subpackages] for pkgname in subpackages]
# build a list of sub modules # build a list of sub modules
submodules = [path.splitext(sub)[0] for sub in py_files submodules = [path.splitext(sub)[0] for sub in py_files
if not shall_skip(path.join(root, sub), opts, excludes) and if not shall_skip(path.join(root, sub), opts, excludes) and
sub != INITPY] sub != INITPY]
submodules = [makename(master_package, makename(subroot, modname)) submodules = [module_join(master_package, subroot, modname)
for modname in submodules] for modname in submodules]
pkgname = module_join(master_package, subroot)
context = { context = {
'pkgname': makename(master_package, subroot), 'pkgname': pkgname,
'subpackages': subpackages, 'subpackages': subpackages,
'submodules': submodules, 'submodules': submodules,
'is_namespace': is_namespace, 'is_namespace': is_namespace,
@ -143,7 +152,7 @@ def create_package_file(root, master_package, subroot, py_files, opts, subs, is_
'show_headings': not opts.noheadings, 'show_headings': not opts.noheadings,
} }
text = ReSTRenderer(template_dir).render('package.rst', context) text = ReSTRenderer(template_dir).render('package.rst', context)
write_file(makename(master_package, subroot), text, opts) write_file(pkgname, text, opts)
if submodules and opts.separatemodules: if submodules and opts.separatemodules:
for submodule in submodules: for submodule in submodules:
@ -250,7 +259,7 @@ def recurse_tree(rootpath, excludes, opts):
if not is_namespace or len(py_files) > 0: if not is_namespace or len(py_files) > 0:
create_package_file(root, root_package, subpackage, create_package_file(root, root_package, subpackage,
py_files, opts, subs, is_namespace, excludes) py_files, opts, subs, is_namespace, excludes)
toplevels.append(makename(root_package, subpackage)) toplevels.append(module_join(root_package, subpackage))
else: else:
# if we are at the root level, we don't require it to be a package # if we are at the root level, we don't require it to be a package
assert root == rootpath and root_package is None assert root == rootpath and root_package is None

View File

@ -65,6 +65,7 @@ def identity(x):
ALL = object() ALL = object()
INSTANCEATTR = object() INSTANCEATTR = object()
SLOTSATTR = object()
def members_option(arg): def members_option(arg):
@ -363,8 +364,8 @@ class Documenter:
return False return False
return True return True
def format_args(self): def format_args(self, **kwargs):
# type: () -> str # type: (Any) -> str
"""Format the argument signature of *self.object*. """Format the argument signature of *self.object*.
Should return None if the object does not have a signature. Should return None if the object does not have a signature.
@ -383,8 +384,8 @@ class Documenter:
# directives of course) # directives of course)
return '.'.join(self.objpath) or self.modname return '.'.join(self.objpath) or self.modname
def format_signature(self): def format_signature(self, **kwargs):
# type: () -> str # type: (Any) -> str
"""Format the signature (arguments and return annotation) of the object. """Format the signature (arguments and return annotation) of the object.
Let the user process it via the ``autodoc-process-signature`` event. Let the user process it via the ``autodoc-process-signature`` event.
@ -395,6 +396,10 @@ class Documenter:
else: else:
# try to introspect the signature # try to introspect the signature
try: try:
try:
args = self.format_args(**kwargs)
except TypeError:
# retry without arguments for old documenters
args = self.format_args() args = self.format_args()
except Exception as err: except Exception as err:
logger.warning(__('error while formatting arguments for %s: %s') % logger.warning(__('error while formatting arguments for %s: %s') %
@ -954,15 +959,15 @@ class DocstringSignatureMixin:
return lines return lines
return super().get_doc(None, ignore) # type: ignore return super().get_doc(None, ignore) # type: ignore
def format_signature(self): def format_signature(self, **kwargs):
# type: () -> str # type: (Any) -> str
if self.args is None and self.env.config.autodoc_docstring_signature: # type: ignore if self.args is None and self.env.config.autodoc_docstring_signature: # type: ignore
# only act if a signature is not explicitly given already, and if # only act if a signature is not explicitly given already, and if
# the feature is enabled # the feature is enabled
result = self._find_signature() result = self._find_signature()
if result is not None: if result is not None:
self.args, self.retann = result self.args, self.retann = result
return super().format_signature() # type: ignore return super().format_signature(**kwargs) # type: ignore
class DocstringStripSignatureMixin(DocstringSignatureMixin): class DocstringStripSignatureMixin(DocstringSignatureMixin):
@ -970,8 +975,8 @@ class DocstringStripSignatureMixin(DocstringSignatureMixin):
Mixin for AttributeDocumenter to provide the Mixin for AttributeDocumenter to provide the
feature of stripping any function signature from the docstring. feature of stripping any function signature from the docstring.
""" """
def format_signature(self): def format_signature(self, **kwargs):
# type: () -> str # type: (Any) -> str
if self.args is None and self.env.config.autodoc_docstring_signature: # type: ignore if self.args is None and self.env.config.autodoc_docstring_signature: # type: ignore
# only act if a signature is not explicitly given already, and if # only act if a signature is not explicitly given already, and if
# the feature is enabled # the feature is enabled
@ -981,7 +986,7 @@ class DocstringStripSignatureMixin(DocstringSignatureMixin):
# DocstringSignatureMixin.format_signature. # DocstringSignatureMixin.format_signature.
# Documenter.format_signature use self.args value to format. # Documenter.format_signature use self.args value to format.
_args, self.retann = result _args, self.retann = result
return super().format_signature() return super().format_signature(**kwargs)
class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type: ignore class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type: ignore
@ -998,8 +1003,8 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
return (inspect.isfunction(member) or inspect.isbuiltin(member) or return (inspect.isfunction(member) or inspect.isbuiltin(member) or
(inspect.isroutine(member) and isinstance(parent, ModuleDocumenter))) (inspect.isroutine(member) and isinstance(parent, ModuleDocumenter)))
def format_args(self): def format_args(self, **kwargs):
# type: () -> str # type: (Any) -> str
if inspect.isbuiltin(self.object) or inspect.ismethoddescriptor(self.object): if inspect.isbuiltin(self.object) or inspect.ismethoddescriptor(self.object):
# cannot introspect arguments of a C function or method # cannot introspect arguments of a C function or method
return None return None
@ -1009,9 +1014,9 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
not inspect.isbuiltin(self.object) and not inspect.isbuiltin(self.object) and
not inspect.isclass(self.object) and not inspect.isclass(self.object) and
hasattr(self.object, '__call__')): hasattr(self.object, '__call__')):
args = Signature(self.object.__call__).format_args() args = Signature(self.object.__call__).format_args(**kwargs)
else: else:
args = Signature(self.object).format_args() args = Signature(self.object).format_args(**kwargs)
except TypeError: except TypeError:
if (inspect.is_builtin_class_method(self.object, '__new__') and if (inspect.is_builtin_class_method(self.object, '__new__') and
inspect.is_builtin_class_method(self.object, '__init__')): inspect.is_builtin_class_method(self.object, '__init__')):
@ -1022,10 +1027,10 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
# signature without the first argument. # signature without the first argument.
try: try:
sig = Signature(self.object.__new__, bound_method=True, has_retval=False) sig = Signature(self.object.__new__, bound_method=True, has_retval=False)
args = sig.format_args() args = sig.format_args(**kwargs)
except TypeError: except TypeError:
sig = Signature(self.object.__init__, bound_method=True, has_retval=False) sig = Signature(self.object.__init__, bound_method=True, has_retval=False)
args = sig.format_args() args = sig.format_args(**kwargs)
# escape backslashes for reST # escape backslashes for reST
args = args.replace('\\', '\\\\') args = args.replace('\\', '\\\\')
@ -1053,8 +1058,8 @@ class DecoratorDocumenter(FunctionDocumenter):
# must be lower than FunctionDocumenter # must be lower than FunctionDocumenter
priority = -1 priority = -1
def format_args(self): def format_args(self, **kwargs):
args = super().format_args() args = super().format_args(**kwargs)
if ',' in args: if ',' in args:
return args return args
else: else:
@ -1097,8 +1102,8 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
self.doc_as_attr = True self.doc_as_attr = True
return ret return ret
def format_args(self): def format_args(self, **kwargs):
# type: () -> str # type: (Any) -> str
# for classes, the relevant signature is the __init__ method's # for classes, the relevant signature is the __init__ method's
initmeth = self.get_attr(self.object, '__init__', None) initmeth = self.get_attr(self.object, '__init__', None)
# classes without __init__ method, default __init__ or # classes without __init__ method, default __init__ or
@ -1108,18 +1113,19 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
not(inspect.ismethod(initmeth) or inspect.isfunction(initmeth)): not(inspect.ismethod(initmeth) or inspect.isfunction(initmeth)):
return None return None
try: try:
return Signature(initmeth, bound_method=True, has_retval=False).format_args() sig = Signature(initmeth, bound_method=True, has_retval=False)
return sig.format_args(**kwargs)
except TypeError: except TypeError:
# still not possible: happens e.g. for old-style classes # still not possible: happens e.g. for old-style classes
# with __init__ in C # with __init__ in C
return None return None
def format_signature(self): def format_signature(self, **kwargs):
# type: () -> str # type: (Any) -> str
if self.doc_as_attr: if self.doc_as_attr:
return '' return ''
return super().format_signature() return super().format_signature(**kwargs)
def add_directive_header(self, sig): def add_directive_header(self, sig):
# type: (str) -> None # type: (str) -> None
@ -1310,15 +1316,15 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
return ret return ret
def format_args(self): def format_args(self, **kwargs):
# type: () -> str # type: (Any) -> str
if inspect.isbuiltin(self.object) or inspect.ismethoddescriptor(self.object): if inspect.isbuiltin(self.object) or inspect.ismethoddescriptor(self.object):
# can never get arguments of a C function or method # can never get arguments of a C function or method
return None return None
if inspect.isstaticmethod(self.object, cls=self.parent, name=self.object_name): if inspect.isstaticmethod(self.object, cls=self.parent, name=self.object_name):
args = Signature(self.object, bound_method=False).format_args() args = Signature(self.object, bound_method=False).format_args(**kwargs)
else: else:
args = Signature(self.object, bound_method=True).format_args() args = Signature(self.object, bound_method=True).format_args(**kwargs)
# escape backslashes for reST # escape backslashes for reST
args = args.replace('\\', '\\\\') args = args.replace('\\', '\\\\')
return args return args
@ -1329,6 +1335,8 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
sourcename = self.get_sourcename() sourcename = self.get_sourcename()
obj = self.parent.__dict__.get(self.object_name, self.object) obj = self.parent.__dict__.get(self.object_name, self.object)
if inspect.isabstractmethod(obj):
self.add_line(' :abstractmethod:', sourcename)
if inspect.iscoroutinefunction(obj): if inspect.iscoroutinefunction(obj):
self.add_line(' :async:', sourcename) self.add_line(' :async:', sourcename)
if inspect.isclassmethod(obj): if inspect.isclassmethod(obj):
@ -1446,7 +1454,10 @@ class PropertyDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): #
def add_directive_header(self, sig): def add_directive_header(self, sig):
# type: (str) -> None # type: (str) -> None
super().add_directive_header(sig) super().add_directive_header(sig)
self.add_line(' :property:', self.get_sourcename()) sourcename = self.get_sourcename()
if inspect.isabstractmethod(self.object):
self.add_line(' :abstractmethod:', sourcename)
self.add_line(' :property:', sourcename)
class InstanceAttributeDocumenter(AttributeDocumenter): class InstanceAttributeDocumenter(AttributeDocumenter):
@ -1481,6 +1492,55 @@ class InstanceAttributeDocumenter(AttributeDocumenter):
super().add_content(more_content, no_docstring=True) super().add_content(more_content, no_docstring=True)
class SlotsAttributeDocumenter(AttributeDocumenter):
"""
Specialized Documenter subclass for attributes that cannot be imported
because they are attributes in __slots__.
"""
objtype = 'slotsattribute'
directivetype = 'attribute'
member_order = 60
# must be higher than AttributeDocumenter
priority = 11
@classmethod
def can_document_member(cls, member, membername, isattr, parent):
# type: (Any, str, bool, Any) -> bool
"""This documents only SLOTSATTR members."""
return member is SLOTSATTR
def import_object(self):
# type: () -> bool
"""Never import anything."""
# disguise as an attribute
self.objtype = 'attribute'
self._datadescriptor = True
with mock(self.env.config.autodoc_mock_imports):
try:
ret = import_object(self.modname, self.objpath[:-1], 'class',
attrgetter=self.get_attr,
warningiserror=self.env.config.autodoc_warningiserror)
self.module, _, _, self.parent = ret
return True
except ImportError as exc:
logger.warning(exc.args[0], type='autodoc', subtype='import_object')
self.env.note_reread()
return False
def get_doc(self, encoding=None, ignore=1):
# type: (str, int) -> List[List[str]]
"""Decode and return lines of the docstring(s) for the object."""
name = self.objpath[-1]
__slots__ = safe_getattr(self.parent, '__slots__', [])
if isinstance(__slots__, dict) and isinstance(__slots__.get(name), str):
docstring = prepare_docstring(__slots__[name])
return [docstring]
else:
return []
def get_documenters(app): def get_documenters(app):
# type: (Sphinx) -> Dict[str, Type[Documenter]] # type: (Sphinx) -> Dict[str, Type[Documenter]]
"""Returns registered Documenter classes""" """Returns registered Documenter classes"""
@ -1509,6 +1569,7 @@ def setup(app):
app.add_autodocumenter(AttributeDocumenter) app.add_autodocumenter(AttributeDocumenter)
app.add_autodocumenter(PropertyDocumenter) app.add_autodocumenter(PropertyDocumenter)
app.add_autodocumenter(InstanceAttributeDocumenter) app.add_autodocumenter(InstanceAttributeDocumenter)
app.add_autodocumenter(SlotsAttributeDocumenter)
app.add_config_value('autoclass_content', 'class', True) app.add_config_value('autoclass_content', 'class', True)
app.add_config_value('autodoc_member_order', 'alphabetic', True) app.add_config_value('autodoc_member_order', 'alphabetic', True)

View File

@ -15,7 +15,7 @@ from collections import namedtuple
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
from sphinx.util import logging from sphinx.util import logging
from sphinx.util.inspect import isenumclass, safe_getattr from sphinx.util.inspect import isclass, isenumclass, safe_getattr
if False: if False:
# For type annotation # For type annotation
@ -127,6 +127,13 @@ def get_object_members(subject, objpath, attrgetter, analyzer=None):
if name not in superclass.__dict__: if name not in superclass.__dict__:
members[name] = Attribute(name, True, value) members[name] = Attribute(name, True, value)
# members in __slots__
if isclass(subject) and hasattr(subject, '__slots__'):
from sphinx.ext.autodoc import SLOTSATTR
for name in subject.__slots__:
members[name] = Attribute(name, True, SLOTSATTR)
# other members # other members
for name in dir(subject): for name in dir(subject):
try: try:

View File

@ -55,7 +55,7 @@ def register_sections_as_label(app, document):
if name in labels: if name in labels:
logger.warning(__('duplicate label %s, other instance in %s'), logger.warning(__('duplicate label %s, other instance in %s'),
name, app.env.doc2path(labels[name][0]), name, app.env.doc2path(labels[name][0]),
location=node) location=node, type='autosectionlabel', subtype=docname)
anonlabels[name] = docname, labelid anonlabels[name] = docname, labelid
labels[name] = docname, labelid, sectname labels[name] = docname, labelid, sectname

View File

@ -63,7 +63,7 @@ from typing import List, cast
from docutils import nodes from docutils import nodes
from docutils.parsers.rst import directives from docutils.parsers.rst import directives
from docutils.parsers.rst.states import RSTStateMachine, state_classes from docutils.parsers.rst.states import RSTStateMachine, Struct, state_classes
from docutils.statemachine import StringList from docutils.statemachine import StringList
import sphinx import sphinx
@ -175,7 +175,10 @@ _app = None # type: Sphinx
class FakeDirective(DocumenterBridge): class FakeDirective(DocumenterBridge):
def __init__(self): def __init__(self):
# type: () -> None # type: () -> None
super().__init__({}, None, Options(), 0, None) # type: ignore settings = Struct(tab_width=8)
document = Struct(settings=settings)
state = Struct(document=document)
super().__init__({}, None, Options(), 0, state) # type: ignore
def get_documenter(app, obj, parent): def get_documenter(app, obj, parent):
@ -329,7 +332,12 @@ class Autosummary(SphinxDirective):
# -- Grab the signature # -- Grab the signature
try:
sig = documenter.format_signature(show_annotation=False)
except TypeError:
# the documenter does not support ``show_annotation`` option
sig = documenter.format_signature() sig = documenter.format_signature()
if not sig: if not sig:
sig = '' sig = ''
else: else:
@ -436,16 +444,26 @@ def mangle_signature(sig, max_chars=30):
# Remove parenthesis # Remove parenthesis
s = re.sub(r"^\((.*)\)$", r"\1", s).strip() s = re.sub(r"^\((.*)\)$", r"\1", s).strip()
# Strip strings (which can contain things that confuse the code below) # Strip literals (which can contain things that confuse the code below)
s = re.sub(r"\\\\", "", s) s = re.sub(r"\\\\", "", s) # escaped backslash (maybe inside string)
s = re.sub(r"\\'", "", s) s = re.sub(r"\\'", "", s) # escaped single quote
s = re.sub(r"'[^']*'", "", s) s = re.sub(r'\\"', "", s) # escaped double quote
s = re.sub(r"'[^']*'", "", s) # string literal (w/ single quote)
s = re.sub(r'"[^"]*"', "", s) # string literal (w/ double quote)
# Strip complex objects (maybe default value of arguments)
while re.search(r'\([^)]*\)', s): # contents of parenthesis (ex. NamedTuple(attr=...))
s = re.sub(r'\([^)]*\)', '', s)
while re.search(r'<[^>]*>', s): # contents of angle brackets (ex. <object>)
s = re.sub(r'<[^>]*>', '', s)
while re.search(r'{[^}]*}', s): # contents of curly brackets (ex. dict)
s = re.sub(r'{[^}]*}', '', s)
# Parse the signature to arguments + options # Parse the signature to arguments + options
args = [] # type: List[str] args = [] # type: List[str]
opts = [] # type: List[str] opts = [] # type: List[str]
opt_re = re.compile(r"^(.*, |)([a-zA-Z0-9_*]+)=") opt_re = re.compile(r"^(.*, |)([a-zA-Z0-9_*]+)\s*=\s*")
while s: while s:
m = opt_re.search(s) m = opt_re.search(s)
if not m: if not m:

View File

@ -24,7 +24,7 @@ import pydoc
import re import re
import sys import sys
from jinja2 import FileSystemLoader, TemplateNotFound from jinja2 import BaseLoader, FileSystemLoader, TemplateNotFound
from jinja2.sandbox import SandboxedEnvironment from jinja2.sandbox import SandboxedEnvironment
import sphinx.locale import sphinx.locale
@ -34,9 +34,9 @@ from sphinx.ext.autosummary import import_by_name, get_documenter
from sphinx.jinja2glue import BuiltinTemplateLoader from sphinx.jinja2glue import BuiltinTemplateLoader
from sphinx.locale import __ from sphinx.locale import __
from sphinx.registry import SphinxComponentRegistry from sphinx.registry import SphinxComponentRegistry
from sphinx.util import rst
from sphinx.util.inspect import safe_getattr from sphinx.util.inspect import safe_getattr
from sphinx.util.osutil import ensuredir from sphinx.util.osutil import ensuredir
from sphinx.util.rst import escape as rst_escape
if False: if False:
# For type annotation # For type annotation
@ -86,6 +86,42 @@ def _underline(title, line='='):
return title + '\n' + line * len(title) return title + '\n' + line * len(title)
class AutosummaryRenderer:
"""A helper class for rendering."""
def __init__(self, builder, template_dir):
# type: (Builder, str) -> None
loader = None # type: BaseLoader
template_dirs = [os.path.join(package_dir, 'ext', 'autosummary', 'templates')]
if builder is None:
if template_dir:
template_dirs.insert(0, template_dir)
loader = FileSystemLoader(template_dirs)
else:
# allow the user to override the templates
loader = BuiltinTemplateLoader()
loader.init(builder, dirs=template_dirs)
self.env = SandboxedEnvironment(loader=loader)
self.env.filters['escape'] = rst.escape
self.env.filters['e'] = rst.escape
self.env.filters['underline'] = _underline
def exists(self, template_name):
# type: (str) -> bool
"""Check if template file exists."""
try:
self.env.get_template(template_name)
return True
except TemplateNotFound:
return False
def render(self, template_name, context):
# type: (str, Dict) -> str
"""Render a template file."""
return self.env.get_template(template_name).render(context)
# -- Generating output --------------------------------------------------------- # -- Generating output ---------------------------------------------------------
def generate_autosummary_docs(sources, output_dir=None, suffix='.rst', def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
@ -106,26 +142,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
if base_path is not None: if base_path is not None:
sources = [os.path.join(base_path, filename) for filename in sources] sources = [os.path.join(base_path, filename) for filename in sources]
# create our own templating environment template = AutosummaryRenderer(builder, template_dir)
template_dirs = None # type: List[str]
template_dirs = [os.path.join(package_dir, 'ext',
'autosummary', 'templates')]
template_loader = None # type: Union[BuiltinTemplateLoader, FileSystemLoader]
if builder is not None:
# allow the user to override the templates
template_loader = BuiltinTemplateLoader()
template_loader.init(builder, dirs=template_dirs)
else:
if template_dir:
template_dirs.insert(0, template_dir)
template_loader = FileSystemLoader(template_dirs)
template_env = SandboxedEnvironment(loader=template_loader)
template_env.filters['underline'] = _underline
# replace the builtin html filters
template_env.filters['escape'] = rst_escape
template_env.filters['e'] = rst_escape
# read # read
items = find_autosummary_in_files(sources) items = find_autosummary_in_files(sources)
@ -160,14 +177,10 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
with open(fn, 'w') as f: with open(fn, 'w') as f:
doc = get_documenter(app, obj, parent) doc = get_documenter(app, obj, parent)
if template_name is not None: if template_name is None:
template = template_env.get_template(template_name) template_name = 'autosummary/%s.rst' % doc.objtype
else: if not template.exists(template_name):
try: template_name = 'autosummary/base.rst'
template = template_env.get_template('autosummary/%s.rst'
% doc.objtype)
except TemplateNotFound:
template = template_env.get_template('autosummary/base.rst')
def get_members(obj, types, include_public=[], imported=True): def get_members(obj, types, include_public=[], imported=True):
# type: (Any, Set[str], List[str], bool) -> Tuple[List[str], List[str]] # NOQA # type: (Any, Set[str], List[str], bool) -> Tuple[List[str], List[str]] # NOQA
@ -222,7 +235,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
ns['objtype'] = doc.objtype ns['objtype'] = doc.objtype
ns['underline'] = len(name) * '=' ns['underline'] = len(name) * '='
rendered = template.render(**ns) rendered = template.render(template_name, ns)
f.write(rendered) f.write(rendered)
# descend recursively to new files # descend recursively to new files

View File

@ -79,6 +79,8 @@ class CoverageBuilder(Builder):
self.config.coverage_ignore_classes) self.config.coverage_ignore_classes)
self.fun_ignorexps = compile_regex_list('coverage_ignore_functions', self.fun_ignorexps = compile_regex_list('coverage_ignore_functions',
self.config.coverage_ignore_functions) self.config.coverage_ignore_functions)
self.py_ignorexps = compile_regex_list('coverage_ignore_pyobjects',
self.config.coverage_ignore_pyobjects)
def get_outdated_docs(self): def get_outdated_docs(self):
# type: () -> str # type: () -> str
@ -130,6 +132,12 @@ class CoverageBuilder(Builder):
op.write(' * %-50s [%9s]\n' % (name, typ)) op.write(' * %-50s [%9s]\n' % (name, typ))
op.write('\n') op.write('\n')
def ignore_pyobj(self, full_name):
for exp in self.py_ignorexps:
if exp.search(full_name):
return True
return False
def build_py_coverage(self): def build_py_coverage(self):
# type: () -> None # type: () -> None
objects = self.env.domaindata['py']['objects'] objects = self.env.domaindata['py']['objects']
@ -143,7 +151,7 @@ class CoverageBuilder(Builder):
if exp.match(mod_name): if exp.match(mod_name):
ignore = True ignore = True
break break
if ignore: if ignore or self.ignore_pyobj(mod_name):
continue continue
try: try:
@ -169,6 +177,8 @@ class CoverageBuilder(Builder):
continue continue
full_name = '%s.%s' % (mod_name, name) full_name = '%s.%s' % (mod_name, name)
if self.ignore_pyobj(full_name):
continue
if inspect.isfunction(obj): if inspect.isfunction(obj):
if full_name not in objects: if full_name not in objects:
@ -209,11 +219,11 @@ class CoverageBuilder(Builder):
if skip_undoc and not attr.__doc__: if skip_undoc and not attr.__doc__:
# skip methods without docstring if wished # skip methods without docstring if wished
continue continue
full_attr_name = '%s.%s' % (full_name, attr_name) full_attr_name = '%s.%s' % (full_name, attr_name)
if self.ignore_pyobj(full_attr_name):
continue
if full_attr_name not in objects: if full_attr_name not in objects:
attrs.append(attr_name) attrs.append(attr_name)
if attrs: if attrs:
# some attributes are undocumented # some attributes are undocumented
classes[name] = attrs classes[name] = attrs
@ -270,6 +280,7 @@ def setup(app):
app.add_config_value('coverage_ignore_modules', [], False) app.add_config_value('coverage_ignore_modules', [], False)
app.add_config_value('coverage_ignore_functions', [], False) app.add_config_value('coverage_ignore_functions', [], False)
app.add_config_value('coverage_ignore_classes', [], False) app.add_config_value('coverage_ignore_classes', [], False)
app.add_config_value('coverage_ignore_pyobjects', [], False)
app.add_config_value('coverage_c_path', [], False) app.add_config_value('coverage_c_path', [], False)
app.add_config_value('coverage_c_regexes', {}, False) app.add_config_value('coverage_c_regexes', {}, False)
app.add_config_value('coverage_ignore_c_items', {}, False) app.add_config_value('coverage_ignore_c_items', {}, False)

View File

@ -25,11 +25,11 @@ if errorlevel 9009 (
exit /b 1 exit /b 1
) )
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
goto end goto end
:help :help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
:end :end
popd popd

View File

@ -9,7 +9,7 @@ if "%SPHINXBUILD%" == "" (
) )
set BUILDDIR={{ rbuilddir }} set BUILDDIR={{ rbuilddir }}
set SOURCEDIR={{ rsrcdir }} set SOURCEDIR={{ rsrcdir }}
set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% %SOURCEDIR% set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% %O% %SOURCEDIR%
set I18NSPHINXOPTS=%SPHINXOPTS% %SOURCEDIR% set I18NSPHINXOPTS=%SPHINXOPTS% %SOURCEDIR%
if NOT "%PAPER%" == "" ( if NOT "%PAPER%" == "" (
set ALLSPHINXOPTS=-D latex_elements.papersize=%PAPER%paper %ALLSPHINXOPTS% set ALLSPHINXOPTS=-D latex_elements.papersize=%PAPER%paper %ALLSPHINXOPTS%

View File

@ -51,7 +51,7 @@
<div class="topnav" role="navigation" aria-label="top navigation"> <div class="topnav" role="navigation" aria-label="top navigation">
{{ nav() }} {{ nav() }}
</div> </div>
<div class="content"> <div class="content" role="main">
{#{%- if display_toc %} {#{%- if display_toc %}
<div id="toc"> <div id="toc">
<h3>{{ _('Table of Contents') }}</h3> <h3>{{ _('Table of Contents') }}</h3>

View File

@ -42,7 +42,9 @@
{{ toc }} {{ toc }}
</div> </div>
{%- endif %} {%- endif %}
<div role="main">
{% block body %}{% endblock %} {% block body %}{% endblock %}
</div> </div>
</div> </div>
</div>
{% endblock %} {% endblock %}

View File

@ -244,7 +244,7 @@ date_format_mappings = {
'%x': 'medium', # Locales appropriate date representation. '%x': 'medium', # Locales appropriate date representation.
'%X': 'medium', # Locales appropriate time representation. '%X': 'medium', # Locales appropriate time representation.
'%y': 'YY', # Year without century as a zero-padded decimal number. '%y': 'YY', # Year without century as a zero-padded decimal number.
'%Y': 'YYYY', # Year with century as a decimal number. '%Y': 'yyyy', # Year with century as a decimal number.
'%Z': 'zzzz', # Time zone name (no characters if no time zone exists). '%Z': 'zzzz', # Time zone name (no characters if no time zone exists).
'%%': '%', '%%': '%',
} }

View File

@ -170,6 +170,12 @@ def isdescriptor(x):
return False return False
def isabstractmethod(obj):
# type: (Any) -> bool
"""Check if the object is an abstractmethod."""
return safe_getattr(obj, '__isabstractmethod__', False) is True
def isattributedescriptor(obj): def isattributedescriptor(obj):
# type: (Any) -> bool # type: (Any) -> bool
"""Check if the object is an attribute like descriptor.""" """Check if the object is an attribute like descriptor."""
@ -229,7 +235,7 @@ def isproperty(obj):
def safe_getattr(obj, name, *defargs): def safe_getattr(obj, name, *defargs):
# type: (Any, str, str) -> object # type: (Any, str, Any) -> Any
"""A getattr() that turns all exceptions into AttributeErrors.""" """A getattr() that turns all exceptions into AttributeErrors."""
try: try:
return getattr(obj, name, *defargs) return getattr(obj, name, *defargs)
@ -317,9 +323,9 @@ def is_builtin_class_method(obj, attr_name):
classes = [c for c in inspect.getmro(obj) if attr_name in c.__dict__] classes = [c for c in inspect.getmro(obj) if attr_name in c.__dict__]
cls = classes[0] if classes else object cls = classes[0] if classes else object
if not hasattr(builtins, safe_getattr(cls, '__name__', '')): # type: ignore if not hasattr(builtins, safe_getattr(cls, '__name__', '')):
return False return False
return getattr(builtins, safe_getattr(cls, '__name__', '')) is cls # type: ignore return getattr(builtins, safe_getattr(cls, '__name__', '')) is cls
class Signature: class Signature:
@ -391,8 +397,8 @@ class Signature:
else: else:
return None return None
def format_args(self): def format_args(self, show_annotation=True):
# type: () -> str # type: (bool) -> str
args = [] args = []
last_kind = None last_kind = None
for i, param in enumerate(self.parameters.values()): for i, param in enumerate(self.parameters.values()):
@ -413,7 +419,7 @@ class Signature:
param.POSITIONAL_OR_KEYWORD, param.POSITIONAL_OR_KEYWORD,
param.KEYWORD_ONLY): param.KEYWORD_ONLY):
arg.write(param.name) arg.write(param.name)
if param.annotation is not param.empty: if show_annotation and param.annotation is not param.empty:
if isinstance(param.annotation, str) and param.name in self.annotations: if isinstance(param.annotation, str) and param.name in self.annotations:
arg.write(': ') arg.write(': ')
arg.write(self.format_annotation(self.annotations[param.name])) arg.write(self.format_annotation(self.annotations[param.name]))

View File

@ -31,7 +31,7 @@ logger = logging.getLogger(__name__)
# \x00 means the "<" was backslash-escaped # \x00 means the "<" was backslash-escaped
explicit_title_re = re.compile(r'^(.+?)\s*(?<!\x00)<(.*?)>$', re.DOTALL) explicit_title_re = re.compile(r'^(.+?)\s*(?<!\x00)<([^<]*?)>$', re.DOTALL)
caption_ref_re = explicit_title_re # b/w compat alias caption_ref_re = explicit_title_re # b/w compat alias

View File

@ -0,0 +1,29 @@
from abc import abstractmethod
class Base():
def meth(self):
pass
@abstractmethod
def abstractmeth(self):
pass
@staticmethod
@abstractmethod
def staticmeth():
pass
@classmethod
@abstractmethod
def classmeth(cls):
pass
@property
@abstractmethod
def prop(self):
pass
@abstractmethod
async def coroutinemeth(self):
pass

View File

@ -0,0 +1,11 @@
class Foo:
__slots__ = ['attr']
class Bar:
__slots__ = {'attr1': 'docstring of attr1',
'attr2': 'docstring of attr2',
'attr3': None}
def __init__(self):
self.attr2 = None #: docstring of instance attr2

View File

@ -1,4 +1,5 @@
from os import * # NOQA from os import * # NOQA
from typing import Union
class Foo: class Foo:
@ -11,3 +12,7 @@ class Foo:
@property @property
def baz(self): def baz(self):
pass pass
def bar(x: Union[int, str], y: int = 1):
pass

View File

@ -8,4 +8,5 @@
autosummary_dummy_module autosummary_dummy_module
autosummary_dummy_module.Foo autosummary_dummy_module.Foo
autosummary_dummy_module.bar
autosummary_importfail autosummary_importfail

View File

@ -0,0 +1,12 @@
import os
import sys
sys.path.insert(0, os.path.abspath('.'))
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.coverage']
coverage_ignore_pyobjects = [
r'^coverage_ignored(\..*)?$',
r'\.Ignored$',
r'\.Documented\.ignored\d$',
]

View File

@ -0,0 +1,22 @@
class Documented:
"""Documented"""
def ignored1(self):
pass
def ignored2(self):
pass
def not_ignored1(self):
pass
def not_ignored2(self):
pass
class Ignored:
pass
class NotIgnored:
pass

View File

@ -0,0 +1,22 @@
class Documented:
"""Documented"""
def ignored1(self):
pass
def ignored2(self):
pass
def not_ignored1(self):
pass
def not_ignored2(self):
pass
class Ignored:
pass
class NotIgnored:
pass

View File

@ -0,0 +1,6 @@
.. automodule:: coverage_ignored
:members:
.. automodule:: coverage_not_ignored
:members:

View File

@ -1317,6 +1317,46 @@ def test_instance_attributes(app):
] ]
@pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_slots(app):
options = {"members": None,
"undoc-members": True}
actual = do_autodoc(app, 'module', 'target.slots', options)
assert list(actual) == [
'',
'.. py:module:: target.slots',
'',
'',
'.. py:class:: Bar()',
' :module: target.slots',
'',
' ',
' .. py:attribute:: Bar.attr1',
' :module: target.slots',
' ',
' docstring of attr1',
' ',
' ',
' .. py:attribute:: Bar.attr2',
' :module: target.slots',
' ',
' docstring of instance attr2',
' ',
' ',
' .. py:attribute:: Bar.attr3',
' :module: target.slots',
' ',
'',
'.. py:class:: Foo',
' :module: target.slots',
'',
' ',
' .. py:attribute:: Foo.attr',
' :module: target.slots',
' ',
]
@pytest.mark.sphinx('html', testroot='ext-autodoc') @pytest.mark.sphinx('html', testroot='ext-autodoc')
def test_enum_class(app): def test_enum_class(app):
options = {"members": None, options = {"members": None,
@ -1482,6 +1522,55 @@ def test_mocked_module_imports(app, warning):
assert warning.getvalue() == '' assert warning.getvalue() == ''
@pytest.mark.usefixtures('setup_test')
def test_abstractmethods():
options = {"members": None,
"undoc-members": None}
actual = do_autodoc(app, 'module', 'target.abstractmethods', options)
assert list(actual) == [
'',
'.. py:module:: target.abstractmethods',
'',
'',
'.. py:class:: Base',
' :module: target.abstractmethods',
'',
' ',
' .. py:method:: Base.abstractmeth()',
' :module: target.abstractmethods',
' :abstractmethod:',
' ',
' ',
' .. py:method:: Base.classmeth()',
' :module: target.abstractmethods',
' :abstractmethod:',
' :classmethod:',
' ',
' ',
' .. py:method:: Base.coroutinemeth()',
' :module: target.abstractmethods',
' :abstractmethod:',
' :async:',
' ',
' ',
' .. py:method:: Base.meth()',
' :module: target.abstractmethods',
' ',
' ',
' .. py:method:: Base.prop',
' :module: target.abstractmethods',
' :abstractmethod:',
' :property:',
' ',
' ',
' .. py:method:: Base.staticmeth()',
' :module: target.abstractmethods',
' :abstractmethod:',
' :staticmethod:',
' '
]
@pytest.mark.usefixtures('setup_test') @pytest.mark.usefixtures('setup_test')
def test_partialfunction(): def test_partialfunction():
options = {"members": None} options = {"members": None}

View File

@ -18,7 +18,10 @@ from sphinx.addnodes import (
desc, desc_addname, desc_annotation, desc_content, desc_name, desc_optional, desc, desc_addname, desc_annotation, desc_content, desc_name, desc_optional,
desc_parameter, desc_parameterlist, desc_returns, desc_signature desc_parameter, desc_parameterlist, desc_returns, desc_signature
) )
from sphinx.domains.python import py_sig_re, _pseudo_parse_arglist, PythonDomain from sphinx.domains import IndexEntry
from sphinx.domains.python import (
py_sig_re, _pseudo_parse_arglist, PythonDomain, PythonModuleIndex
)
from sphinx.testing import restructuredtext from sphinx.testing import restructuredtext
from sphinx.testing.util import assert_node from sphinx.testing.util import assert_node
@ -335,7 +338,9 @@ def test_pymethod_options(app):
" .. py:method:: meth4\n" " .. py:method:: meth4\n"
" :async:\n" " :async:\n"
" .. py:method:: meth5\n" " .. py:method:: meth5\n"
" :property:\n") " :property:\n"
" .. py:method:: meth6\n"
" :abstractmethod:\n")
domain = app.env.get_domain('py') domain = app.env.get_domain('py')
doctree = restructuredtext.parse(app, text) doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index, assert_node(doctree, (addnodes.index,
@ -350,6 +355,8 @@ def test_pymethod_options(app):
addnodes.index, addnodes.index,
desc, desc,
addnodes.index, addnodes.index,
desc,
addnodes.index,
desc)])])) desc)])]))
# method # method
@ -400,6 +407,16 @@ def test_pymethod_options(app):
assert 'Class.meth5' in domain.objects assert 'Class.meth5' in domain.objects
assert domain.objects['Class.meth5'] == ('index', 'method') assert domain.objects['Class.meth5'] == ('index', 'method')
# :abstractmethod:
assert_node(doctree[1][1][10], addnodes.index,
entries=[('single', 'meth6() (Class method)', 'Class.meth6', '', None)])
assert_node(doctree[1][1][11], ([desc_signature, ([desc_annotation, "abstract "],
[desc_name, "meth6"],
[desc_parameterlist, ()])],
[desc_content, ()]))
assert 'Class.meth6' in domain.objects
assert domain.objects['Class.meth6'] == ('index', 'method')
def test_pyclassmethod(app): def test_pyclassmethod(app):
text = (".. py:class:: Class\n" text = (".. py:class:: Class\n"
@ -460,3 +477,49 @@ def test_pyattribute(app):
[desc_content, ()])) [desc_content, ()]))
assert 'Class.attr' in domain.objects assert 'Class.attr' in domain.objects
assert domain.objects['Class.attr'] == ('index', 'attribute') assert domain.objects['Class.attr'] == ('index', 'attribute')
@pytest.mark.sphinx(freshenv=True)
def test_module_index(app):
text = (".. py:module:: docutils\n"
".. py:module:: sphinx\n"
".. py:module:: sphinx.config\n"
".. py:module:: sphinx.builders\n"
".. py:module:: sphinx.builders.html\n"
".. py:module:: sphinx_intl\n")
restructuredtext.parse(app, text)
index = PythonModuleIndex(app.env.get_domain('py'))
assert index.generate() == (
[('d', [IndexEntry('docutils', 0, 'index', 'module-docutils', '', '', '')]),
('s', [IndexEntry('sphinx', 1, 'index', 'module-sphinx', '', '', ''),
IndexEntry('sphinx.builders', 2, 'index', 'module-sphinx.builders', '', '', ''), # NOQA
IndexEntry('sphinx.builders.html', 2, 'index', 'module-sphinx.builders.html', '', '', ''), # NOQA
IndexEntry('sphinx.config', 2, 'index', 'module-sphinx.config', '', '', ''),
IndexEntry('sphinx_intl', 0, 'index', 'module-sphinx_intl', '', '', '')])],
False
)
@pytest.mark.sphinx(freshenv=True)
def test_module_index_submodule(app):
text = ".. py:module:: sphinx.config\n"
restructuredtext.parse(app, text)
index = PythonModuleIndex(app.env.get_domain('py'))
assert index.generate() == (
[('s', [IndexEntry('sphinx', 1, '', '', '', '', ''),
IndexEntry('sphinx.config', 2, 'index', 'module-sphinx.config', '', '', '')])],
False
)
@pytest.mark.sphinx(freshenv=True)
def test_module_index_not_collapsed(app):
text = (".. py:module:: docutils\n"
".. py:module:: sphinx\n")
restructuredtext.parse(app, text)
index = PythonModuleIndex(app.env.get_domain('py'))
assert index.generate() == (
[('d', [IndexEntry('docutils', 0, 'index', 'module-docutils', '', '', '')]),
('s', [IndexEntry('sphinx', 0, 'index', 'module-sphinx', '', '', '')])],
True
)

View File

@ -13,9 +13,13 @@ from io import StringIO
from unittest.mock import Mock from unittest.mock import Mock
import pytest import pytest
from docutils import nodes
from sphinx.ext.autosummary import mangle_signature, import_by_name, extract_summary from sphinx import addnodes
from sphinx.testing.util import etree_parse from sphinx.ext.autosummary import (
autosummary_table, autosummary_toc, mangle_signature, import_by_name, extract_summary
)
from sphinx.testing.util import assert_node, etree_parse
from sphinx.util.docutils import new_document from sphinx.util.docutils import new_document
html_warnfile = StringIO() html_warnfile = StringIO()
@ -43,11 +47,13 @@ def test_mangle_signature():
(a, b[, c]) :: (a, b[, c]) (a, b[, c]) :: (a, b[, c])
(a, b[, cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]) :: (a, b[, ...) (a, b[, cxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]) :: (a, b[, ...)
(a, b='c=d, e=f, g=h', c=3) :: (a[, b, c]) (a, b='c=d, e=f, g=h', c=3) :: (a[, b, c])
(a, b="c=d, e=f, g=h", c=3) :: (a[, b, c])
(a, b='c=d, \\'e=f,\\' g=h', c=3) :: (a[, b, c]) (a, b='c=d, \\'e=f,\\' g=h', c=3) :: (a[, b, c])
(a, b='c=d, ', e='\\\\' g=h, c=3) :: (a[, b, e, c]) (a, b='c=d, ', e='\\\\' g=h, c=3) :: (a[, b, e, c])
(a, b={'c=d, ': 3, '\\\\': 3}) :: (a[, b]) (a, b={'c=d, ': 3, '\\\\': 3}) :: (a[, b])
(a=1, b=2, c=3) :: ([a, b, c]) (a=1, b=2, c=3) :: ([a, b, c])
(a=1, b=<SomeClass: a, b, c>, c=3) :: ([a, b, c]) (a=1, b=<SomeClass: a, b, c>, c=3) :: ([a, b, c])
(a=1, b=T(a=1, b=2), c=3) :: ([a, b, c])
(a: int, b: int) -> str :: (a, b) (a: int, b: int) -> str :: (a, b)
""" """
@ -179,6 +185,24 @@ def test_escaping(app, status, warning):
def test_autosummary_generate(app, status, warning): def test_autosummary_generate(app, status, warning):
app.builder.build_all() app.builder.build_all()
doctree = app.env.get_doctree('index')
assert_node(doctree, (nodes.paragraph,
nodes.paragraph,
addnodes.tabular_col_spec,
autosummary_table,
autosummary_toc))
assert_node(doctree[3],
[autosummary_table, nodes.table, nodes.tgroup, (nodes.colspec,
nodes.colspec,
[nodes.tbody, (nodes.row,
nodes.row,
nodes.row,
nodes.row)])])
assert doctree[3][0][0][2][0].astext() == 'autosummary_dummy_module\n\n'
assert doctree[3][0][0][2][1].astext() == 'autosummary_dummy_module.Foo()\n\n'
assert doctree[3][0][0][2][2].astext() == 'autosummary_dummy_module.bar(x[, y])\n\n'
assert doctree[3][0][0][2][3].astext() == 'autosummary_importfail\n\n'
module = (app.srcdir / 'generated' / 'autosummary_dummy_module.rst').text() module = (app.srcdir / 'generated' / 'autosummary_dummy_module.rst').text()
assert (' .. autosummary::\n' assert (' .. autosummary::\n'
' \n' ' \n'

View File

@ -45,3 +45,22 @@ def test_build(app, status, warning):
assert 'classes' in undoc_py['autodoc_target'] assert 'classes' in undoc_py['autodoc_target']
assert 'Class' in undoc_py['autodoc_target']['classes'] assert 'Class' in undoc_py['autodoc_target']['classes']
assert 'undocmeth' in undoc_py['autodoc_target']['classes']['Class'] assert 'undocmeth' in undoc_py['autodoc_target']['classes']['Class']
@pytest.mark.sphinx('coverage', testroot='ext-coverage')
def test_coverage_ignore_pyobjects(app, status, warning):
app.builder.build_all()
actual = (app.outdir / 'python.txt').text()
expected = '''Undocumented Python objects
===========================
coverage_not_ignored
--------------------
Classes:
* Documented -- missing methods:
- not_ignored1
- not_ignored2
* NotIgnored
'''
assert actual == expected

View File

@ -17,7 +17,7 @@ from docutils.parsers import rst
from docutils.utils import new_document from docutils.utils import new_document
from sphinx.transforms import ApplySourceWorkaround from sphinx.transforms import ApplySourceWorkaround
from sphinx.util.nodes import NodeMatcher, extract_messages, clean_astext from sphinx.util.nodes import NodeMatcher, extract_messages, clean_astext, split_explicit_title
def _transform(doctree): def _transform(doctree):
@ -178,3 +178,18 @@ def test_clean_astext():
node = nodes.paragraph(text='hello world') node = nodes.paragraph(text='hello world')
node += nodes.raw('', 'raw text', format='html') node += nodes.raw('', 'raw text', format='html')
assert 'hello world' == clean_astext(node) assert 'hello world' == clean_astext(node)
@pytest.mark.parametrize(
'title, expected',
[
# implicit
('hello', (False, 'hello', 'hello')),
# explicit
('hello <world>', (True, 'hello', 'world')),
# explicit (title having angle brackets)
('hello <world> <sphinx>', (True, 'hello <world>', 'sphinx')),
]
)
def test_split_explicit_target(title, expected):
assert expected == split_explicit_title(title)

View File

@ -14,7 +14,10 @@ import sys
from typing import List from typing import List
MAX_LINE_LENGTH = 100 MAX_LINE_LENGTH = 90
LONG_INTERPRETED_TEXT = re.compile(r'^\s*\W*(:(\w+:)+)?`.*`\W*$')
CODE_BLOCK_DIRECTIVE = re.compile(r'^(\s*)\.\. code-block::')
LEADING_SPACES = re.compile(r'^(\s*)')
def lint(path: str) -> int: def lint(path: str) -> int:
@ -22,13 +25,28 @@ def lint(path: str) -> int:
document = f.readlines() document = f.readlines()
errors = 0 errors = 0
in_code_block = False
code_block_depth = 0
for i, line in enumerate(document): for i, line in enumerate(document):
if line.endswith(' '): if line.endswith(' '):
print('%s:%d: the line ends with whitespace.' % print('%s:%d: the line ends with whitespace.' %
(path, i + 1)) (path, i + 1))
errors += 1 errors += 1
if len(line) > MAX_LINE_LENGTH: matched = CODE_BLOCK_DIRECTIVE.match(line)
if matched:
in_code_block = True
code_block_depth = len(matched.group(1))
elif in_code_block:
if line.strip() == '':
pass
else:
spaces = LEADING_SPACES.match(line).group(1)
if len(spaces) < code_block_depth:
in_code_block = False
elif LONG_INTERPRETED_TEXT.match(line):
pass
elif len(line) > MAX_LINE_LENGTH:
if re.match(r'^\s*\.\. ', line): if re.match(r'^\s*\.\. ', line):
# ignore directives and hyperlink targets # ignore directives and hyperlink targets
pass pass
@ -42,8 +60,11 @@ def lint(path: str) -> int:
def main(args: List[str]) -> int: def main(args: List[str]) -> int:
errors = 0 errors = 0
for directory in args: for path in args:
for root, dirs, files in os.walk(directory): if os.path.isfile(path):
errors += lint(path)
elif os.path.isdir(path):
for root, dirs, files in os.walk(path):
for filename in files: for filename in files:
if filename.endswith('.rst'): if filename.endswith('.rst'):
path = os.path.join(root, filename) path = os.path.join(root, filename)