Merge remote-tracking branch 'sphinx/3.x' into 3.x

This commit is contained in:
Daniel Fremont 2020-05-17 08:09:45 -07:00
commit f9e9bdc4a0
217 changed files with 5331 additions and 3195 deletions

View File

@ -8,4 +8,7 @@ jobs:
- checkout - checkout
- run: /python3.6/bin/pip install -U pip setuptools - run: /python3.6/bin/pip install -U pip setuptools
- run: /python3.6/bin/pip install -U .[test] - run: /python3.6/bin/pip install -U .[test]
- run: make test PYTHON=/python3.6/bin/python - run: mkdir -p test-reports/pytest
- run: make test PYTHON=/python3.6/bin/python TEST=--junitxml=test-reports/pytest/results.xml
- store_test_results:
path: test-reports

1
.gitignore vendored
View File

@ -9,6 +9,7 @@
.mypy_cache/ .mypy_cache/
.pytest_cache/ .pytest_cache/
.ropeproject/ .ropeproject/
.vscode/
TAGS TAGS
.tags .tags
.tox/ .tox/

View File

@ -85,6 +85,7 @@ Other contributors, listed alphabetically, are:
* 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 * Adrián Chaves (Gallaecio) -- coverage builder improvements
* Lars Hupfeldt Nielsen - OpenSSL FIPS mode md5 bug fix
Many thanks for all contributions! Many thanks for all contributions!

135
CHANGES
View File

@ -7,26 +7,116 @@ Dependencies
Incompatible changes Incompatible changes
-------------------- --------------------
* #7477: imgconverter: Invoke "magick convert" command by default on Windows
Deprecated Deprecated
---------- ----------
* The first argument for sphinx.ext.autosummary.generate.AutosummaryRenderer has
been changed to Sphinx object
* ``sphinx.ext.autosummary.generate.AutosummaryRenderer`` takes an object type
as an argument
* The ``ignore`` argument of ``sphinx.ext.autodoc.Documenter.get_doc()``
* The ``template_dir`` argument of ``sphinx.ext.autosummary.generate.
AutosummaryRenderer``
* The ``module`` argument of ``sphinx.ext.autosummary.generate. * The ``module`` argument of ``sphinx.ext.autosummary.generate.
find_autosummary_in_docstring()`` find_autosummary_in_docstring()``
* The ``builder`` argument of ``sphinx.ext.autosummary.generate.
generate_autosummary_docs()``
* The ``template_dir`` argument of ``sphinx.ext.autosummary.generate.
generate_autosummary_docs()``
* The ``ignore`` argument of ``sphinx.util.docstring.prepare_docstring()``
* ``sphinx.ext.autosummary.generate.AutosummaryRenderer.exists()``
* ``sphinx.util.rpartition()``
Features added Features added
-------------- --------------
* LaTeX: Make the ``toplevel_sectioning`` setting optional in LaTeX theme * LaTeX: Make the ``toplevel_sectioning`` setting optional in LaTeX theme
* LaTeX: Allow to override papersize and pointsize from LaTeX themes
* LaTeX: Add :confval:`latex_theme_options` to override theme options
* #7410: Allow to suppress "circular toctree references detected" warnings using * #7410: Allow to suppress "circular toctree references detected" warnings using
:confval:`suppress_warnings` :confval:`suppress_warnings`
* C, added scope control directives, :rst:dir:`c:namespace`,
:rst:dir:`c:namespace-push`, and :rst:dir:`c:namespace-pop`.
* #2044: autodoc: Suppress default value for instance attributes
* #7473: autodoc: consider a member public if docstring contains
``:meta public:`` in info-field-list
* #7487: autodoc: Allow to generate docs for singledispatch functions by
py:autofunction
* #7143: autodoc: Support final classes and methods
* #7466: autosummary: headings in generated documents are not translated
* #7490: autosummary: Add ``:caption:`` option to autosummary directive to set a
caption to the toctree
* #248, #6040: autosummary: Add ``:recursive:`` option to autosummary directive
to generate stub files recursively
* #4030: autosummary: Add :confval:`autosummary_context` to add template
variables for custom templates
* #7530: html: Support nested <kbd> elements
* #7481: html theme: Add right margin to footnote/citation labels
* #7482: html theme: CSS spacing for code blocks with captions and line numbers
* #7443: html theme: Add new options :confval:`globaltoc_collapse` and
:confval:`globaltoc_includehidden` to control the behavior of globaltoc in
sidebar
* #7484: html theme: Avoid clashes between sidebar and other blocks
* #7476: html theme: Relbar breadcrumb should contain current page
* #7506: html theme: A canonical URL is not escaped
* #7533: html theme: Avoid whitespace at the beginning of genindex.html
* #7541: html theme: Add a "clearer" at the end of the "body"
* #7542: html theme: Make admonition/topic/sidebar scrollable
* #7543: html theme: Add top and bottom margins to tables
* C and C++: allow semicolon in the end of declarations.
* C++, parse parameterized noexcept specifiers.
* #7294: C++, parse expressions with user-defined literals.
* C++, parse trailing return types.
* #7143: py domain: Add ``:final:`` option to :rst:dir:`py:class:`,
:rst:dir:`py:exception:` and :rst:dir:`py:method:` directives
* #7596: py domain: Change a type annotation for variables to a hyperlink
* #7582: napoleon: a type for attribute are represented like type annotation
* #7683: Add ``allowed_exceptions`` parameter to ``Sphinx.emit()`` to allow
handlers to raise specified exceptions
Bugs fixed Bugs fixed
---------- ----------
* #6703: autodoc: incremental build does not work for imported objects
* #7564: autodoc: annotations not to be shown for descriptors
* #6588: autodoc: Decorated inherited method has no documentation
* #7469: autodoc: The change of autodoc-process-docstring for variables is
cached unexpectedly
* #7559: autodoc: misdetects a sync function is async
* #6857: autodoc: failed to detect a classmethod on Enum class
* #7562: autodoc: a typehint contains spaces is wrongly rendered under
autodoc_typehints='description' mode
* #7551: autodoc: failed to import nested class
* #7362: autodoc: does not render correct signatures for built-in functions
* #7654: autodoc: ``Optional[Union[foo, bar]]`` is presented as
``Union[foo, bar, None]``
* #7629: autodoc: autofunction emits an unfriendly warning if an invalid object
specified
* #7650: autodoc: undecorated signature is shown for decorated functions
* #7676: autodoc: typo in the default value of autodoc_member_order
* #7551: autosummary: a nested class is indexed as non-nested class
* #7661: autosummary: autosummary directive emits warnings twices if failed to
import the target module
* #7535: sphinx-autogen: crashes when custom template uses inheritance
* #7536: sphinx-autogen: crashes when template uses i18n feature
* #7653: sphinx-quickstart: Fix multiple directory creation for nested relpath
* #2785: html: Bad alignment of equation links
* #7581: napoleon: bad parsing of inline code in attribute docstrings
* #7628: imgconverter: runs imagemagick once unnecessary for builders not
supporting images
* #7610: incorrectly renders consecutive backslashes for docutils-0.16
* #7646: handle errors on event handlers
* C++, fix rendering and xrefs in nested names explicitly starting
in global scope, e.g., ``::A::B``.
* C, fix rendering and xrefs in nested names explicitly starting
in global scope, e.g., ``.A.B``.
Testing Testing
-------- --------
Release 3.0.2 (in development) Release 3.0.4 (in development)
============================== ==============================
Dependencies Dependencies
@ -44,9 +134,50 @@ Features added
Bugs fixed Bugs fixed
---------- ----------
* #7567: autodoc: parametrized types are shown twice for generic types
* #7637: autodoc: system defined TypeVars are shown in Python 3.9
* #7611: md5 fails when OpenSSL FIPS is enabled
* #7626: release package does not contain ``CODE_OF_CONDUCT``
Testing Testing
-------- --------
Release 3.0.3 (released Apr 26, 2020)
=====================================
Features added
--------------
* C, parse array declarators with static, qualifiers, and VLA specification.
Bugs fixed
----------
* #7516: autodoc: crashes if target object raises an error on accessing
its attributes
Release 3.0.2 (released Apr 19, 2020)
=====================================
Features added
--------------
* C, parse attributes and add :confval:`c_id_attributes`
and :confval:`c_paren_attributes` to support user-defined attributes.
Bugs fixed
----------
* #7461: py domain: fails with IndexError for empty tuple in type annotation
* #7510: py domain: keyword-only arguments are documented as having a default of
None
* #7418: std domain: :rst:role:`term` role could not match case-insensitively
* #7461: autodoc: empty tuple in type annotation is not shown correctly
* #7479: autodoc: Sphinx builds has been slower since 3.0.0 on mocking
* C++, fix spacing issue in east-const declarations.
* #7414: LaTeX: Xindy language options were incorrect
* sphinx crashes with ImportError on python3.5.1
Release 3.0.1 (released Apr 11, 2020) Release 3.0.1 (released Apr 11, 2020)
===================================== =====================================
@ -1291,7 +1422,7 @@ Incompatible changes
object. Please use ``config.gettext_compact`` instead. object. Please use ``config.gettext_compact`` instead.
* The processing order on reading phase is changed. smart_quotes, sphinx * The processing order on reading phase is changed. smart_quotes, sphinx
domains, :event:`doctree-read` event and versioning doctrees are invoked domains, :event:`doctree-read` event and versioning doctrees are invoked
earlier than so far. For more details, please read a description of earlier than so far. For more details, please read a description of
:py:meth:`.Sphinx.add_transform()` :py:meth:`.Sphinx.add_transform()`
* #4827: All ``substitution_definition`` nodes are removed from doctree on * #4827: All ``substitution_definition`` nodes are removed from doctree on
reading phase reading phase

View File

@ -3,6 +3,7 @@ include LICENSE
include AUTHORS include AUTHORS
include CHANGES include CHANGES
include CHANGES.old include CHANGES.old
include CODE_OF_CONDUCT
include CONTRIBUTING.rst include CONTRIBUTING.rst
include EXAMPLES include EXAMPLES

View File

@ -50,7 +50,7 @@ clean-buildfiles:
.PHONY: clean-mypyfiles .PHONY: clean-mypyfiles
clean-mypyfiles: clean-mypyfiles:
rm -rf **/.mypy_cache/ find . -name '.mypy_cache' -exec rm -rf {} +
.PHONY: style-check .PHONY: style-check
style-check: style-check:

View File

@ -13,11 +13,6 @@
{% block sidebar1 %}{{ sidebar() }}{% endblock %} {% block sidebar1 %}{{ sidebar() }}{% endblock %}
{% block sidebar2 %}{% endblock %} {% block sidebar2 %}{% endblock %}
{% block linktags %}
{{ super() }}
<link rel="canonical" href="http://www.sphinx-doc.org/en/master/{{ pagename }}{{ file_suffix }}" />
{% endblock %}
{% block extrahead %} {% block extrahead %}
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,700' <link href='https://fonts.googleapis.com/css?family=Open+Sans:300,400,700'
rel='stylesheet' type='text/css' /> rel='stylesheet' type='text/css' />

View File

@ -127,6 +127,7 @@ div.sphinxsidebar {
float: right; float: right;
font-size: 1em; font-size: 1em;
text-align: left; text-align: left;
max-height: 0px;
} }
div.sphinxsidebar .logo { div.sphinxsidebar .logo {

View File

@ -26,7 +26,8 @@ modindex_common_prefix = ['sphinx.']
html_static_path = ['_static'] html_static_path = ['_static']
html_sidebars = {'index': ['indexsidebar.html', 'searchbox.html']} html_sidebars = {'index': ['indexsidebar.html', 'searchbox.html']}
html_additional_pages = {'index': 'index.html'} html_additional_pages = {'index': 'index.html'}
html_use_opensearch = 'http://sphinx-doc.org' html_use_opensearch = 'https://www.sphinx-doc.org/en/master'
html_baseurl = 'https://www.sphinx-doc.org/en/master/'
htmlhelp_basename = 'Sphinxdoc' htmlhelp_basename = 'Sphinxdoc'

View File

@ -230,11 +230,15 @@ connect handlers to the events. Example:
.. event:: missing-reference (app, env, node, contnode) .. event:: missing-reference (app, env, node, contnode)
Emitted when a cross-reference to a Python module or object cannot be Emitted when a cross-reference to an object cannot be resolved.
resolved. If the event handler can resolve the reference, it should return a If the event handler can resolve the reference, it should return a
new docutils node to be inserted in the document tree in place of the node new docutils node to be inserted in the document tree in place of the node
*node*. Usually this node is a :class:`reference` node containing *contnode* *node*. Usually this node is a :class:`reference` node containing *contnode*
as a child. as a child.
If the handler can not resolve the cross-reference,
it can either return ``None`` to let other handlers try,
or raise :class:`NoUri` to prevent other handlers in trying and suppress
a warning about this cross-reference being unresolved.
:param env: The build environment (``app.builder.env``). :param env: The build environment (``app.builder.env``).
:param node: The :class:`pending_xref` node to be resolved. Its attributes :param node: The :class:`pending_xref` node to be resolved. Its attributes

View File

@ -26,12 +26,63 @@ The following is a list of deprecated interfaces.
- (will be) Removed - (will be) Removed
- Alternatives - Alternatives
* - The first argument for
``sphinx.ext.autosummary.generate.AutosummaryRenderer`` has been changed
to Sphinx object
- 3.1
- 5.0
- N/A
* - ``sphinx.ext.autosummary.generate.AutosummaryRenderer`` takes an object
type as an argument
- 3.1
- 5.0
- N/A
* - The ``ignore`` argument of ``sphinx.ext.autodoc.Documenter.get_doc()``
- 3.1
- 5.0
- N/A
* - The ``template_dir`` argument of
``sphinx.ext.autosummary.generate.AutosummaryRenderer``
- 3.1
- 5.0
- N/A
* - The ``module`` argument of * - The ``module`` argument of
``sphinx.ext.autosummary.generate.find_autosummary_in_docstring()`` ``sphinx.ext.autosummary.generate.find_autosummary_in_docstring()``
- 3.0 - 3.0
- 5.0 - 5.0
- N/A - N/A
* - The ``builder`` argument of
``sphinx.ext.autosummary.generate.generate_autosummary_docs()``
- 3.1
- 5.0
- N/A
* - The ``template_dir`` argument of
``sphinx.ext.autosummary.generate.generate_autosummary_docs()``
- 3.1
- 5.0
- N/A
* - ``sphinx.ext.autosummary.generate.AutosummaryRenderer.exists()``
- 3.1
- 5.0
- N/A
* - The ``ignore`` argument of ``sphinx.util.docstring.prepare_docstring()``
- 3.1
- 5.0
- N/A
* - ``sphinx.util.rpartition()``
- 3.1
- 5.0
- ``str.rpartition()``
* - ``desc_signature['first']`` * - ``desc_signature['first']``
- -
- 3.0 - 3.0

View File

@ -90,9 +90,9 @@ section describe an easy way to translate with *sphinx-intl*.
locale_dirs = ['locale/'] # path is example but recommended. locale_dirs = ['locale/'] # path is example but recommended.
gettext_compact = False # optional. gettext_compact = False # optional.
This case-study assumes that :confval:`locale_dirs` is set to ``locale/`` and This case-study assumes that BUILDDIR is set to ``_build``,
:confval:`gettext_compact` is set to ``False`` (the Sphinx document is :confval:`locale_dirs` is set to ``locale/`` and :confval:`gettext_compact`
already configured as such). is set to ``False`` (the Sphinx document is already configured as such).
#. Extract translatable messages into pot files. #. Extract translatable messages into pot files.

View File

@ -1385,7 +1385,7 @@ that use Sphinx's HTMLWriter class.
.. versionadded:: 1.3 .. versionadded:: 1.3
.. versionchanged:: 2.4 .. versionchanged:: 3.0
It is disabled for images having ``no-scaled-link`` class It is disabled for images having ``no-scaled-link`` class
@ -2119,6 +2119,13 @@ These options influence LaTeX output.
.. versionadded:: 3.0 .. versionadded:: 3.0
.. confval:: latex_theme_options
A dictionary of options that influence the look and feel of the selected
theme.
.. versionadded:: 3.1
.. confval:: latex_theme_path .. confval:: latex_theme_path
A list of paths that contain custom LaTeX themes as subdirectories. Relative A list of paths that contain custom LaTeX themes as subdirectories. Relative
@ -2479,6 +2486,30 @@ Options for the XML builder
match any sequence of characters *including* slashes. match any sequence of characters *including* slashes.
.. _c-config:
Options for the C domain
------------------------
.. confval:: c_id_attributes
A list of strings that the parser additionally should accept as attributes.
This can for example be used when attributes have been ``#define`` d for
portability.
.. versionadded:: 3.0
.. confval:: c_paren_attributes
A list of strings that the parser additionally should accept as attributes
with one argument. That is, if ``my_align_as`` is in the list, then
``my_align_as(X)`` is parsed as an attribute for all strings ``X`` that have
balanced braces (``()``, ``[]``, and ``{}``). This can for example be used
when attributes have been ``#define`` d for portability.
.. versionadded:: 3.0
.. _cpp-config: .. _cpp-config:
Options for the C++ domain Options for the C++ domain

View File

@ -154,6 +154,21 @@ inserting them into the page source under a suitable :rst:dir:`py:module`,
.. versionadded:: 3.0 .. versionadded:: 3.0
* autodoc considers a member public if its docstring contains
``:meta public:`` in its :ref:`info-field-lists`, even if it starts with
an underscore.
For example:
.. code-block:: rst
def _my_function(my_arg, my_other_arg):
"""blah blah blah
:meta public:
"""
.. versionadded:: 3.1
* Python "special" members (that is, those named like ``__special__``) will * Python "special" members (that is, those named like ``__special__``) will
be included if the ``special-members`` flag option is given:: be included if the ``special-members`` flag option is given::

View File

@ -32,7 +32,8 @@ The :mod:`sphinx.ext.autosummary` extension does this in two parts:
The :rst:dir:`autosummary` directive can also optionally serve as a The :rst:dir:`autosummary` directive can also optionally serve as a
:rst:dir:`toctree` entry for the included items. Optionally, stub :rst:dir:`toctree` entry for the included items. Optionally, stub
``.rst`` files for these items can also be automatically generated. ``.rst`` files for these items can also be automatically generated
when :confval:`autosummary_generate` is `True`.
For example, :: For example, ::
@ -76,6 +77,12 @@ The :mod:`sphinx.ext.autosummary` extension does this in two parts:
directory. If no argument is given, output is placed in the same directory directory. If no argument is given, output is placed in the same directory
as the file that contains the directive. as the file that contains the directive.
You can also use ``caption`` option to give a caption to the toctree.
.. versionadded:: 3.1
caption option added.
* If you don't want the :rst:dir:`autosummary` to show function signatures in * If you don't want the :rst:dir:`autosummary` to show function signatures in
the listing, include the ``nosignatures`` option:: the listing, include the ``nosignatures`` option::
@ -99,6 +106,17 @@ The :mod:`sphinx.ext.autosummary` extension does this in two parts:
.. versionadded:: 1.0 .. versionadded:: 1.0
* You can specify the ``recursive`` option to generate documents for
modules and sub-packages recursively. It defaults to disabled.
For example, ::
.. autosummary::
:recursive:
sphinx.environment.BuildEnvironment
.. versionadded:: 3.1
:program:`sphinx-autogen` -- generate autodoc stub pages :program:`sphinx-autogen` -- generate autodoc stub pages
-------------------------------------------------------- --------------------------------------------------------
@ -133,10 +151,17 @@ Generating stub pages automatically
If you do not want to create stub pages with :program:`sphinx-autogen`, you can If you do not want to create stub pages with :program:`sphinx-autogen`, you can
also use these config values: also use these config values:
.. confval:: autosummary_context
A dictionary of values to pass into the template engine's context for
autosummary stubs files.
.. versionadded:: 3.1
.. confval:: autosummary_generate .. confval:: autosummary_generate
Boolean indicating whether to scan all found documents for autosummary Boolean indicating whether to scan all found documents for autosummary
directives, and to generate stub pages for each. directives, and to generate stub pages for each. It is disabled by default.
Can also be a list of documents for which stub pages should be generated. Can also be a list of documents for which stub pages should be generated.
@ -263,6 +288,12 @@ The following variables available in the templates:
List containing names of "public" attributes in the class/module. Only List containing names of "public" attributes in the class/module. Only
available for classes and modules. available for classes and modules.
.. data:: modules
List containing names of "public" modules in the package. Only available for
modules that are packages.
.. versionadded:: 3.1
Additionally, the following filters are available Additionally, the following filters are available

View File

@ -132,8 +132,8 @@ a comma-separated list of group names.
.. testcode:: .. testcode::
1+1 # this will give no output! 1+1 # this will give no output!
print 2+2 # this will give output print(2+2) # this will give output
.. testoutput:: .. testoutput::
@ -161,7 +161,7 @@ a comma-separated list of group names.
.. testcode:: .. testcode::
print 'Output text.' print('Output text.')
.. testoutput:: .. testoutput::
:hide: :hide:
@ -328,7 +328,7 @@ The doctest extension uses the following configuration values:
Some documentation text. Some documentation text.
>>> print 1 >>> print(1)
1 1
Some more documentation text. Some more documentation text.
@ -344,7 +344,7 @@ The doctest extension uses the following configuration values:
.. doctest:: .. doctest::
>>> print 1 >>> print(1)
1 1
Some more documentation text. Some more documentation text.

View File

@ -34,7 +34,19 @@ Configuration
A path to :command:`convert` command. By default, the imgconverter uses A path to :command:`convert` command. By default, the imgconverter uses
the command from search paths. the command from search paths.
On windows platform, :command:`magick` command is used by default.
.. versionchanged:: 3.1
Use :command:`magick` command by default on windows
.. confval:: image_converter_args .. confval:: image_converter_args
Additional command-line arguments to give to :command:`convert`, as a list. Additional command-line arguments to give to :command:`convert`, as a list.
The default is an empty list ``[]``. The default is an empty list ``[]``.
On windows platform, it defaults to ``["convert"]``.
.. versionchanged:: 3.1
Use ``["convert"]`` by default on windows

View File

@ -212,6 +212,15 @@ The following directives are provided for module and class contents:
Describes an exception class. The signature can, but need not include Describes an exception class. The signature can, but need not include
parentheses with constructor arguments. parentheses with constructor arguments.
.. rubric:: options
.. rst:directive:option:: final
:type: no value
Indicate the class is a final class.
.. versionadded:: 3.1
.. rst:directive:: .. py:class:: name .. rst:directive:: .. py:class:: name
.. py:class:: name(parameters) .. py:class:: name(parameters)
@ -235,6 +244,15 @@ The following directives are provided for module and class contents:
The first way is the preferred one. The first way is the preferred one.
.. rubric:: options
.. rst:directive:option:: final
:type: no value
Indicate the class is a final class.
.. versionadded:: 3.1
.. rst:directive:: .. py:attribute:: name .. rst:directive:: .. py:attribute:: name
Describes an object data attribute. The description should include Describes an object data attribute. The description should include
@ -283,6 +301,13 @@ The following directives are provided for module and class contents:
.. versionadded:: 2.1 .. versionadded:: 2.1
.. rst:directive:option:: final
:type: no value
Indicate the class is a final method.
.. versionadded:: 3.1
.. rst:directive:option:: property .. rst:directive:option:: property
:type: no value :type: no value
@ -706,6 +731,77 @@ Inline Expressions and Types
.. versionadded:: 3.0 .. versionadded:: 3.0
Namespacing
~~~~~~~~~~~
.. versionadded:: 3.1
The C language it self does not support namespacing, but it can sometimes be
useful to emulate it in documentation, e.g., to show alternate declarations.
The feature may also be used to document members of structs/unions/enums
separate from their parent declaration.
The current scope can be changed using three namespace directives. They manage
a stack declarations where ``c:namespace`` resets the stack and changes a given
scope.
The ``c:namespace-push`` directive changes the scope to a given inner scope
of the current one.
The ``c:namespace-pop`` directive undoes the most recent
``c:namespace-push`` directive.
.. rst:directive:: .. c:namespace:: scope specification
Changes the current scope for the subsequent objects to the given scope, and
resets the namespace directive stack. Note that nested scopes can be
specified by separating with a dot, e.g.::
.. c:namespace:: Namespace1.Namespace2.SomeStruct.AnInnerStruct
All subsequent objects will be defined as if their name were declared with
the scope prepended. The subsequent cross-references will be searched for
starting in the current scope.
Using ``NULL`` or ``0`` as the scope will change to global scope.
.. rst:directive:: .. c:namespace-push:: scope specification
Change the scope relatively to the current scope. For example, after::
.. c:namespace:: A.B
.. c:namespace-push:: C.D
the current scope will be ``A.B.C.D``.
.. rst:directive:: .. c:namespace-pop::
Undo the previous ``c:namespace-push`` directive (*not* just pop a scope).
For example, after::
.. c:namespace:: A.B
.. c:namespace-push:: C.D
.. c:namespace-pop::
the current scope will be ``A.B`` (*not* ``A.B.C``).
If no previous ``c:namespace-push`` directive has been used, but only a
``c:namespace`` directive, then the current scope will be reset to global
scope. That is, ``.. c:namespace:: A.B`` is equivalent to::
.. c:namespace:: NULL
.. c:namespace-push:: A.B
Configuration Variables
~~~~~~~~~~~~~~~~~~~~~~~
See :ref:`c-config`.
.. _cpp-domain: .. _cpp-domain:
The C++ Domain The C++ Domain

View File

@ -155,6 +155,21 @@ These themes are:
previous/next page using the keyboard's left and right arrows. Defaults to previous/next page using the keyboard's left and right arrows. Defaults to
``False``. ``False``.
- **globaltoc_collapse** (true or false): Only expand subsections
of the current document in ``globaltoc.html``
(see :confval:`html_sidebars`).
Defaults to ``True``.
.. versionadded:: 3.1
- **globaltoc_includehidden** (true or false): Show even those
subsections in ``globaltoc.html`` (see :confval:`html_sidebars`)
which have been included with the ``:hidden:`` flag of the
:rst:dir:`toctree` directive.
Defaults to ``False``.
.. versionadded:: 3.1
**alabaster** **alabaster**
`Alabaster theme`_ is a modified "Kr" Sphinx theme from @kennethreitz `Alabaster theme`_ is a modified "Kr" Sphinx theme from @kennethreitz
(especially as used in his Requests project), which was itself originally (especially as used in his Requests project), which was itself originally

View File

@ -54,6 +54,8 @@ strict_optional = False
filterwarnings = filterwarnings =
all all
ignore::DeprecationWarning:docutils.io ignore::DeprecationWarning:docutils.io
ignore::DeprecationWarning:pyximport.pyximport
ignore::PendingDeprecationWarning:sphinx.util.pycompat
markers = markers =
sphinx sphinx
apidoc apidoc

View File

@ -56,6 +56,7 @@ if __version__.endswith('+'):
__version__ = __version__[:-1] # remove '+' for PEP-440 version spec. __version__ = __version__[:-1] # remove '+' for PEP-440 version spec.
try: try:
ret = subprocess.run(['git', 'show', '-s', '--pretty=format:%h'], ret = subprocess.run(['git', 'show', '-s', '--pretty=format:%h'],
cwd=package_dir,
stdout=PIPE, stderr=PIPE) stdout=PIPE, stderr=PIPE)
if ret.stdout: if ret.stdout:
__display_version__ += '/' + ret.stdout.decode('ascii').strip() __display_version__ += '/' + ret.stdout.decode('ascii').strip()

View File

@ -112,6 +112,13 @@ class desc_signature(nodes.Part, nodes.Inline, nodes.TextElement):
In that case all child nodes must be ``desc_signature_line`` nodes. In that case all child nodes must be ``desc_signature_line`` nodes.
""" """
@property
def child_text_separator(self):
if self.get('is_multiline'):
return ' '
else:
return super().child_text_separator
class desc_signature_line(nodes.Part, nodes.Inline, nodes.FixedTextElement): class desc_signature_line(nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for a line in a multi-line object signatures. """Node for a line in a multi-line object signatures.
@ -150,6 +157,9 @@ class desc_parameterlist(nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for a general parameter list.""" """Node for a general parameter list."""
child_text_separator = ', ' child_text_separator = ', '
def astext(self):
return '({})'.format(super().astext())
class desc_parameter(nodes.Part, nodes.Inline, nodes.FixedTextElement): class desc_parameter(nodes.Part, nodes.Inline, nodes.FixedTextElement):
"""Node for a single parameter.""" """Node for a single parameter."""

View File

@ -204,7 +204,7 @@ class Sphinx:
# notice for parallel build on macOS and py38+ # notice for parallel build on macOS and py38+
if sys.version_info > (3, 8) and platform.system() == 'Darwin' and parallel > 1: if sys.version_info > (3, 8) and platform.system() == 'Darwin' and parallel > 1:
logger.info(bold(__("For security reason, parallel mode is disabled on macOS and " logger.info(bold(__("For security reason, parallel mode is disabled on macOS and "
"python3.8 and above. For more details, please read " "python3.8 and above. For more details, please read "
"https://github.com/sphinx-doc/sphinx/issues/6803"))) "https://github.com/sphinx-doc/sphinx/issues/6803")))
# status code for command-line application # status code for command-line application
@ -436,22 +436,32 @@ class Sphinx:
logger.debug('[app] disconnecting event: [id=%s]', listener_id) logger.debug('[app] disconnecting event: [id=%s]', listener_id)
self.events.disconnect(listener_id) self.events.disconnect(listener_id)
def emit(self, event: str, *args: Any) -> List: def emit(self, event: str, *args: Any,
allowed_exceptions: Tuple["Type[Exception]", ...] = ()) -> List:
"""Emit *event* and pass *arguments* to the callback functions. """Emit *event* and pass *arguments* to the callback functions.
Return the return values of all callbacks as a list. Do not emit core Return the return values of all callbacks as a list. Do not emit core
Sphinx events in extensions! Sphinx events in extensions!
"""
return self.events.emit(event, *args)
def emit_firstresult(self, event: str, *args: Any) -> Any: .. versionchanged:: 3.1
Added *allowed_exceptions* to specify path-through exceptions
"""
return self.events.emit(event, *args, allowed_exceptions=allowed_exceptions)
def emit_firstresult(self, event: str, *args: Any,
allowed_exceptions: Tuple["Type[Exception]", ...] = ()) -> Any:
"""Emit *event* and pass *arguments* to the callback functions. """Emit *event* and pass *arguments* to the callback functions.
Return the result of the first callback that doesn't return ``None``. Return the result of the first callback that doesn't return ``None``.
.. versionadded:: 0.5 .. versionadded:: 0.5
.. versionchanged:: 3.1
Added *allowed_exceptions* to specify path-through exceptions
""" """
return self.events.emit_firstresult(event, *args) return self.events.emit_firstresult(event, *args,
allowed_exceptions=allowed_exceptions)
# registering addon parts # registering addon parts
@ -990,7 +1000,7 @@ class Sphinx:
if isinstance(lexer, Lexer): if isinstance(lexer, Lexer):
warnings.warn('app.add_lexer() API changed; ' warnings.warn('app.add_lexer() API changed; '
'Please give lexer class instead instance', 'Please give lexer class instead instance',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
lexers[alias] = lexer lexers[alias] = lexer
else: else:
lexer_classes[alias] = lexer lexer_classes[alias] = lexer

View File

@ -173,7 +173,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
"""Replace all characters not allowed in text an attribute values.""" """Replace all characters not allowed in text an attribute values."""
warnings.warn( warnings.warn(
'%s.esc() is deprecated. Use html.escape() instead.' % self.__class__.__name__, '%s.esc() is deprecated. Use html.escape() instead.' % self.__class__.__name__,
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
name = name.replace('&', '&amp;') name = name.replace('&', '&amp;')
name = name.replace('<', '&lt;') name = name.replace('<', '&lt;')
name = name.replace('>', '&gt;') name = name.replace('>', '&gt;')

View File

@ -32,7 +32,7 @@ deprecated_alias('sphinx.builders.applehelp',
def setup(app: Sphinx) -> Dict[str, Any]: def setup(app: Sphinx) -> Dict[str, Any]:
warnings.warn('sphinx.builders.applehelp has been moved to sphinxcontrib-applehelp.', warnings.warn('sphinx.builders.applehelp has been moved to sphinxcontrib-applehelp.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
app.setup_extension('sphinxcontrib.applehelp') app.setup_extension('sphinxcontrib.applehelp')
return { return {

View File

@ -13,7 +13,6 @@ import posixpath
import re import re
import sys import sys
import warnings import warnings
from hashlib import md5
from os import path from os import path
from typing import Any, Dict, IO, Iterable, Iterator, List, Set, Tuple from typing import Any, Dict, IO, Iterable, Iterator, List, Set, Tuple
@ -38,7 +37,7 @@ from sphinx.highlighting import PygmentsBridge
from sphinx.locale import _, __ from sphinx.locale import _, __
from sphinx.search import js_index from sphinx.search import js_index
from sphinx.theming import HTMLThemeFactory from sphinx.theming import HTMLThemeFactory
from sphinx.util import logging, progress_message, status_iterator from sphinx.util import logging, progress_message, status_iterator, md5
from sphinx.util.docutils import is_html5_writer_available, new_document from sphinx.util.docutils import is_html5_writer_available, new_document
from sphinx.util.fileutil import copy_asset from sphinx.util.fileutil import copy_asset
from sphinx.util.i18n import format_date from sphinx.util.i18n import format_date
@ -882,7 +881,7 @@ class StandaloneHTMLBuilder(Builder):
'The %s.feed() method signature is deprecated. Update to ' 'The %s.feed() method signature is deprecated. Update to '
'%s.feed(docname, filename, title, doctree).' % ( '%s.feed(docname, filename, title, doctree).' % (
indexer_name, indexer_name), indexer_name, indexer_name),
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
def _get_local_toctree(self, docname: str, collapse: bool = True, **kwargs: Any) -> str: def _get_local_toctree(self, docname: str, collapse: bool = True, **kwargs: Any) -> str:
if 'includehidden' not in kwargs: if 'includehidden' not in kwargs:
@ -1243,6 +1242,9 @@ def setup(app: Sphinx) -> Dict[str, Any]:
# load default math renderer # load default math renderer
app.setup_extension('sphinx.ext.mathjax') app.setup_extension('sphinx.ext.mathjax')
# load transforms for HTML builder
app.setup_extension('sphinx.builders.html.transforms')
return { return {
'version': 'builtin', 'version': 'builtin',
'parallel_read_safe': True, 'parallel_read_safe': True,

View File

@ -0,0 +1,69 @@
"""
sphinx.builders.html.transforms
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Transforms for HTML builder.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import re
from typing import Any, Dict
from docutils import nodes
from sphinx.application import Sphinx
from sphinx.transforms.post_transforms import SphinxPostTransform
from sphinx.util.nodes import NodeMatcher
class KeyboardTransform(SphinxPostTransform):
"""Transform :kbd: role to more detailed form.
Before::
<literal class="kbd">
Control-x
After::
<literal class="kbd">
<literal class="kbd">
Control
-
<literal class="kbd">
x
"""
default_priority = 400
builders = ('html',)
pattern = re.compile(r'(-|\+|\^|\s+)')
def run(self, **kwargs: Any) -> None:
matcher = NodeMatcher(nodes.literal, classes=["kbd"])
for node in self.document.traverse(matcher): # type: nodes.literal
parts = self.pattern.split(node[-1].astext())
if len(parts) == 1:
continue
node.pop()
while parts:
key = parts.pop(0)
node += nodes.literal('', key, classes=["kbd"])
try:
# key separator (ex. -, +, ^)
sep = parts.pop(0)
node += nodes.Text(sep)
except IndexError:
pass
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_post_transform(KeyboardTransform)
return {
'version': 'builtin',
'parallel_read_safe': True,
'parallel_write_safe': True,
}

View File

@ -32,7 +32,7 @@ deprecated_alias('sphinx.builders.htmlhelp',
def setup(app: Sphinx) -> Dict[str, Any]: def setup(app: Sphinx) -> Dict[str, Any]:
warnings.warn('sphinx.builders.htmlhelp has been moved to sphinxcontrib-htmlhelp.', warnings.warn('sphinx.builders.htmlhelp has been moved to sphinxcontrib-htmlhelp.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
app.setup_extension('sphinxcontrib.htmlhelp') app.setup_extension('sphinxcontrib.htmlhelp')
return { return {

View File

@ -54,13 +54,13 @@ XINDY_LANG_OPTIONS = {
'hr': '-L croatian -C utf8 ', 'hr': '-L croatian -C utf8 ',
'cs': '-L czech -C utf8 ', 'cs': '-L czech -C utf8 ',
'da': '-L danish -C utf8 ', 'da': '-L danish -C utf8 ',
'nl': '-L dutch -C ij-as-ij-utf8 ', 'nl': '-L dutch-ij-as-ij -C utf8 ',
'en': '-L english -C utf8 ', 'en': '-L english -C utf8 ',
'eo': '-L esperanto -C utf8 ', 'eo': '-L esperanto -C utf8 ',
'et': '-L estonian -C utf8 ', 'et': '-L estonian -C utf8 ',
'fi': '-L finnish -C utf8 ', 'fi': '-L finnish -C utf8 ',
'fr': '-L french -C utf8 ', 'fr': '-L french -C utf8 ',
'de': '-L german -C din5007-utf8 ', 'de': '-L german-din5007 -C utf8 ',
'is': '-L icelandic -C utf8 ', 'is': '-L icelandic -C utf8 ',
'it': '-L italian -C utf8 ', 'it': '-L italian -C utf8 ',
'la': '-L latin -C utf8 ', 'la': '-L latin -C utf8 ',
@ -73,9 +73,9 @@ XINDY_LANG_OPTIONS = {
'pl': '-L polish -C utf8 ', 'pl': '-L polish -C utf8 ',
'pt': '-L portuguese -C utf8 ', 'pt': '-L portuguese -C utf8 ',
'ro': '-L romanian -C utf8 ', 'ro': '-L romanian -C utf8 ',
'sk': '-L slovak -C small-utf8 ', # there is also slovak-large 'sk': '-L slovak-small -C utf8 ', # there is also slovak-large
'sl': '-L slovenian -C utf8 ', 'sl': '-L slovenian -C utf8 ',
'es': '-L spanish -C modern-utf8 ', # there is also spanish-traditional 'es': '-L spanish-modern -C utf8 ', # there is also spanish-traditional
'sv': '-L swedish -C utf8 ', 'sv': '-L swedish -C utf8 ',
'tr': '-L turkish -C utf8 ', 'tr': '-L turkish -C utf8 ',
'hsb': '-L upper-sorbian -C utf8 ', 'hsb': '-L upper-sorbian -C utf8 ',
@ -86,7 +86,7 @@ XINDY_LANG_OPTIONS = {
'be': '-L belarusian -C utf8 ', 'be': '-L belarusian -C utf8 ',
'bg': '-L bulgarian -C utf8 ', 'bg': '-L bulgarian -C utf8 ',
'mk': '-L macedonian -C utf8 ', 'mk': '-L macedonian -C utf8 ',
'mn': '-L mongolian -C cyrillic-utf8 ', 'mn': '-L mongolian-cyrillic -C utf8 ',
'ru': '-L russian -C utf8 ', 'ru': '-L russian -C utf8 ',
'sr': '-L serbian -C utf8 ', 'sr': '-L serbian -C utf8 ',
'sh-cyrl': '-L serbian -C utf8 ', 'sh-cyrl': '-L serbian -C utf8 ',
@ -96,7 +96,7 @@ XINDY_LANG_OPTIONS = {
# can work only with xelatex/lualatex, not supported by texindy+pdflatex # can work only with xelatex/lualatex, not supported by texindy+pdflatex
'el': '-L greek -C utf8 ', 'el': '-L greek -C utf8 ',
# FIXME, not compatible with [:2] slice but does Sphinx support Greek ? # FIXME, not compatible with [:2] slice but does Sphinx support Greek ?
'el-polyton': '-L greek -C polytonic-utf8 ', 'el-polyton': '-L greek-polytonic -C utf8 ',
} }
XINDY_CYRILLIC_SCRIPTS = [ XINDY_CYRILLIC_SCRIPTS = [
@ -314,6 +314,8 @@ class LaTeXBuilder(Builder):
self.context['title'] = title self.context['title'] = title
self.context['author'] = author self.context['author'] = author
self.context['docclass'] = theme.docclass self.context['docclass'] = theme.docclass
self.context['papersize'] = theme.papersize
self.context['pointsize'] = theme.pointsize
self.context['wrapperclass'] = theme.wrapperclass self.context['wrapperclass'] = theme.wrapperclass
def assemble_doctree(self, indexfile: str, toctree_only: bool, appendices: List[str]) -> nodes.document: # NOQA def assemble_doctree(self, indexfile: str, toctree_only: bool, appendices: List[str]) -> nodes.document: # NOQA
@ -361,7 +363,7 @@ class LaTeXBuilder(Builder):
def apply_transforms(self, doctree: nodes.document) -> None: def apply_transforms(self, doctree: nodes.document) -> None:
warnings.warn('LaTeXBuilder.apply_transforms() is deprecated.', warnings.warn('LaTeXBuilder.apply_transforms() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
def finish(self) -> None: def finish(self) -> None:
self.copy_image_files() self.copy_image_files()
@ -491,6 +493,14 @@ def validate_config_values(app: Sphinx, config: Config) -> None:
config.latex_elements.pop(key) config.latex_elements.pop(key)
def validate_latex_theme_options(app: Sphinx, config: Config) -> None:
for key in list(config.latex_theme_options):
if key not in Theme.UPDATABLE_KEYS:
msg = __("Unknown theme option: latex_theme_options[%r], ignored.")
logger.warning(msg % (key,))
config.latex_theme_options.pop(key)
def default_latex_engine(config: Config) -> str: def default_latex_engine(config: Config) -> str:
""" Better default latex_engine settings for specific languages. """ """ Better default latex_engine settings for specific languages. """
if config.language == 'ja': if config.language == 'ja':
@ -537,6 +547,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_builder(LaTeXBuilder) app.add_builder(LaTeXBuilder)
app.connect('config-inited', validate_config_values, priority=800) app.connect('config-inited', validate_config_values, priority=800)
app.connect('config-inited', validate_latex_theme_options, priority=800)
app.add_config_value('latex_engine', default_latex_engine, None, app.add_config_value('latex_engine', default_latex_engine, None,
ENUM('pdflatex', 'xelatex', 'lualatex', 'platex', 'uplatex')) ENUM('pdflatex', 'xelatex', 'lualatex', 'platex', 'uplatex'))
@ -553,6 +564,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_config_value('latex_elements', {}, None) app.add_config_value('latex_elements', {}, None)
app.add_config_value('latex_additional_files', [], None) app.add_config_value('latex_additional_files', [], None)
app.add_config_value('latex_theme', 'manual', None, [str]) app.add_config_value('latex_theme', 'manual', None, [str])
app.add_config_value('latex_theme_options', {}, None)
app.add_config_value('latex_theme_path', [], None, [list]) app.add_config_value('latex_theme_path', [], None, [list])
app.add_config_value('latex_docclass', default_latex_docclass, None) app.add_config_value('latex_docclass', default_latex_docclass, None)

View File

@ -69,8 +69,8 @@ LUALATEX_DEFAULT_FONTPKG = XELATEX_DEFAULT_FONTPKG
DEFAULT_SETTINGS = { DEFAULT_SETTINGS = {
'latex_engine': 'pdflatex', 'latex_engine': 'pdflatex',
'papersize': 'letterpaper', 'papersize': '',
'pointsize': '10pt', 'pointsize': '',
'pxunit': '.75bp', 'pxunit': '.75bp',
'classoptions': '', 'classoptions': '',
'extraclassoptions': '', 'extraclassoptions': '',

View File

@ -24,50 +24,59 @@ logger = logging.getLogger(__name__)
class Theme: class Theme:
"""A set of LaTeX configurations.""" """A set of LaTeX configurations."""
LATEX_ELEMENTS_KEYS = ['papersize', 'pointsize']
UPDATABLE_KEYS = ['papersize', 'pointsize']
def __init__(self, name: str) -> None: def __init__(self, name: str) -> None:
self.name = name self.name = name
self.docclass = name self.docclass = name
self.wrapperclass = name self.wrapperclass = name
self.papersize = 'letterpaper'
self.pointsize = '10pt'
self.toplevel_sectioning = 'chapter' self.toplevel_sectioning = 'chapter'
def update(self, config: Config) -> None:
"""Override theme settings by user's configuration."""
for key in self.LATEX_ELEMENTS_KEYS:
if config.latex_elements.get(key):
value = config.latex_elements[key]
setattr(self, key, value)
for key in self.UPDATABLE_KEYS:
if key in config.latex_theme_options:
value = config.latex_theme_options[key]
setattr(self, key, value)
class BuiltInTheme(Theme): class BuiltInTheme(Theme):
"""A built-in LaTeX theme.""" """A built-in LaTeX theme."""
def __init__(self, name: str, config: Config) -> None: def __init__(self, name: str, config: Config) -> None:
# Note: Don't call supermethod here. super().__init__(name)
self.name = name
self.latex_docclass = config.latex_docclass # type: Dict[str, str]
@property if name == 'howto':
def docclass(self) -> str: # type: ignore self.docclass = config.latex_docclass.get('howto', 'article')
if self.name == 'howto':
return self.latex_docclass.get('howto', 'article')
else: else:
return self.latex_docclass.get('manual', 'report') self.docclass = config.latex_docclass.get('manual', 'report')
@property if name in ('manual', 'howto'):
def wrapperclass(self) -> str: # type: ignore self.wrapperclass = 'sphinx' + name
if self.name in ('manual', 'howto'):
return 'sphinx' + self.name
else: else:
return self.name self.wrapperclass = name
@property
def toplevel_sectioning(self) -> str: # type: ignore
# we assume LaTeX class provides \chapter command except in case # we assume LaTeX class provides \chapter command except in case
# of non-Japanese 'howto' case # of non-Japanese 'howto' case
if self.name == 'howto' and not self.docclass.startswith('j'): if name == 'howto' and not self.docclass.startswith('j'):
return 'section' self.toplevel_sectioning = 'section'
else: else:
return 'chapter' self.toplevel_sectioning = 'chapter'
class UserTheme(Theme): class UserTheme(Theme):
"""A user defined LaTeX theme.""" """A user defined LaTeX theme."""
REQUIRED_CONFIG_KEYS = ['docclass', 'wrapperclass'] REQUIRED_CONFIG_KEYS = ['docclass', 'wrapperclass']
OPTIONAL_CONFIG_KEYS = ['toplevel_sectioning'] OPTIONAL_CONFIG_KEYS = ['papersize', 'pointsize', 'toplevel_sectioning']
def __init__(self, name: str, filename: str) -> None: def __init__(self, name: str, filename: str) -> None:
super().__init__(name) super().__init__(name)
@ -97,6 +106,7 @@ class ThemeFactory:
def __init__(self, app: Sphinx) -> None: def __init__(self, app: Sphinx) -> None:
self.themes = {} # type: Dict[str, Theme] self.themes = {} # type: Dict[str, Theme]
self.theme_paths = [path.join(app.srcdir, p) for p in app.config.latex_theme_path] self.theme_paths = [path.join(app.srcdir, p) for p in app.config.latex_theme_path]
self.config = app.config
self.load_builtin_themes(app.config) self.load_builtin_themes(app.config)
def load_builtin_themes(self, config: Config) -> None: def load_builtin_themes(self, config: Config) -> None:
@ -107,13 +117,14 @@ class ThemeFactory:
def get(self, name: str) -> Theme: def get(self, name: str) -> Theme:
"""Get a theme for given *name*.""" """Get a theme for given *name*."""
if name in self.themes: if name in self.themes:
return self.themes[name] theme = self.themes[name]
else: else:
theme = self.find_user_theme(name) theme = self.find_user_theme(name)
if theme: if not theme:
return theme theme = Theme(name)
else:
return Theme(name) theme.update(self.config)
return theme
def find_user_theme(self, name: str) -> Theme: def find_user_theme(self, name: str) -> Theme:
"""Find a theme named as *name* from latex_theme_path.""" """Find a theme named as *name* from latex_theme_path."""

View File

@ -8,6 +8,8 @@
:license: BSD, see LICENSE for details. :license: BSD, see LICENSE for details.
""" """
from typing import Optional
from docutils.writers.latex2e import Babel from docutils.writers.latex2e import Babel
@ -40,7 +42,7 @@ class ExtBabel(Babel):
self.supported = False self.supported = False
return 'english' # fallback to english return 'english' # fallback to english
def get_mainlanguage_options(self) -> str: def get_mainlanguage_options(self) -> Optional[str]:
"""Return options for polyglossia's ``\\setmainlanguage``.""" """Return options for polyglossia's ``\\setmainlanguage``."""
if self.use_polyglossia is False: if self.use_polyglossia is False:
return None return None

View File

@ -64,7 +64,7 @@ def handle_exception(app: Sphinx, args: Any, exception: BaseException, stderr: I
print(terminal_safe(str(exception)), file=stderr) print(terminal_safe(str(exception)), file=stderr)
print(file=stderr) print(file=stderr)
print(__('This can happen with very large or deeply nested source ' print(__('This can happen with very large or deeply nested source '
'files. You can carefully increase the default Python ' 'files. You can carefully increase the default Python '
'recursion limit of 1000 in conf.py with e.g.:'), file=stderr) 'recursion limit of 1000 in conf.py with e.g.:'), file=stderr)
print(' import sys; sys.setrecursionlimit(1500)', file=stderr) print(' import sys; sys.setrecursionlimit(1500)', file=stderr)
else: else:
@ -107,7 +107,7 @@ Generate documentation from source files.
sphinx-build generates documentation from the files in SOURCEDIR and places it sphinx-build generates documentation from the files in SOURCEDIR and places it
in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration
settings. The 'sphinx-quickstart' tool may be used to generate template files, settings. The 'sphinx-quickstart' tool may be used to generate template files,
including 'conf.py' including 'conf.py'
sphinx-build can create documentation in different formats. A format is sphinx-build can create documentation in different formats. A format is

View File

@ -187,7 +187,7 @@ def do_prompt(text: str, default: str = None, validator: Callable[[str], Any] =
def convert_python_source(source: str, rex: Pattern = re.compile(r"[uU]('.*?')")) -> str: def convert_python_source(source: str, rex: Pattern = re.compile(r"[uU]('.*?')")) -> str:
# remove Unicode literal prefixes # remove Unicode literal prefixes
warnings.warn('convert_python_source() is deprecated.', warnings.warn('convert_python_source() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
return rex.sub('\\1', source) return rex.sub('\\1', source)
@ -275,7 +275,7 @@ def ask_user(d: Dict) -> None:
print(__('Sphinx has the notion of a "version" and a "release" for the\n' print(__('Sphinx has the notion of a "version" and a "release" for the\n'
'software. Each version can have multiple releases. For example, for\n' 'software. Each version can have multiple releases. For example, for\n'
'Python the version is something like 2.5 or 3.0, while the release is\n' 'Python the version is something like 2.5 or 3.0, while the release is\n'
'something like 2.5.1 or 3.0a1. If you don\'t need this dual structure,\n' 'something like 2.5.1 or 3.0a1. If you don\'t need this dual structure,\n'
'just set both to the same value.')) 'just set both to the same value.'))
d['version'] = do_prompt(__('Project version'), '', allow_empty) d['version'] = do_prompt(__('Project version'), '', allow_empty)
if 'release' not in d: if 'release' not in d:
@ -296,7 +296,7 @@ def ask_user(d: Dict) -> None:
if 'suffix' not in d: if 'suffix' not in d:
print() print()
print(__('The file name suffix for source files. Commonly, this is either ".txt"\n' print(__('The file name suffix for source files. Commonly, this is either ".txt"\n'
'or ".rst". Only files with this suffix are considered documents.')) 'or ".rst". Only files with this suffix are considered documents.'))
d['suffix'] = do_prompt(__('Source file suffix'), '.rst', suffix) d['suffix'] = do_prompt(__('Source file suffix'), '.rst', suffix)
if 'master' not in d: if 'master' not in d:
@ -357,6 +357,7 @@ def generate(d: Dict, overwrite: bool = True, silent: bool = False, templatedir:
d.setdefault('extensions', []) d.setdefault('extensions', [])
d['copyright'] = time.strftime('%Y') + ', ' + d['author'] d['copyright'] = time.strftime('%Y') + ', ' + d['author']
d["path"] = os.path.abspath(d['path'])
ensuredir(d['path']) ensuredir(d['path'])
srcdir = path.join(d['path'], 'source') if d['sep'] else d['path'] srcdir = path.join(d['path'], 'source') if d['sep'] else d['path']

View File

@ -444,7 +444,7 @@ def check_unicode(config: Config) -> None:
since that can result in UnicodeErrors all over the place since that can result in UnicodeErrors all over the place
""" """
warnings.warn('sphinx.config.check_unicode() is deprecated.', warnings.warn('sphinx.config.check_unicode() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
nonascii_re = re.compile(br'[\x80-\xff]') nonascii_re = re.compile(br'[\x80-\xff]')

View File

@ -12,7 +12,10 @@ import sys
import warnings import warnings
from importlib import import_module from importlib import import_module
from typing import Any, Dict from typing import Any, Dict
from typing import Type # for python3.5.1
if False:
# For type annotation
from typing import Type # for python3.5.1
class RemovedInSphinx40Warning(DeprecationWarning): class RemovedInSphinx40Warning(DeprecationWarning):
@ -26,13 +29,13 @@ class RemovedInSphinx50Warning(PendingDeprecationWarning):
RemovedInNextVersionWarning = RemovedInSphinx40Warning RemovedInNextVersionWarning = RemovedInSphinx40Warning
def deprecated_alias(modname: str, objects: Dict, warning: Type[Warning]) -> None: def deprecated_alias(modname: str, objects: Dict, warning: "Type[Warning]") -> None:
module = import_module(modname) module = import_module(modname)
sys.modules[modname] = _ModuleWrapper(module, modname, objects, warning) # type: ignore sys.modules[modname] = _ModuleWrapper(module, modname, objects, warning) # type: ignore
class _ModuleWrapper: class _ModuleWrapper:
def __init__(self, module: Any, modname: str, objects: Dict, warning: Type[Warning] def __init__(self, module: Any, modname: str, objects: Dict, warning: "Type[Warning]"
) -> None: ) -> None:
self._module = module self._module = module
self._modname = modname self._modname = modname
@ -52,7 +55,7 @@ class _ModuleWrapper:
class DeprecatedDict(dict): class DeprecatedDict(dict):
"""A deprecated dict which warns on each access.""" """A deprecated dict which warns on each access."""
def __init__(self, data: Dict, message: str, warning: Type[Warning]) -> None: def __init__(self, data: Dict, message: str, warning: "Type[Warning]") -> None:
self.message = message self.message = message
self.warning = warning self.warning = warning
super().__init__(data) super().__init__(data)
@ -73,6 +76,6 @@ class DeprecatedDict(dict):
warnings.warn(self.message, self.warning, stacklevel=2) warnings.warn(self.message, self.warning, stacklevel=2)
return super().get(key, default) return super().get(key, default)
def update(self, other: Dict = None) -> None: # type: ignore def update(self, other: Dict) -> None: # type: ignore
warnings.warn(self.message, self.warning, stacklevel=2) warnings.warn(self.message, self.warning, stacklevel=2)
super().update(other) super().update(other)

View File

@ -31,10 +31,12 @@ from sphinx.util.cfamily import (
NoOldIdError, ASTBaseBase, verify_description_mode, StringifyTransform, NoOldIdError, ASTBaseBase, verify_description_mode, StringifyTransform,
BaseParser, DefinitionError, UnsupportedMultiCharacterCharLiteral, BaseParser, DefinitionError, UnsupportedMultiCharacterCharLiteral,
identifier_re, anon_identifier_re, integer_literal_re, octal_literal_re, identifier_re, anon_identifier_re, integer_literal_re, octal_literal_re,
hex_literal_re, binary_literal_re, float_literal_re, hex_literal_re, binary_literal_re, integers_literal_suffix_re,
float_literal_re, float_literal_suffix_re,
char_literal_re char_literal_re
) )
from sphinx.util.docfields import Field, TypedField from sphinx.util.docfields import Field, TypedField
from sphinx.util.docutils import SphinxDirective
from sphinx.util.nodes import make_refnode from sphinx.util.nodes import make_refnode
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -184,11 +186,17 @@ class ASTNestedName(ASTBase):
# If lastIsName, then wrap all of the prefix in a desc_addname, # If lastIsName, then wrap all of the prefix in a desc_addname,
# else append directly to signode. # else append directly to signode.
# TODO: also for C? # TODO: also for C?
# NOTE: Breathe relies on the prefix being in the desc_addname node, # NOTE: Breathe previously relied on the prefix being in the desc_addname node,
# so it can remove it in inner declarations. # so it can remove it in inner declarations.
dest = signode dest = signode
if mode == 'lastIsName': if mode == 'lastIsName':
dest = addnodes.desc_addname() dest = addnodes.desc_addname()
if self.rooted:
prefix += '.'
if mode == 'lastIsName' and len(names) == 0:
signode += nodes.Text('.')
else:
dest += nodes.Text('.')
for i in range(len(names)): for i in range(len(names)):
ident = names[i] ident = names[i]
if not first: if not first:
@ -791,20 +799,60 @@ class ASTDeclSpecs(ASTBase):
################################################################################ ################################################################################
class ASTArray(ASTBase): class ASTArray(ASTBase):
def __init__(self, size: ASTExpression): def __init__(self, static: bool, const: bool, volatile: bool, restrict: bool,
vla: bool, size: ASTExpression):
self.static = static
self.const = const
self.volatile = volatile
self.restrict = restrict
self.vla = vla
self.size = size self.size = size
if vla:
assert size is None
if size is not None:
assert not vla
def _stringify(self, transform: StringifyTransform) -> str: def _stringify(self, transform: StringifyTransform) -> str:
if self.size: el = []
return '[' + transform(self.size) + ']' if self.static:
else: el.append('static')
return '[]' if self.restrict:
el.append('restrict')
if self.volatile:
el.append('volatile')
if self.const:
el.append('const')
if self.vla:
return '[' + ' '.join(el) + '*]'
elif self.size:
el.append(transform(self.size))
return '[' + ' '.join(el) + ']'
def describe_signature(self, signode: TextElement, mode: str, def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None: env: "BuildEnvironment", symbol: "Symbol") -> None:
verify_description_mode(mode) verify_description_mode(mode)
signode.append(nodes.Text("[")) signode.append(nodes.Text("["))
if self.size: addSpace = False
def _add(signode: TextElement, text: str) -> bool:
if addSpace:
signode += nodes.Text(' ')
signode += addnodes.desc_annotation(text, text)
return True
if self.static:
addSpace = _add(signode, 'static')
if self.restrict:
addSpace = _add(signode, 'restrict')
if self.volatile:
addSpace = _add(signode, 'volatile')
if self.const:
addSpace = _add(signode, 'const')
if self.vla:
signode.append(nodes.Text('*'))
elif self.size:
if addSpace:
signode += nodes.Text(' ')
self.size.describe_signature(signode, mode, env, symbol) self.size.describe_signature(signode, mode, env, symbol)
signode.append(nodes.Text("]")) signode.append(nodes.Text("]"))
@ -1271,10 +1319,12 @@ class ASTEnumerator(ASTBase):
class ASTDeclaration(ASTBaseBase): class ASTDeclaration(ASTBaseBase):
def __init__(self, objectType: str, directiveType: str, declaration: Any) -> None: def __init__(self, objectType: str, directiveType: str, declaration: Any,
semicolon: bool = False) -> None:
self.objectType = objectType self.objectType = objectType
self.directiveType = directiveType self.directiveType = directiveType
self.declaration = declaration self.declaration = declaration
self.semicolon = semicolon
self.symbol = None # type: Symbol self.symbol = None # type: Symbol
# set by CObject._add_enumerator_to_parent # set by CObject._add_enumerator_to_parent
@ -1303,7 +1353,10 @@ class ASTDeclaration(ASTBaseBase):
return self.get_id(_max_id, True) return self.get_id(_max_id, True)
def _stringify(self, transform: StringifyTransform) -> str: def _stringify(self, transform: StringifyTransform) -> str:
return transform(self.declaration) res = transform(self.declaration)
if self.semicolon:
res += ';'
return res
def describe_signature(self, signode: TextElement, mode: str, def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", options: Dict) -> None: env: "BuildEnvironment", options: Dict) -> None:
@ -1339,6 +1392,8 @@ class ASTDeclaration(ASTBaseBase):
else: else:
assert False assert False
self.declaration.describe_signature(mainDeclNode, mode, env, self.symbol) self.declaration.describe_signature(mainDeclNode, mode, env, self.symbol)
if self.semicolon:
mainDeclNode += nodes.Text(';')
class SymbolLookupResult: class SymbolLookupResult:
@ -1990,6 +2045,14 @@ class DefinitionParser(BaseParser):
def language(self) -> str: def language(self) -> str:
return 'C' return 'C'
@property
def id_attributes(self):
return self.config.c_id_attributes
@property
def paren_attributes(self):
return self.config.c_paren_attributes
def _parse_string(self) -> str: def _parse_string(self) -> str:
if self.current_char != '"': if self.current_char != '"':
return None return None
@ -2009,66 +2072,6 @@ class DefinitionParser(BaseParser):
self.pos += 1 self.pos += 1
return self.definition[startPos:self.pos] return self.definition[startPos:self.pos]
def _parse_attribute(self) -> Any:
return None
# self.skip_ws()
# # try C++11 style
# startPos = self.pos
# if self.skip_string_and_ws('['):
# if not self.skip_string('['):
# self.pos = startPos
# else:
# # TODO: actually implement the correct grammar
# arg = self._parse_balanced_token_seq(end=[']'])
# if not self.skip_string_and_ws(']'):
# self.fail("Expected ']' in end of attribute.")
# if not self.skip_string_and_ws(']'):
# self.fail("Expected ']' in end of attribute after [[...]")
# return ASTCPPAttribute(arg)
#
# # try GNU style
# if self.skip_word_and_ws('__attribute__'):
# if not self.skip_string_and_ws('('):
# self.fail("Expected '(' after '__attribute__'.")
# if not self.skip_string_and_ws('('):
# self.fail("Expected '(' after '__attribute__('.")
# attrs = []
# while 1:
# if self.match(identifier_re):
# name = self.matched_text
# self.skip_ws()
# if self.skip_string_and_ws('('):
# self.fail('Parameterized GNU style attribute not yet supported.')
# attrs.append(ASTGnuAttribute(name, None))
# # TODO: parse arguments for the attribute
# if self.skip_string_and_ws(','):
# continue
# elif self.skip_string_and_ws(')'):
# break
# else:
# self.fail("Expected identifier, ')', or ',' in __attribute__.")
# if not self.skip_string_and_ws(')'):
# self.fail("Expected ')' after '__attribute__((...)'")
# return ASTGnuAttributeList(attrs)
#
# # try the simple id attributes defined by the user
# for id in self.config.cpp_id_attributes:
# if self.skip_word_and_ws(id):
# return ASTIdAttribute(id)
#
# # try the paren attributes defined by the user
# for id in self.config.cpp_paren_attributes:
# if not self.skip_string_and_ws(id):
# continue
# if not self.skip_string('('):
# self.fail("Expected '(' after user-defined paren-attribute.")
# arg = self._parse_balanced_token_seq(end=[')'])
# if not self.skip_string(')'):
# self.fail("Expected ')' to end user-defined paren-attribute.")
# return ASTParenAttribute(id, arg)
return None
def _parse_literal(self) -> ASTLiteral: def _parse_literal(self) -> ASTLiteral:
# -> integer-literal # -> integer-literal
# | character-literal # | character-literal
@ -2080,12 +2083,14 @@ class DefinitionParser(BaseParser):
return ASTBooleanLiteral(True) return ASTBooleanLiteral(True)
if self.skip_word('false'): if self.skip_word('false'):
return ASTBooleanLiteral(False) return ASTBooleanLiteral(False)
for regex in [float_literal_re, binary_literal_re, hex_literal_re, pos = self.pos
if self.match(float_literal_re):
self.match(float_literal_suffix_re)
return ASTNumberLiteral(self.definition[pos:self.pos])
for regex in [binary_literal_re, hex_literal_re,
integer_literal_re, octal_literal_re]: integer_literal_re, octal_literal_re]:
pos = self.pos
if self.match(regex): if self.match(regex):
while self.current_char in 'uUlLfF': self.match(integers_literal_suffix_re)
self.pos += 1
return ASTNumberLiteral(self.definition[pos:self.pos]) return ASTNumberLiteral(self.definition[pos:self.pos])
string = self._parse_string() string = self._parse_string()
@ -2639,18 +2644,45 @@ class DefinitionParser(BaseParser):
self.skip_ws() self.skip_ws()
if typed and self.skip_string('['): if typed and self.skip_string('['):
self.skip_ws() self.skip_ws()
if self.skip_string(']'): static = False
arrayOps.append(ASTArray(None)) const = False
continue volatile = False
restrict = False
while True:
if not static:
if self.skip_word_and_ws('static'):
static = True
continue
if not const:
if self.skip_word_and_ws('const'):
const = True
continue
if not volatile:
if self.skip_word_and_ws('volatile'):
volatile = True
continue
if not restrict:
if self.skip_word_and_ws('restrict'):
restrict = True
continue
break
vla = False if static else self.skip_string_and_ws('*')
if vla:
if not self.skip_string(']'):
self.fail("Expected ']' in end of array operator.")
size = None
else:
if self.skip_string(']'):
size = None
else:
def parser() -> ASTExpression: def parser():
return self._parse_expression() return self._parse_expression()
size = self._parse_expression_fallback([']'], parser)
value = self._parse_expression_fallback([']'], parser) self.skip_ws()
if not self.skip_string(']'): if not self.skip_string(']'):
self.fail("Expected ']' in end of array operator.") self.fail("Expected ']' in end of array operator.")
arrayOps.append(ASTArray(value)) arrayOps.append(ASTArray(static, const, volatile, restrict, vla, size))
continue
else: else:
break break
param = self._parse_parameters(paramMode) param = self._parse_parameters(paramMode)
@ -2793,7 +2825,7 @@ class DefinitionParser(BaseParser):
declSpecs = self._parse_decl_specs(outer=outer, typed=False) declSpecs = self._parse_decl_specs(outer=outer, typed=False)
decl = self._parse_declarator(named=True, paramMode=outer, decl = self._parse_declarator(named=True, paramMode=outer,
typed=False) typed=False)
self.assert_end() self.assert_end(allowSemicolon=True)
except DefinitionError as exUntyped: except DefinitionError as exUntyped:
desc = "If just a name" desc = "If just a name"
prevErrors.append((exUntyped, desc)) prevErrors.append((exUntyped, desc))
@ -2926,7 +2958,15 @@ class DefinitionParser(BaseParser):
declaration = self._parse_type(named=True, outer='type') declaration = self._parse_type(named=True, outer='type')
else: else:
assert False assert False
return ASTDeclaration(objectType, directiveType, declaration) if objectType != 'macro':
self.skip_ws()
semicolon = self.skip_string(';')
else:
semicolon = False
return ASTDeclaration(objectType, directiveType, declaration, semicolon)
def parse_namespace_object(self) -> ASTNestedName:
return self._parse_nested_name()
def parse_xref_object(self) -> ASTNestedName: def parse_xref_object(self) -> ASTNestedName:
name = self._parse_nested_name() name = self._parse_nested_name()
@ -3081,7 +3121,7 @@ class CObject(ObjectDescription):
def handle_signature(self, sig: str, signode: TextElement) -> ASTDeclaration: def handle_signature(self, sig: str, signode: TextElement) -> ASTDeclaration:
parentSymbol = self.env.temp_data['c:parent_symbol'] # type: Symbol parentSymbol = self.env.temp_data['c:parent_symbol'] # type: Symbol
parser = DefinitionParser(sig, location=signode) parser = DefinitionParser(sig, location=signode, config=self.env.config)
try: try:
ast = self.parse_definition(parser) ast = self.parse_definition(parser)
parser.assert_end() parser.assert_end()
@ -3178,6 +3218,97 @@ class CTypeObject(CObject):
object_type = 'type' object_type = 'type'
class CNamespaceObject(SphinxDirective):
"""
This directive is just to tell Sphinx that we're documenting stuff in
namespace foo.
"""
has_content = False
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec = {} # type: Dict
def run(self) -> List[Node]:
rootSymbol = self.env.domaindata['c']['root_symbol']
if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
symbol = rootSymbol
stack = [] # type: List[Symbol]
else:
parser = DefinitionParser(self.arguments[0],
location=self.get_source_info(),
config=self.env.config)
try:
name = parser.parse_namespace_object()
parser.assert_end()
except DefinitionError as e:
logger.warning(e, location=self.get_source_info())
name = _make_phony_error_name()
symbol = rootSymbol.add_name(name)
stack = [symbol]
self.env.temp_data['c:parent_symbol'] = symbol
self.env.temp_data['c:namespace_stack'] = stack
self.env.ref_context['c:parent_key'] = symbol.get_lookup_key()
return []
class CNamespacePushObject(SphinxDirective):
has_content = False
required_arguments = 1
optional_arguments = 0
final_argument_whitespace = True
option_spec = {} # type: Dict
def run(self) -> List[Node]:
if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
return []
parser = DefinitionParser(self.arguments[0],
location=self.get_source_info(),
config=self.env.config)
try:
name = parser.parse_namespace_object()
parser.assert_end()
except DefinitionError as e:
logger.warning(e, location=self.get_source_info())
name = _make_phony_error_name()
oldParent = self.env.temp_data.get('c:parent_symbol', None)
if not oldParent:
oldParent = self.env.domaindata['c']['root_symbol']
symbol = oldParent.add_name(name)
stack = self.env.temp_data.get('c:namespace_stack', [])
stack.append(symbol)
self.env.temp_data['c:parent_symbol'] = symbol
self.env.temp_data['c:namespace_stack'] = stack
self.env.ref_context['c:parent_key'] = symbol.get_lookup_key()
return []
class CNamespacePopObject(SphinxDirective):
has_content = False
required_arguments = 0
optional_arguments = 0
final_argument_whitespace = True
option_spec = {} # type: Dict
def run(self) -> List[Node]:
stack = self.env.temp_data.get('c:namespace_stack', None)
if not stack or len(stack) == 0:
logger.warning("C namespace pop on empty stack. Defaulting to gobal scope.",
location=self.get_source_info())
stack = []
else:
stack.pop()
if len(stack) > 0:
symbol = stack[-1]
else:
symbol = self.env.domaindata['c']['root_symbol']
self.env.temp_data['c:parent_symbol'] = symbol
self.env.temp_data['c:namespace_stack'] = stack
self.env.ref_context['cp:parent_key'] = symbol.get_lookup_key()
return []
class CXRefRole(XRefRole): class CXRefRole(XRefRole):
def process_link(self, env: BuildEnvironment, refnode: Element, def process_link(self, env: BuildEnvironment, refnode: Element,
has_explicit_title: bool, title: str, target: str) -> Tuple[str, str]: has_explicit_title: bool, title: str, target: str) -> Tuple[str, str]:
@ -3214,7 +3345,8 @@ class CExprRole(SphinxRole):
def run(self) -> Tuple[List[Node], List[system_message]]: def run(self) -> Tuple[List[Node], List[system_message]]:
text = self.text.replace('\n', ' ') text = self.text.replace('\n', ' ')
parser = DefinitionParser(text, location=self.get_source_info()) parser = DefinitionParser(text, location=self.get_source_info(),
config=self.env.config)
# attempt to mimic XRefRole classes, except that... # attempt to mimic XRefRole classes, except that...
classes = ['xref', 'c', self.class_type] classes = ['xref', 'c', self.class_type]
try: try:
@ -3256,6 +3388,10 @@ class CDomain(Domain):
'enum': CEnumObject, 'enum': CEnumObject,
'enumerator': CEnumeratorObject, 'enumerator': CEnumeratorObject,
'type': CTypeObject, 'type': CTypeObject,
# scope control
'namespace': CNamespaceObject,
'namespace-push': CNamespacePushObject,
'namespace-pop': CNamespacePopObject,
} }
roles = { roles = {
'member': CXRefRole(), 'member': CXRefRole(),
@ -3344,7 +3480,7 @@ class CDomain(Domain):
def _resolve_xref_inner(self, env: BuildEnvironment, fromdocname: str, builder: Builder, def _resolve_xref_inner(self, env: BuildEnvironment, fromdocname: str, builder: Builder,
typ: str, target: str, node: pending_xref, typ: str, target: str, node: pending_xref,
contnode: Element) -> Tuple[Element, str]: contnode: Element) -> Tuple[Element, str]:
parser = DefinitionParser(target, location=node) parser = DefinitionParser(target, location=node, config=env.config)
try: try:
name = parser.parse_xref_object() name = parser.parse_xref_object()
except DefinitionError as e: except DefinitionError as e:
@ -3401,6 +3537,8 @@ class CDomain(Domain):
def setup(app: Sphinx) -> Dict[str, Any]: def setup(app: Sphinx) -> Dict[str, Any]:
app.add_domain(CDomain) app.add_domain(CDomain)
app.add_config_value("c_id_attributes", [], 'env')
app.add_config_value("c_paren_attributes", [], 'env')
return { return {
'version': 'builtin', 'version': 'builtin',

View File

@ -10,7 +10,7 @@
import re import re
from typing import ( from typing import (
Any, Callable, Dict, Generator, Iterator, List, Tuple, Type, TypeVar, Union Any, Callable, Dict, Generator, Iterator, List, Tuple, Type, TypeVar, Union, Optional
) )
from docutils import nodes from docutils import nodes
@ -21,7 +21,6 @@ from sphinx import addnodes
from sphinx.addnodes import desc_signature, pending_xref from sphinx.addnodes import desc_signature, pending_xref
from sphinx.application import Sphinx from sphinx.application import Sphinx
from sphinx.builders import Builder from sphinx.builders import Builder
from sphinx.config import Config
from sphinx.directives import ObjectDescription from sphinx.directives import ObjectDescription
from sphinx.domains import Domain, ObjType from sphinx.domains import Domain, ObjType
from sphinx.environment import BuildEnvironment from sphinx.environment import BuildEnvironment
@ -32,10 +31,11 @@ from sphinx.transforms import SphinxTransform
from sphinx.transforms.post_transforms import ReferencesResolver from sphinx.transforms.post_transforms import ReferencesResolver
from sphinx.util import logging from sphinx.util import logging
from sphinx.util.cfamily import ( from sphinx.util.cfamily import (
NoOldIdError, ASTBaseBase, verify_description_mode, StringifyTransform, NoOldIdError, ASTBaseBase, ASTAttribute, verify_description_mode, StringifyTransform,
BaseParser, DefinitionError, UnsupportedMultiCharacterCharLiteral, BaseParser, DefinitionError, UnsupportedMultiCharacterCharLiteral,
identifier_re, anon_identifier_re, integer_literal_re, octal_literal_re, identifier_re, anon_identifier_re, integer_literal_re, octal_literal_re,
hex_literal_re, binary_literal_re, float_literal_re, hex_literal_re, binary_literal_re, integers_literal_suffix_re,
float_literal_re, float_literal_suffix_re,
char_literal_re char_literal_re
) )
from sphinx.util.docfields import Field, GroupedField from sphinx.util.docfields import Field, GroupedField
@ -110,7 +110,8 @@ T = TypeVar('T')
simple-declaration -> simple-declaration ->
attribute-specifier-seq[opt] decl-specifier-seq[opt] attribute-specifier-seq[opt] decl-specifier-seq[opt]
init-declarator-list[opt] ; init-declarator-list[opt] ;
# Drop the semi-colon. For now: drop the attributes (TODO). # Make the semicolon optional.
# For now: drop the attributes (TODO).
# Use at most 1 init-declarator. # Use at most 1 init-declarator.
-> decl-specifier-seq init-declarator -> decl-specifier-seq init-declarator
-> decl-specifier-seq declarator initializer -> decl-specifier-seq declarator initializer
@ -296,6 +297,9 @@ T = TypeVar('T')
nested-name nested-name
""" """
udl_identifier_re = re.compile(r'''(?x)
[a-zA-Z_][a-zA-Z0-9_]*\b # note, no word boundary in the beginning
''')
_string_re = re.compile(r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'" _string_re = re.compile(r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'"
r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S) r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
_visibility_re = re.compile(r'\b(public|private|protected)\b') _visibility_re = re.compile(r'\b(public|private|protected)\b')
@ -607,8 +611,7 @@ class ASTIdentifier(ASTBase):
reftype='identifier', reftype='identifier',
reftarget=targetText, modname=None, reftarget=targetText, modname=None,
classname=None) classname=None)
key = symbol.get_lookup_key() pnode['cpp:parent_key'] = symbol.get_lookup_key()
pnode['cpp:parent_key'] = key
if self.is_anon(): if self.is_anon():
pnode += nodes.strong(text="[anonymous]") pnode += nodes.strong(text="[anonymous]")
else: else:
@ -624,6 +627,19 @@ class ASTIdentifier(ASTBase):
signode += nodes.strong(text="[anonymous]") signode += nodes.strong(text="[anonymous]")
else: else:
signode += nodes.Text(self.identifier) signode += nodes.Text(self.identifier)
elif mode == 'udl':
# the target is 'operator""id' instead of just 'id'
assert len(prefix) == 0
assert len(templateArgs) == 0
assert not self.is_anon()
targetText = 'operator""' + self.identifier
pnode = addnodes.pending_xref('', refdomain='cpp',
reftype='identifier',
reftarget=targetText, modname=None,
classname=None)
pnode['cpp:parent_key'] = symbol.get_lookup_key()
pnode += nodes.Text(self.identifier)
signode += pnode
else: else:
raise Exception('Unknown description mode: %s' % mode) raise Exception('Unknown description mode: %s' % mode)
@ -736,11 +752,17 @@ class ASTNestedName(ASTBase):
names = self.names[:-1] if mode == 'lastIsName' else self.names names = self.names[:-1] if mode == 'lastIsName' else self.names
# If lastIsName, then wrap all of the prefix in a desc_addname, # If lastIsName, then wrap all of the prefix in a desc_addname,
# else append directly to signode. # else append directly to signode.
# NOTE: Breathe relies on the prefix being in the desc_addname node, # NOTE: Breathe previously relied on the prefix being in the desc_addname node,
# so it can remove it in inner declarations. # so it can remove it in inner declarations.
dest = signode dest = signode
if mode == 'lastIsName': if mode == 'lastIsName':
dest = addnodes.desc_addname() dest = addnodes.desc_addname()
if self.rooted:
prefix += '::'
if mode == 'lastIsName' and len(names) == 0:
signode += nodes.Text('::')
else:
dest += nodes.Text('::')
for i in range(len(names)): for i in range(len(names)):
nne = names[i] nne = names[i]
template = self.templates[i] template = self.templates[i]
@ -769,89 +791,6 @@ class ASTNestedName(ASTBase):
raise Exception('Unknown description mode: %s' % mode) raise Exception('Unknown description mode: %s' % mode)
################################################################################
# Attributes
################################################################################
class ASTAttribute(ASTBase):
def describe_signature(self, signode: TextElement) -> None:
raise NotImplementedError(repr(self))
class ASTCPPAttribute(ASTAttribute):
def __init__(self, arg: str) -> None:
self.arg = arg
def _stringify(self, transform: StringifyTransform) -> str:
return "[[" + self.arg + "]]"
def describe_signature(self, signode: TextElement) -> None:
txt = str(self)
signode.append(nodes.Text(txt, txt))
class ASTGnuAttribute(ASTBase):
def __init__(self, name: str, args: Any) -> None:
self.name = name
self.args = args
def _stringify(self, transform: StringifyTransform) -> str:
res = [self.name]
if self.args:
res.append('(')
res.append(transform(self.args))
res.append(')')
return ''.join(res)
class ASTGnuAttributeList(ASTAttribute):
def __init__(self, attrs: List[ASTGnuAttribute]) -> None:
self.attrs = attrs
def _stringify(self, transform: StringifyTransform) -> str:
res = ['__attribute__((']
first = True
for attr in self.attrs:
if not first:
res.append(', ')
first = False
res.append(transform(attr))
res.append('))')
return ''.join(res)
def describe_signature(self, signode: TextElement) -> None:
txt = str(self)
signode.append(nodes.Text(txt, txt))
class ASTIdAttribute(ASTAttribute):
"""For simple attributes defined by the user."""
def __init__(self, id: str) -> None:
self.id = id
def _stringify(self, transform: StringifyTransform) -> str:
return self.id
def describe_signature(self, signode: TextElement) -> None:
signode.append(nodes.Text(self.id, self.id))
class ASTParenAttribute(ASTAttribute):
"""For paren attributes defined by the user."""
def __init__(self, id: str, arg: str) -> None:
self.id = id
self.arg = arg
def _stringify(self, transform: StringifyTransform) -> str:
return self.id + '(' + self.arg + ')'
def describe_signature(self, signode: TextElement) -> None:
txt = str(self)
signode.append(nodes.Text(txt, txt))
################################################################################ ################################################################################
# Expressions # Expressions
################################################################################ ################################################################################
@ -913,6 +852,7 @@ class ASTNumberLiteral(ASTLiteral):
return self.data return self.data
def get_id(self, version: int) -> str: def get_id(self, version: int) -> str:
# TODO: floats should be mangled by writing the hex of the binary representation
return "L%sE" % self.data return "L%sE" % self.data
def describe_signature(self, signode: TextElement, mode: str, def describe_signature(self, signode: TextElement, mode: str,
@ -957,6 +897,7 @@ class ASTCharLiteral(ASTLiteral):
return self.prefix + "'" + self.data + "'" return self.prefix + "'" + self.data + "'"
def get_id(self, version: int) -> str: def get_id(self, version: int) -> str:
# TODO: the ID should be have L E around it
return self.type + str(self.value) return self.type + str(self.value)
def describe_signature(self, signode: TextElement, mode: str, def describe_signature(self, signode: TextElement, mode: str,
@ -965,6 +906,26 @@ class ASTCharLiteral(ASTLiteral):
signode.append(nodes.Text(txt, txt)) signode.append(nodes.Text(txt, txt))
class ASTUserDefinedLiteral(ASTLiteral):
def __init__(self, literal: ASTLiteral, ident: ASTIdentifier):
self.literal = literal
self.ident = ident
def _stringify(self, transform: StringifyTransform) -> str:
return transform(self.literal) + transform(self.ident)
def get_id(self, version: int) -> str:
# mangle as if it was a function call: ident(literal)
return 'clL_Zli{}E{}E'.format(self.ident.get_id(version), self.literal.get_id(version))
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
self.literal.describe_signature(signode, mode, env, symbol)
self.ident.describe_signature(signode, "udl", env, "", "", symbol)
################################################################################
class ASTThisLiteral(ASTExpression): class ASTThisLiteral(ASTExpression):
def _stringify(self, transform: StringifyTransform) -> str: def _stringify(self, transform: StringifyTransform) -> str:
return "this" return "this"
@ -1350,7 +1311,7 @@ class ASTNoexceptExpr(ASTExpression):
self.expr = expr self.expr = expr
def _stringify(self, transform: StringifyTransform) -> str: def _stringify(self, transform: StringifyTransform) -> str:
return "noexcept(" + transform(self.expr) + ")" return 'noexcept(' + transform(self.expr) + ')'
def get_id(self, version: int) -> str: def get_id(self, version: int) -> str:
return 'nx' + self.expr.get_id(version) return 'nx' + self.expr.get_id(version)
@ -1896,15 +1857,34 @@ class ASTFunctionParameter(ASTBase):
self.arg.describe_signature(signode, mode, env, symbol=symbol) self.arg.describe_signature(signode, mode, env, symbol=symbol)
class ASTNoexceptSpec(ASTBase):
def __init__(self, expr: Optional[ASTExpression]):
self.expr = expr
def _stringify(self, transform: StringifyTransform) -> str:
if self.expr:
return 'noexcept(' + transform(self.expr) + ')'
return 'noexcept'
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
signode += addnodes.desc_annotation('noexcept', 'noexcept')
if self.expr:
signode.append(nodes.Text('('))
self.expr.describe_signature(signode, mode, env, symbol)
signode.append(nodes.Text(')'))
class ASTParametersQualifiers(ASTBase): class ASTParametersQualifiers(ASTBase):
def __init__(self, args: List[ASTFunctionParameter], def __init__(self, args: List[ASTFunctionParameter], volatile: bool, const: bool,
volatile: bool, const: bool, refQual: str, refQual: str, exceptionSpec: ASTNoexceptSpec, trailingReturn: "ASTType",
exceptionSpec: str, override: bool, final: bool, initializer: str) -> None: override: bool, final: bool, initializer: str) -> None:
self.args = args self.args = args
self.volatile = volatile self.volatile = volatile
self.const = const self.const = const
self.refQual = refQual self.refQual = refQual
self.exceptionSpec = exceptionSpec self.exceptionSpec = exceptionSpec
self.trailingReturn = trailingReturn
self.override = override self.override = override
self.final = final self.final = final
self.initializer = initializer self.initializer = initializer
@ -1958,7 +1938,10 @@ class ASTParametersQualifiers(ASTBase):
res.append(self.refQual) res.append(self.refQual)
if self.exceptionSpec: if self.exceptionSpec:
res.append(' ') res.append(' ')
res.append(str(self.exceptionSpec)) res.append(transform(self.exceptionSpec))
if self.trailingReturn:
res.append(' -> ')
res.append(transform(self.trailingReturn))
if self.final: if self.final:
res.append(' final') res.append(' final')
if self.override: if self.override:
@ -1995,7 +1978,11 @@ class ASTParametersQualifiers(ASTBase):
if self.refQual: if self.refQual:
_add_text(signode, self.refQual) _add_text(signode, self.refQual)
if self.exceptionSpec: if self.exceptionSpec:
_add_anno(signode, str(self.exceptionSpec)) signode += nodes.Text(' ')
self.exceptionSpec.describe_signature(signode, mode, env, symbol)
if self.trailingReturn:
signode += nodes.Text(' -> ')
self.trailingReturn.describe_signature(signode, mode, env, symbol)
if self.final: if self.final:
_add_anno(signode, 'final') _add_anno(signode, 'final')
if self.override: if self.override:
@ -2146,12 +2133,15 @@ class ASTDeclSpecs(ASTBase):
if self.trailingTypeSpec: if self.trailingTypeSpec:
if addSpace: if addSpace:
signode += nodes.Text(' ') signode += nodes.Text(' ')
numChildren = len(signode)
self.trailingTypeSpec.describe_signature(signode, mode, env, self.trailingTypeSpec.describe_signature(signode, mode, env,
symbol=symbol) symbol=symbol)
numChildren = len(signode) addSpace = len(signode) != numChildren
self.rightSpecs.describe_signature(signode)
if len(signode) != numChildren: if len(str(self.rightSpecs)) > 0:
signode += nodes.Text(' ') if addSpace:
signode += nodes.Text(' ')
self.rightSpecs.describe_signature(signode)
# Declarator # Declarator
@ -2202,6 +2192,10 @@ class ASTDeclarator(ASTBase):
def function_params(self) -> List[ASTFunctionParameter]: def function_params(self) -> List[ASTFunctionParameter]:
raise NotImplementedError(repr(self)) raise NotImplementedError(repr(self))
@property
def trailingReturn(self) -> "ASTType":
raise NotImplementedError(repr(self))
def require_space_after_declSpecs(self) -> bool: def require_space_after_declSpecs(self) -> bool:
raise NotImplementedError(repr(self)) raise NotImplementedError(repr(self))
@ -2245,6 +2239,10 @@ class ASTDeclaratorNameParamQual(ASTDeclarator):
def function_params(self) -> List[ASTFunctionParameter]: def function_params(self) -> List[ASTFunctionParameter]:
return self.paramQual.function_params return self.paramQual.function_params
@property
def trailingReturn(self) -> "ASTType":
return self.paramQual.trailingReturn
# only the modifiers for a function, e.g., # only the modifiers for a function, e.g.,
def get_modifiers_id(self, version: int) -> str: def get_modifiers_id(self, version: int) -> str:
# cv-qualifiers # cv-qualifiers
@ -2362,6 +2360,10 @@ class ASTDeclaratorPtr(ASTDeclarator):
def function_params(self) -> List[ASTFunctionParameter]: def function_params(self) -> List[ASTFunctionParameter]:
return self.next.function_params return self.next.function_params
@property
def trailingReturn(self) -> "ASTType":
return self.next.trailingReturn
def require_space_after_declSpecs(self) -> bool: def require_space_after_declSpecs(self) -> bool:
return self.next.require_space_after_declSpecs() return self.next.require_space_after_declSpecs()
@ -2461,6 +2463,10 @@ class ASTDeclaratorRef(ASTDeclarator):
def function_params(self) -> List[ASTFunctionParameter]: def function_params(self) -> List[ASTFunctionParameter]:
return self.next.function_params return self.next.function_params
@property
def trailingReturn(self) -> "ASTType":
return self.next.trailingReturn
def require_space_after_declSpecs(self) -> bool: def require_space_after_declSpecs(self) -> bool:
return self.next.require_space_after_declSpecs() return self.next.require_space_after_declSpecs()
@ -2517,6 +2523,10 @@ class ASTDeclaratorParamPack(ASTDeclarator):
def function_params(self) -> List[ASTFunctionParameter]: def function_params(self) -> List[ASTFunctionParameter]:
return self.next.function_params return self.next.function_params
@property
def trailingReturn(self) -> "ASTType":
return self.next.trailingReturn
def require_space_after_declSpecs(self) -> bool: def require_space_after_declSpecs(self) -> bool:
return False return False
@ -2573,6 +2583,10 @@ class ASTDeclaratorMemPtr(ASTDeclarator):
def function_params(self) -> List[ASTFunctionParameter]: def function_params(self) -> List[ASTFunctionParameter]:
return self.next.function_params return self.next.function_params
@property
def trailingReturn(self) -> "ASTType":
return self.next.trailingReturn
def require_space_after_declSpecs(self) -> bool: def require_space_after_declSpecs(self) -> bool:
return True return True
@ -2661,6 +2675,10 @@ class ASTDeclaratorParen(ASTDeclarator):
def function_params(self) -> List[ASTFunctionParameter]: def function_params(self) -> List[ASTFunctionParameter]:
return self.inner.function_params return self.inner.function_params
@property
def trailingReturn(self) -> "ASTType":
return self.inner.trailingReturn
def require_space_after_declSpecs(self) -> bool: def require_space_after_declSpecs(self) -> bool:
return True return True
@ -2789,6 +2807,10 @@ class ASTType(ASTBase):
def function_params(self) -> List[ASTFunctionParameter]: def function_params(self) -> List[ASTFunctionParameter]:
return self.decl.function_params return self.decl.function_params
@property
def trailingReturn(self) -> "ASTType":
return self.decl.trailingReturn
def get_id(self, version: int, objectType: str = None, def get_id(self, version: int, objectType: str = None,
symbol: "Symbol" = None) -> str: symbol: "Symbol" = None) -> str:
if version == 1: if version == 1:
@ -2825,7 +2847,10 @@ class ASTType(ASTBase):
templ = symbol.declaration.templatePrefix templ = symbol.declaration.templatePrefix
if templ is not None: if templ is not None:
typeId = self.decl.get_ptr_suffix_id(version) typeId = self.decl.get_ptr_suffix_id(version)
returnTypeId = self.declSpecs.get_id(version) if self.trailingReturn:
returnTypeId = self.trailingReturn.get_id(version)
else:
returnTypeId = self.declSpecs.get_id(version)
res.append(typeId) res.append(typeId)
res.append(returnTypeId) res.append(returnTypeId)
res.append(self.decl.get_param_id(version)) res.append(self.decl.get_param_id(version))
@ -3546,12 +3571,14 @@ class ASTTemplateDeclarationPrefix(ASTBase):
class ASTDeclaration(ASTBase): class ASTDeclaration(ASTBase):
def __init__(self, objectType: str, directiveType: str, visibility: str, def __init__(self, objectType: str, directiveType: str, visibility: str,
templatePrefix: ASTTemplateDeclarationPrefix, declaration: Any) -> None: templatePrefix: ASTTemplateDeclarationPrefix, declaration: Any,
semicolon: bool = False) -> None:
self.objectType = objectType self.objectType = objectType
self.directiveType = directiveType self.directiveType = directiveType
self.visibility = visibility self.visibility = visibility
self.templatePrefix = templatePrefix self.templatePrefix = templatePrefix
self.declaration = declaration self.declaration = declaration
self.semicolon = semicolon
self.symbol = None # type: Symbol self.symbol = None # type: Symbol
# set by CPPObject._add_enumerator_to_parent # set by CPPObject._add_enumerator_to_parent
@ -3564,7 +3591,7 @@ class ASTDeclaration(ASTBase):
templatePrefixClone = None templatePrefixClone = None
return ASTDeclaration(self.objectType, self.directiveType, return ASTDeclaration(self.objectType, self.directiveType,
self.visibility, templatePrefixClone, self.visibility, templatePrefixClone,
self.declaration.clone()) self.declaration.clone(), self.semicolon)
@property @property
def name(self) -> ASTNestedName: def name(self) -> ASTNestedName:
@ -3606,6 +3633,8 @@ class ASTDeclaration(ASTBase):
if self.templatePrefix: if self.templatePrefix:
res.append(transform(self.templatePrefix)) res.append(transform(self.templatePrefix))
res.append(transform(self.declaration)) res.append(transform(self.declaration))
if self.semicolon:
res.append(';')
return ''.join(res) return ''.join(res)
def describe_signature(self, signode: desc_signature, mode: str, def describe_signature(self, signode: desc_signature, mode: str,
@ -3659,6 +3688,8 @@ class ASTDeclaration(ASTBase):
else: else:
assert False assert False
self.declaration.describe_signature(mainDeclNode, mode, env, self.symbol) self.declaration.describe_signature(mainDeclNode, mode, env, self.symbol)
if self.semicolon:
mainDeclNode += nodes.Text(';')
class ASTNamespace(ASTBase): class ASTNamespace(ASTBase):
@ -3697,8 +3728,8 @@ class LookupKey:
class Symbol: class Symbol:
debug_indent = 0 debug_indent = 0
debug_indent_string = " " debug_indent_string = " "
debug_lookup = False debug_lookup = False # overridden by the corresponding config value
debug_show_tree = False debug_show_tree = False # overridden by the corresponding config value
@staticmethod @staticmethod
def debug_print(*args: Any) -> None: def debug_print(*args: Any) -> None:
@ -4667,16 +4698,18 @@ class DefinitionParser(BaseParser):
_prefix_keys = ('class', 'struct', 'enum', 'union', 'typename') _prefix_keys = ('class', 'struct', 'enum', 'union', 'typename')
def __init__(self, definition: str, *,
location: Union[nodes.Node, Tuple[str, int]],
config: "Config") -> None:
super().__init__(definition, location=location)
self.config = config
@property @property
def language(self) -> str: def language(self) -> str:
return 'C++' return 'C++'
@property
def id_attributes(self):
return self.config.cpp_id_attributes
@property
def paren_attributes(self):
return self.config.cpp_paren_attributes
def _parse_string(self) -> str: def _parse_string(self) -> str:
if self.current_char != '"': if self.current_char != '"':
return None return None
@ -4696,85 +4729,6 @@ class DefinitionParser(BaseParser):
self.pos += 1 self.pos += 1
return self.definition[startPos:self.pos] return self.definition[startPos:self.pos]
def _parse_balanced_token_seq(self, end: List[str]) -> str:
# TODO: add handling of string literals and similar
brackets = {'(': ')', '[': ']', '{': '}'}
startPos = self.pos
symbols = [] # type: List[str]
while not self.eof:
if len(symbols) == 0 and self.current_char in end:
break
if self.current_char in brackets.keys():
symbols.append(brackets[self.current_char])
elif len(symbols) > 0 and self.current_char == symbols[-1]:
symbols.pop()
elif self.current_char in ")]}":
self.fail("Unexpected '%s' in balanced-token-seq." % self.current_char)
self.pos += 1
if self.eof:
self.fail("Could not find end of balanced-token-seq starting at %d."
% startPos)
return self.definition[startPos:self.pos]
def _parse_attribute(self) -> ASTAttribute:
self.skip_ws()
# try C++11 style
startPos = self.pos
if self.skip_string_and_ws('['):
if not self.skip_string('['):
self.pos = startPos
else:
# TODO: actually implement the correct grammar
arg = self._parse_balanced_token_seq(end=[']'])
if not self.skip_string_and_ws(']'):
self.fail("Expected ']' in end of attribute.")
if not self.skip_string_and_ws(']'):
self.fail("Expected ']' in end of attribute after [[...]")
return ASTCPPAttribute(arg)
# try GNU style
if self.skip_word_and_ws('__attribute__'):
if not self.skip_string_and_ws('('):
self.fail("Expected '(' after '__attribute__'.")
if not self.skip_string_and_ws('('):
self.fail("Expected '(' after '__attribute__('.")
attrs = []
while 1:
if self.match(identifier_re):
name = self.matched_text
self.skip_ws()
if self.skip_string_and_ws('('):
self.fail('Parameterized GNU style attribute not yet supported.')
attrs.append(ASTGnuAttribute(name, None))
# TODO: parse arguments for the attribute
if self.skip_string_and_ws(','):
continue
elif self.skip_string_and_ws(')'):
break
else:
self.fail("Expected identifier, ')', or ',' in __attribute__.")
if not self.skip_string_and_ws(')'):
self.fail("Expected ')' after '__attribute__((...)'")
return ASTGnuAttributeList(attrs)
# try the simple id attributes defined by the user
for id in self.config.cpp_id_attributes:
if self.skip_word_and_ws(id):
return ASTIdAttribute(id)
# try the paren attributes defined by the user
for id in self.config.cpp_paren_attributes:
if not self.skip_string_and_ws(id):
continue
if not self.skip_string('('):
self.fail("Expected '(' after user-defined paren-attribute.")
arg = self._parse_balanced_token_seq(end=[')'])
if not self.skip_string(')'):
self.fail("Expected ')' to end user-defined paren-attribute.")
return ASTParenAttribute(id, arg)
return None
def _parse_literal(self) -> ASTLiteral: def _parse_literal(self) -> ASTLiteral:
# -> integer-literal # -> integer-literal
# | character-literal # | character-literal
@ -4783,6 +4737,15 @@ class DefinitionParser(BaseParser):
# | boolean-literal -> "false" | "true" # | boolean-literal -> "false" | "true"
# | pointer-literal -> "nullptr" # | pointer-literal -> "nullptr"
# | user-defined-literal # | user-defined-literal
def _udl(literal: ASTLiteral) -> ASTLiteral:
if not self.match(udl_identifier_re):
return literal
# hmm, should we care if it's a keyword?
# it looks like GCC does not disallow keywords
ident = ASTIdentifier(self.matched_text)
return ASTUserDefinedLiteral(literal, ident)
self.skip_ws() self.skip_ws()
if self.skip_word('nullptr'): if self.skip_word('nullptr'):
return ASTPointerLiteral() return ASTPointerLiteral()
@ -4790,31 +4753,40 @@ class DefinitionParser(BaseParser):
return ASTBooleanLiteral(True) return ASTBooleanLiteral(True)
if self.skip_word('false'): if self.skip_word('false'):
return ASTBooleanLiteral(False) return ASTBooleanLiteral(False)
for regex in [float_literal_re, binary_literal_re, hex_literal_re, pos = self.pos
if self.match(float_literal_re):
hasSuffix = self.match(float_literal_suffix_re)
floatLit = ASTNumberLiteral(self.definition[pos:self.pos])
if hasSuffix:
return floatLit
else:
return _udl(floatLit)
for regex in [binary_literal_re, hex_literal_re,
integer_literal_re, octal_literal_re]: integer_literal_re, octal_literal_re]:
pos = self.pos
if self.match(regex): if self.match(regex):
while self.current_char in 'uUlLfF': hasSuffix = self.match(integers_literal_suffix_re)
self.pos += 1 intLit = ASTNumberLiteral(self.definition[pos:self.pos])
return ASTNumberLiteral(self.definition[pos:self.pos]) if hasSuffix:
return intLit
else:
return _udl(intLit)
string = self._parse_string() string = self._parse_string()
if string is not None: if string is not None:
return ASTStringLiteral(string) return _udl(ASTStringLiteral(string))
# character-literal # character-literal
if self.match(char_literal_re): if self.match(char_literal_re):
prefix = self.last_match.group(1) # may be None when no prefix prefix = self.last_match.group(1) # may be None when no prefix
data = self.last_match.group(2) data = self.last_match.group(2)
try: try:
return ASTCharLiteral(prefix, data) charLit = ASTCharLiteral(prefix, data)
except UnicodeDecodeError as e: except UnicodeDecodeError as e:
self.fail("Can not handle character literal. Internal error was: %s" % e) self.fail("Can not handle character literal. Internal error was: %s" % e)
except UnsupportedMultiCharacterCharLiteral: except UnsupportedMultiCharacterCharLiteral:
self.fail("Can not handle character literal" self.fail("Can not handle character literal"
" resulting in multiple decoded characters.") " resulting in multiple decoded characters.")
return _udl(charLit)
# TODO: user-defined lit
return None return None
def _parse_fold_or_paren_expression(self) -> ASTExpression: def _parse_fold_or_paren_expression(self) -> ASTExpression:
@ -5651,15 +5623,22 @@ class DefinitionParser(BaseParser):
refQual = '&' refQual = '&'
exceptionSpec = None exceptionSpec = None
override = None
final = None
initializer = None
self.skip_ws() self.skip_ws()
if self.skip_string('noexcept'): if self.skip_string('noexcept'):
exceptionSpec = 'noexcept' if self.skip_string_and_ws('('):
self.skip_ws() expr = self._parse_constant_expression(False)
if self.skip_string('('): self.skip_ws()
self.fail('Parameterised "noexcept" not yet implemented.') if not self.skip_string(')'):
self.fail("Expecting ')' to end 'noexcept'.")
exceptionSpec = ASTNoexceptSpec(expr)
else:
exceptionSpec = ASTNoexceptSpec(None)
self.skip_ws()
if self.skip_string('->'):
trailingReturn = self._parse_type(named=False)
else:
trailingReturn = None
self.skip_ws() self.skip_ws()
override = self.skip_word_and_ws('override') override = self.skip_word_and_ws('override')
@ -5669,6 +5648,7 @@ class DefinitionParser(BaseParser):
'override') # they can be permuted 'override') # they can be permuted
self.skip_ws() self.skip_ws()
initializer = None
if self.skip_string('='): if self.skip_string('='):
self.skip_ws() self.skip_ws()
valid = ('0', 'delete', 'default') valid = ('0', 'delete', 'default')
@ -5682,8 +5662,8 @@ class DefinitionParser(BaseParser):
% '" or "'.join(valid)) % '" or "'.join(valid))
return ASTParametersQualifiers( return ASTParametersQualifiers(
args, volatile, const, refQual, exceptionSpec, override, final, args, volatile, const, refQual, exceptionSpec, trailingReturn,
initializer) override, final, initializer)
def _parse_decl_specs_simple(self, outer: str, typed: bool) -> ASTDeclSpecsSimple: def _parse_decl_specs_simple(self, outer: str, typed: bool) -> ASTDeclSpecsSimple:
"""Just parse the simple ones.""" """Just parse the simple ones."""
@ -6033,7 +6013,7 @@ class DefinitionParser(BaseParser):
declSpecs = self._parse_decl_specs(outer=outer, typed=False) declSpecs = self._parse_decl_specs(outer=outer, typed=False)
decl = self._parse_declarator(named=True, paramMode=outer, decl = self._parse_declarator(named=True, paramMode=outer,
typed=False) typed=False)
self.assert_end() self.assert_end(allowSemicolon=True)
except DefinitionError as exUntyped: except DefinitionError as exUntyped:
if outer == 'type': if outer == 'type':
desc = "If just a name" desc = "If just a name"
@ -6444,8 +6424,10 @@ class DefinitionParser(BaseParser):
templatePrefix, templatePrefix,
fullSpecShorthand=False, fullSpecShorthand=False,
isMember=objectType == 'member') isMember=objectType == 'member')
self.skip_ws()
semicolon = self.skip_string(';')
return ASTDeclaration(objectType, directiveType, visibility, return ASTDeclaration(objectType, directiveType, visibility,
templatePrefix, declaration) templatePrefix, declaration, semicolon)
def parse_namespace_object(self) -> ASTNamespace: def parse_namespace_object(self) -> ASTNamespace:
templatePrefix = self._parse_template_declaration_prefix(objectType="namespace") templatePrefix = self._parse_template_declaration_prefix(objectType="namespace")
@ -7200,8 +7182,7 @@ class CPPDomain(Domain):
# add parens again for those that could be functions # add parens again for those that could be functions
if typ == 'any' or typ == 'func': if typ == 'any' or typ == 'func':
target += '()' target += '()'
parser = DefinitionParser(target, location=node, parser = DefinitionParser(target, location=node, config=env.config)
config=env.config)
try: try:
ast, isShorthand = parser.parse_xref_object() ast, isShorthand = parser.parse_xref_object()
except DefinitionError as e: except DefinitionError as e:
@ -7408,9 +7389,18 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_config_value("cpp_paren_attributes", [], 'env') app.add_config_value("cpp_paren_attributes", [], 'env')
app.add_post_transform(AliasTransform) app.add_post_transform(AliasTransform)
# debug stuff
app.add_config_value("cpp_debug_lookup", False, '')
app.add_config_value("cpp_debug_show_tree", False, '')
def setDebugFlags(app):
Symbol.debug_lookup = app.config.cpp_debug_lookup
Symbol.debug_show_tree = app.config.cpp_debug_show_tree
app.connect("builder-inited", setDebugFlags)
return { return {
'version': 'builtin', 'version': 'builtin',
'env_version': 2, 'env_version': 3,
'parallel_read_safe': True, 'parallel_read_safe': True,
'parallel_write_safe': True, 'parallel_write_safe': True,
} }

View File

@ -142,7 +142,7 @@ class MathDomain(Domain):
def add_equation(self, env: BuildEnvironment, docname: str, labelid: str) -> int: def add_equation(self, env: BuildEnvironment, docname: str, labelid: str) -> int:
warnings.warn('MathDomain.add_equation() is deprecated.', warnings.warn('MathDomain.add_equation() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
if labelid in self.equations: if labelid in self.equations:
path = env.doc2path(self.equations[labelid][0]) path = env.doc2path(self.equations[labelid][0])
msg = __('duplicate label of equation %s, other instance in %s') % (labelid, path) msg = __('duplicate label of equation %s, other instance in %s') % (labelid, path)
@ -154,7 +154,7 @@ class MathDomain(Domain):
def get_next_equation_number(self, docname: str) -> int: def get_next_equation_number(self, docname: str) -> int:
warnings.warn('MathDomain.get_next_equation_number() is deprecated.', warnings.warn('MathDomain.get_next_equation_number() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
targets = [eq for eq in self.equations.values() if eq[0] == docname] targets = [eq for eq in self.equations.values() if eq[0] == docname]
return len(targets) + 1 return len(targets) + 1

View File

@ -77,17 +77,19 @@ ModuleEntry = NamedTuple('ModuleEntry', [('docname', str),
('deprecated', bool)]) ('deprecated', bool)])
def type_to_xref(text: str) -> addnodes.pending_xref:
"""Convert a type string to a cross reference node."""
if text == 'None':
reftype = 'obj'
else:
reftype = 'class'
return pending_xref('', nodes.Text(text),
refdomain='py', reftype=reftype, reftarget=text)
def _parse_annotation(annotation: str) -> List[Node]: def _parse_annotation(annotation: str) -> List[Node]:
"""Parse type annotation.""" """Parse type annotation."""
def make_xref(text: str) -> addnodes.pending_xref:
if text == 'None':
reftype = 'obj'
else:
reftype = 'class'
return pending_xref('', nodes.Text(text),
refdomain='py', reftype=reftype, reftarget=text)
def unparse(node: ast.AST) -> List[Node]: def unparse(node: ast.AST) -> List[Node]:
if isinstance(node, ast.Attribute): if isinstance(node, ast.Attribute):
return [nodes.Text("%s.%s" % (unparse(node.value)[0], node.attr))] return [nodes.Text("%s.%s" % (unparse(node.value)[0], node.attr))]
@ -114,11 +116,16 @@ def _parse_annotation(annotation: str) -> List[Node]:
result.append(addnodes.desc_sig_punctuation('', ']')) result.append(addnodes.desc_sig_punctuation('', ']'))
return result return result
elif isinstance(node, ast.Tuple): elif isinstance(node, ast.Tuple):
result = [] if node.elts:
for elem in node.elts: result = []
result.extend(unparse(elem)) for elem in node.elts:
result.append(addnodes.desc_sig_punctuation('', ', ')) result.extend(unparse(elem))
result.pop() result.append(addnodes.desc_sig_punctuation('', ', '))
result.pop()
else:
result = [addnodes.desc_sig_punctuation('', '('),
addnodes.desc_sig_punctuation('', ')')]
return result return result
else: else:
raise SyntaxError # unsupported syntax raise SyntaxError # unsupported syntax
@ -128,10 +135,10 @@ def _parse_annotation(annotation: str) -> List[Node]:
result = unparse(tree) result = unparse(tree)
for i, node in enumerate(result): for i, node in enumerate(result):
if isinstance(node, nodes.Text): if isinstance(node, nodes.Text):
result[i] = make_xref(str(node)) result[i] = type_to_xref(str(node))
return result return result
except SyntaxError: except SyntaxError:
return [make_xref(annotation)] return [type_to_xref(annotation)]
def _parse_arglist(arglist: str) -> addnodes.desc_parameterlist: def _parse_arglist(arglist: str) -> addnodes.desc_parameterlist:
@ -525,10 +532,11 @@ class PyModulelevel(PyObject):
if cls.__name__ != 'DirectiveAdapter': if cls.__name__ != 'DirectiveAdapter':
warnings.warn('PyModulelevel is deprecated. ' warnings.warn('PyModulelevel is deprecated. '
'Please check the implementation of %s' % cls, 'Please check the implementation of %s' % cls,
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
break break
else: else:
warnings.warn('PyModulelevel is deprecated', RemovedInSphinx40Warning) warnings.warn('PyModulelevel is deprecated',
RemovedInSphinx40Warning, stacklevel=2)
return super().run() return super().run()
@ -615,7 +623,7 @@ class PyVariable(PyObject):
typ = self.options.get('type') typ = self.options.get('type')
if typ: if typ:
signode += addnodes.desc_annotation(typ, ': ' + typ) signode += addnodes.desc_annotation(typ, '', nodes.Text(': '), type_to_xref(typ))
value = self.options.get('value') value = self.options.get('value')
if value: if value:
@ -636,10 +644,18 @@ class PyClasslike(PyObject):
Description of a class-like object (classes, interfaces, exceptions). Description of a class-like object (classes, interfaces, exceptions).
""" """
option_spec = PyObject.option_spec.copy()
option_spec.update({
'final': directives.flag,
})
allow_nesting = True allow_nesting = True
def get_signature_prefix(self, sig: str) -> str: def get_signature_prefix(self, sig: str) -> str:
return self.objtype + ' ' if 'final' in self.options:
return 'final %s ' % self.objtype
else:
return '%s ' % self.objtype
def get_index_text(self, modname: str, name_cls: Tuple[str, str]) -> str: def get_index_text(self, modname: str, name_cls: Tuple[str, str]) -> str:
if self.objtype == 'class': if self.objtype == 'class':
@ -662,10 +678,11 @@ class PyClassmember(PyObject):
if cls.__name__ != 'DirectiveAdapter': if cls.__name__ != 'DirectiveAdapter':
warnings.warn('PyClassmember is deprecated. ' warnings.warn('PyClassmember is deprecated. '
'Please check the implementation of %s' % cls, 'Please check the implementation of %s' % cls,
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
break break
else: else:
warnings.warn('PyClassmember is deprecated', RemovedInSphinx40Warning) warnings.warn('PyClassmember is deprecated',
RemovedInSphinx40Warning, stacklevel=2)
return super().run() return super().run()
@ -744,6 +761,7 @@ class PyMethod(PyObject):
'abstractmethod': directives.flag, 'abstractmethod': directives.flag,
'async': directives.flag, 'async': directives.flag,
'classmethod': directives.flag, 'classmethod': directives.flag,
'final': directives.flag,
'property': directives.flag, 'property': directives.flag,
'staticmethod': directives.flag, 'staticmethod': directives.flag,
}) })
@ -756,6 +774,8 @@ class PyMethod(PyObject):
def get_signature_prefix(self, sig: str) -> str: def get_signature_prefix(self, sig: str) -> str:
prefix = [] prefix = []
if 'final' in self.options:
prefix.append('final')
if 'abstractmethod' in self.options: if 'abstractmethod' in self.options:
prefix.append('abstract') prefix.append('abstract')
if 'async' in self.options: if 'async' in self.options:
@ -848,7 +868,7 @@ class PyAttribute(PyObject):
typ = self.options.get('type') typ = self.options.get('type')
if typ: if typ:
signode += addnodes.desc_annotation(typ, ': ' + typ) signode += addnodes.desc_annotation(typ, '', nodes.Text(': '), type_to_xref(typ))
value = self.options.get('value') value = self.options.get('value')
if value: if value:
@ -880,10 +900,11 @@ class PyDecoratorMixin:
if cls.__name__ != 'DirectiveAdapter': if cls.__name__ != 'DirectiveAdapter':
warnings.warn('PyDecoratorMixin is deprecated. ' warnings.warn('PyDecoratorMixin is deprecated. '
'Please check the implementation of %s' % cls, 'Please check the implementation of %s' % cls,
RemovedInSphinx50Warning) RemovedInSphinx50Warning, stacklevel=2)
break break
else: else:
warnings.warn('PyDecoratorMixin is deprecated', RemovedInSphinx50Warning) warnings.warn('PyDecoratorMixin is deprecated',
RemovedInSphinx50Warning, stacklevel=2)
ret = super().handle_signature(sig, signode) # type: ignore ret = super().handle_signature(sig, signode) # type: ignore
signode.insert(0, addnodes.desc_addname('@', '@')) signode.insert(0, addnodes.desc_addname('@', '@'))

View File

@ -292,7 +292,7 @@ def make_glossary_term(env: "BuildEnvironment", textnodes: Iterable[Node], index
document.note_explicit_target(term) document.note_explicit_target(term)
else: else:
warnings.warn('make_glossary_term() expects document is passed as an argument.', warnings.warn('make_glossary_term() expects document is passed as an argument.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
gloss_entries = env.temp_data.setdefault('gloss_entries', set()) gloss_entries = env.temp_data.setdefault('gloss_entries', set())
node_id = nodes.make_id('term-' + termtext) node_id = nodes.make_id('term-' + termtext)
if node_id == 'term': if node_id == 'term':
@ -660,7 +660,7 @@ class StandardDomain(Domain):
def add_object(self, objtype: str, name: str, docname: str, labelid: str) -> None: def add_object(self, objtype: str, name: str, docname: str, labelid: str) -> None:
warnings.warn('StandardDomain.add_object() is deprecated.', warnings.warn('StandardDomain.add_object() is deprecated.',
RemovedInSphinx50Warning) RemovedInSphinx50Warning, stacklevel=2)
self.objects[objtype, name] = (docname, labelid) self.objects[objtype, name] = (docname, labelid)
@property @property
@ -786,9 +786,11 @@ class StandardDomain(Domain):
resolver = self._resolve_option_xref resolver = self._resolve_option_xref
elif typ == 'citation': elif typ == 'citation':
warnings.warn('pending_xref(domain=std, type=citation) is deprecated: %r' % node, warnings.warn('pending_xref(domain=std, type=citation) is deprecated: %r' % node,
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
domain = env.get_domain('citation') domain = env.get_domain('citation')
return domain.resolve_xref(env, fromdocname, builder, typ, target, node, contnode) return domain.resolve_xref(env, fromdocname, builder, typ, target, node, contnode)
elif typ == 'term':
resolver = self._resolve_term_xref
else: else:
resolver = self._resolve_obj_xref resolver = self._resolve_obj_xref
@ -923,6 +925,28 @@ class StandardDomain(Domain):
return make_refnode(builder, fromdocname, docname, return make_refnode(builder, fromdocname, docname,
labelid, contnode) labelid, contnode)
def _resolve_term_xref(self, env: "BuildEnvironment", fromdocname: str,
builder: "Builder", typ: str, target: str,
node: pending_xref, contnode: Element) -> Element:
result = self._resolve_obj_xref(env, fromdocname, builder, typ,
target, node, contnode)
if result:
return result
else:
for objtype, term in self.objects:
if objtype == 'term' and term.lower() == target.lower():
docname, labelid = self.objects[objtype, term]
logger.warning(__('term %s not found in case sensitive match.'
'made a reference to %s instead.'),
target, term, location=node, type='ref', subtype='term')
break
else:
docname, labelid = '', ''
if not docname:
return None
return make_refnode(builder, fromdocname, docname,
labelid, contnode)
def _resolve_obj_xref(self, env: "BuildEnvironment", fromdocname: str, def _resolve_obj_xref(self, env: "BuildEnvironment", fromdocname: str,
builder: "Builder", typ: str, target: str, builder: "Builder", typ: str, target: str,
node: pending_xref, contnode: Element) -> Element: node: pending_xref, contnode: Element) -> Element:
@ -1058,15 +1082,15 @@ class StandardDomain(Domain):
def note_citations(self, env: "BuildEnvironment", docname: str, document: nodes.document) -> None: # NOQA def note_citations(self, env: "BuildEnvironment", docname: str, document: nodes.document) -> None: # NOQA
warnings.warn('StandardDomain.note_citations() is deprecated.', warnings.warn('StandardDomain.note_citations() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
def note_citation_refs(self, env: "BuildEnvironment", docname: str, document: nodes.document) -> None: # NOQA def note_citation_refs(self, env: "BuildEnvironment", docname: str, document: nodes.document) -> None: # NOQA
warnings.warn('StandardDomain.note_citation_refs() is deprecated.', warnings.warn('StandardDomain.note_citation_refs() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
def note_labels(self, env: "BuildEnvironment", docname: str, document: nodes.document) -> None: # NOQA def note_labels(self, env: "BuildEnvironment", docname: str, document: nodes.document) -> None: # NOQA
warnings.warn('StandardDomain.note_labels() is deprecated.', warnings.warn('StandardDomain.note_labels() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
def setup(app: "Sphinx") -> Dict[str, Any]: def setup(app: "Sphinx") -> Dict[str, Any]:

View File

@ -331,10 +331,10 @@ class BuildEnvironment:
""" """
if suffix: if suffix:
warnings.warn('The suffix argument for doc2path() is deprecated.', warnings.warn('The suffix argument for doc2path() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
if base not in (True, False, None): if base not in (True, False, None):
warnings.warn('The string style base argument for doc2path() is deprecated.', warnings.warn('The string style base argument for doc2path() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
pathname = self.project.doc2path(docname, base is True) pathname = self.project.doc2path(docname, base is True)
if suffix: if suffix:

View File

@ -29,7 +29,7 @@ class IndexEntriesCollector(EnvironmentCollector):
def __init__(self) -> None: def __init__(self) -> None:
warnings.warn('IndexEntriesCollector is deprecated.', warnings.warn('IndexEntriesCollector is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
def clear_doc(self, app: Sphinx, env: BuildEnvironment, docname: str) -> None: def clear_doc(self, app: Sphinx, env: BuildEnvironment, docname: str) -> None:
env.indexentries.pop(docname, None) env.indexentries.pop(docname, None)

View File

@ -116,7 +116,8 @@ class PycodeError(Exception):
class NoUri(Exception): class NoUri(Exception):
"""Raised by builder.get_relative_uri() if there is no URI available.""" """Raised by builder.get_relative_uri() or from missing-reference handlers
if there is no URI available."""
pass pass

View File

@ -13,15 +13,16 @@
import warnings import warnings
from collections import defaultdict from collections import defaultdict
from operator import attrgetter from operator import attrgetter
from typing import Any, Callable, Dict, List, NamedTuple from typing import Any, Callable, Dict, List, NamedTuple, Tuple
from sphinx.deprecation import RemovedInSphinx40Warning from sphinx.deprecation import RemovedInSphinx40Warning
from sphinx.errors import ExtensionError from sphinx.errors import ExtensionError, SphinxError
from sphinx.locale import __ from sphinx.locale import __
from sphinx.util import logging from sphinx.util import logging
if False: if False:
# For type annotation # For type annotation
from typing import Type # for python3.5.1
from sphinx.application import Sphinx from sphinx.application import Sphinx
@ -88,7 +89,8 @@ class EventManager:
if listener.id == listener_id: if listener.id == listener_id:
listeners.remove(listener) listeners.remove(listener)
def emit(self, name: str, *args: Any) -> List: def emit(self, name: str, *args: Any,
allowed_exceptions: Tuple["Type[Exception]", ...] = ()) -> List:
"""Emit a Sphinx event.""" """Emit a Sphinx event."""
try: try:
logger.debug('[app] emitting event: %r%s', name, repr(args)[:100]) logger.debug('[app] emitting event: %r%s', name, repr(args)[:100])
@ -100,19 +102,29 @@ class EventManager:
results = [] results = []
listeners = sorted(self.listeners[name], key=attrgetter("priority")) listeners = sorted(self.listeners[name], key=attrgetter("priority"))
for listener in listeners: for listener in listeners:
if self.app is None: try:
# for compatibility; RemovedInSphinx40Warning if self.app is None:
results.append(listener.handler(*args)) # for compatibility; RemovedInSphinx40Warning
else: results.append(listener.handler(*args))
results.append(listener.handler(self.app, *args)) else:
results.append(listener.handler(self.app, *args))
except allowed_exceptions:
# pass through the errors specified as *allowed_exceptions*
raise
except SphinxError:
raise
except Exception as exc:
raise ExtensionError(__("Handler %r for event %r threw an exception") %
(listener.handler, name)) from exc
return results return results
def emit_firstresult(self, name: str, *args: Any) -> Any: def emit_firstresult(self, name: str, *args: Any,
allowed_exceptions: Tuple["Type[Exception]", ...] = ()) -> Any:
"""Emit a Sphinx event and returns first result. """Emit a Sphinx event and returns first result.
This returns the result of the first handler that doesn't return ``None``. This returns the result of the first handler that doesn't return ``None``.
""" """
for result in self.emit(name, *args): for result in self.emit(name, *args, allowed_exceptions=allowed_exceptions):
if result is not None: if result is not None:
return result return result
return None return None

View File

@ -54,7 +54,7 @@ template_dir = path.join(package_dir, 'templates', 'apidoc')
def makename(package: str, module: str) -> str: def makename(package: str, module: str) -> str:
"""Join package and module with a dot.""" """Join package and module with a dot."""
warnings.warn('makename() is deprecated.', warnings.warn('makename() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
# Both package and module can be None/empty. # Both package and module can be None/empty.
if package: if package:
name = package name = package
@ -112,7 +112,7 @@ def write_file(name: str, text: str, opts: Any) -> None:
def format_heading(level: int, text: str, escape: bool = True) -> str: def format_heading(level: int, text: str, escape: bool = True) -> str:
"""Create a heading of <level> [1, 2 or 3 supported].""" """Create a heading of <level> [1, 2 or 3 supported]."""
warnings.warn('format_warning() is deprecated.', warnings.warn('format_warning() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
if escape: if escape:
text = rst.escape(text) text = rst.escape(text)
underlining = ['=', '-', '~', ][level - 1] * len(text) underlining = ['=', '-', '~', ][level - 1] * len(text)
@ -122,7 +122,7 @@ def format_heading(level: int, text: str, escape: bool = True) -> str:
def format_directive(module: str, package: str = None) -> str: def format_directive(module: str, package: str = None) -> str:
"""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, stacklevel=2)
directive = '.. automodule:: %s\n' % module_join(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
@ -209,7 +209,7 @@ def create_modules_toc_file(modules: List[str], opts: Any, name: str = 'modules'
def shall_skip(module: str, opts: Any, excludes: List[str] = []) -> bool: def shall_skip(module: str, opts: Any, excludes: List[str] = []) -> bool:
"""Check if we want to skip this module.""" """Check if we want to skip this module."""
warnings.warn('shall_skip() is deprecated.', warnings.warn('shall_skip() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
# skip if the file doesn't exist and not using implicit namespaces # skip if the file doesn't exist and not using implicit namespaces
if not opts.implicit_namespaces and not path.exists(module): if not opts.implicit_namespaces and not path.exists(module):
return True return True

View File

@ -16,13 +16,12 @@ import warnings
from inspect import Parameter from inspect import Parameter
from types import ModuleType from types import ModuleType
from typing import Any, Callable, Dict, Iterator, List, Sequence, Set, Tuple, Type, Union from typing import Any, Callable, Dict, Iterator, List, Sequence, Set, Tuple, Type, Union
from unittest.mock import patch
from docutils.statemachine import StringList from docutils.statemachine import StringList
import sphinx import sphinx
from sphinx.application import Sphinx from sphinx.application import Sphinx
from sphinx.config import ENUM from sphinx.config import Config, ENUM
from sphinx.deprecation import RemovedInSphinx40Warning, RemovedInSphinx50Warning from sphinx.deprecation import RemovedInSphinx40Warning, RemovedInSphinx50Warning
from sphinx.environment import BuildEnvironment from sphinx.environment import BuildEnvironment
from sphinx.ext.autodoc.importer import import_object, get_module_members, get_object_members from sphinx.ext.autodoc.importer import import_object, get_module_members, get_object_members
@ -31,7 +30,7 @@ from sphinx.locale import _, __
from sphinx.pycode import ModuleAnalyzer, PycodeError from sphinx.pycode import ModuleAnalyzer, PycodeError
from sphinx.util import inspect from sphinx.util import inspect
from sphinx.util import logging from sphinx.util import logging
from sphinx.util import rpartition from sphinx.util import split_full_qualified_name
from sphinx.util.docstrings import extract_metadata, prepare_docstring from sphinx.util.docstrings import extract_metadata, prepare_docstring
from sphinx.util.inspect import getdoc, object_description, safe_getattr, stringify_signature from sphinx.util.inspect import getdoc, object_description, safe_getattr, stringify_signature
from sphinx.util.typing import stringify as stringify_typehint from sphinx.util.typing import stringify as stringify_typehint
@ -66,6 +65,7 @@ def identity(x: Any) -> Any:
ALL = object() ALL = object()
UNINITIALIZED_ATTR = object()
INSTANCEATTR = object() INSTANCEATTR = object()
SLOTSATTR = object() SLOTSATTR = object()
@ -311,7 +311,8 @@ class Documenter:
modname = None modname = None
parents = [] parents = []
self.modname, self.objpath = self.resolve_name(modname, parents, path, base) with mock(self.env.config.autodoc_mock_imports):
self.modname, self.objpath = self.resolve_name(modname, parents, path, base)
if not self.modname: if not self.modname:
return False return False
@ -395,9 +396,9 @@ class Documenter:
except TypeError: except TypeError:
# retry without arguments for old documenters # retry without arguments for old documenters
args = self.format_args() args = self.format_args()
except Exception as err: except Exception:
logger.warning(__('error while formatting arguments for %s: %s') % logger.warning(__('error while formatting arguments for %s:') %
(self.fullname, err), type='autodoc') self.fullname, type='autodoc', exc_info=True)
args = None args = None
retann = self.retann retann = self.retann
@ -419,8 +420,15 @@ class Documenter:
directive = getattr(self, 'directivetype', self.objtype) directive = getattr(self, 'directivetype', self.objtype)
name = self.format_name() name = self.format_name()
sourcename = self.get_sourcename() sourcename = self.get_sourcename()
self.add_line('.. %s:%s:: %s%s' % (domain, directive, name, sig),
sourcename) # one signature per line, indented by column
prefix = '.. %s:%s:: ' % (domain, directive)
for i, sig_line in enumerate(sig.split("\n")):
self.add_line('%s%s%s' % (prefix, name, sig_line),
sourcename)
if i == 0:
prefix = " " * len(prefix)
if self.options.noindex: if self.options.noindex:
self.add_line(' :noindex:', sourcename) self.add_line(' :noindex:', sourcename)
if self.objpath: if self.objpath:
@ -428,14 +436,19 @@ class Documenter:
# etc. don't support a prepended module name # etc. don't support a prepended module name
self.add_line(' :module: %s' % self.modname, sourcename) self.add_line(' :module: %s' % self.modname, sourcename)
def get_doc(self, encoding: str = None, ignore: int = 1) -> List[List[str]]: def get_doc(self, encoding: str = None, ignore: int = None) -> List[List[str]]:
"""Decode and return lines of the docstring(s) for the object.""" """Decode and return lines of the docstring(s) for the object."""
if encoding is not None: if encoding is not None:
warnings.warn("The 'encoding' argument to autodoc.%s.get_doc() is deprecated." warnings.warn("The 'encoding' argument to autodoc.%s.get_doc() is deprecated."
% self.__class__.__name__, % self.__class__.__name__,
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
if ignore is not None:
warnings.warn("The 'ignore' argument to autodoc.%s.get_doc() is deprecated."
% self.__class__.__name__,
RemovedInSphinx50Warning, stacklevel=2)
docstring = getdoc(self.object, self.get_attr, docstring = getdoc(self.object, self.get_attr,
self.env.config.autodoc_inherit_docstrings) self.env.config.autodoc_inherit_docstrings,
self.parent, self.object_name)
if docstring: if docstring:
tab_width = self.directive.state.document.settings.tab_width tab_width = self.directive.state.document.settings.tab_width
return [prepare_docstring(docstring, ignore, tab_width)] return [prepare_docstring(docstring, ignore, tab_width)]
@ -466,7 +479,10 @@ class Documenter:
key = ('.'.join(self.objpath[:-1]), self.objpath[-1]) key = ('.'.join(self.objpath[:-1]), self.objpath[-1])
if key in attr_docs: if key in attr_docs:
no_docstring = True no_docstring = True
docstrings = [attr_docs[key]] # make a copy of docstring for attributes to avoid cache
# the change of autodoc-process-docstring event.
docstrings = [list(attr_docs[key])]
for i, line in enumerate(self.process_doc(docstrings)): for i, line in enumerate(self.process_doc(docstrings)):
self.add_line(line, sourcename, i) self.add_line(line, sourcename, i)
@ -556,7 +572,8 @@ class Documenter:
else: else:
isattr = False isattr = False
doc = getdoc(member, self.get_attr, self.env.config.autodoc_inherit_docstrings) doc = getdoc(member, self.get_attr, self.env.config.autodoc_inherit_docstrings,
self.parent, self.object_name)
if not isinstance(doc, str): if not isinstance(doc, str):
# Ignore non-string __doc__ # Ignore non-string __doc__
doc = None doc = None
@ -574,11 +591,17 @@ class Documenter:
if 'private' in metadata: if 'private' in metadata:
# consider a member private if docstring has "private" metadata # consider a member private if docstring has "private" metadata
isprivate = True isprivate = True
elif 'public' in metadata:
# consider a member public if docstring has "public" metadata
isprivate = False
else: else:
isprivate = membername.startswith('_') isprivate = membername.startswith('_')
keep = False keep = False
if want_all and membername.startswith('__') and \ if safe_getattr(member, '__sphinx_mock__', False):
# mocked module or object
pass
elif want_all and membername.startswith('__') and \
membername.endswith('__') and len(membername) > 4: membername.endswith('__') and len(membername) > 4:
# special __methods__ # special __methods__
if self.options.special_members is ALL: if self.options.special_members is ALL:
@ -725,7 +748,8 @@ class Documenter:
# where the attribute documentation would actually be found in. # where the attribute documentation would actually be found in.
# This is used for situations where you have a module that collects the # This is used for situations where you have a module that collects the
# functions and classes of internal submodules. # functions and classes of internal submodules.
self.real_modname = real_modname or self.get_real_modname() # type: str guess_modname = self.get_real_modname()
self.real_modname = real_modname or guess_modname
# try to also get a source code analyzer for attribute docs # try to also get a source code analyzer for attribute docs
try: try:
@ -733,8 +757,8 @@ class Documenter:
# parse right now, to get PycodeErrors on parsing (results will # parse right now, to get PycodeErrors on parsing (results will
# be cached anyway) # be cached anyway)
self.analyzer.find_attr_docs() self.analyzer.find_attr_docs()
except PycodeError as err: except PycodeError:
logger.debug('[autodoc] module analyzer failed: %s', err) logger.debug('[autodoc] module analyzer failed:', exc_info=True)
# no source file -- e.g. for builtin and C modules # no source file -- e.g. for builtin and C modules
self.analyzer = None self.analyzer = None
# at least add the module.__file__ as a dependency # at least add the module.__file__ as a dependency
@ -743,6 +767,14 @@ class Documenter:
else: else:
self.directive.filename_set.add(self.analyzer.srcname) self.directive.filename_set.add(self.analyzer.srcname)
if self.real_modname != guess_modname:
# Add module to dependency list if target object is defined in other module.
try:
analyzer = ModuleAnalyzer.for_module(guess_modname)
self.directive.filename_set.add(analyzer.srcname)
except PycodeError:
pass
# check __module__ of object (for members not given explicitly) # check __module__ of object (for members not given explicitly)
if check_module: if check_module:
if not self.check_module(): if not self.check_module():
@ -828,7 +860,7 @@ class ModuleDocumenter(Documenter):
if self.options.deprecated: if self.options.deprecated:
self.add_line(' :deprecated:', sourcename) self.add_line(' :deprecated:', sourcename)
def get_object_members(self, want_all: bool) -> Tuple[bool, List[Tuple[str, object]]]: def get_object_members(self, want_all: bool) -> Tuple[bool, List[Tuple[str, Any]]]:
if want_all: if want_all:
if (self.options.ignore_module_all or not if (self.options.ignore_module_all or not
hasattr(self.object, '__all__')): hasattr(self.object, '__all__')):
@ -873,8 +905,14 @@ class ModuleLevelDocumenter(Documenter):
) -> Tuple[str, List[str]]: ) -> Tuple[str, List[str]]:
if modname is None: if modname is None:
if path: if path:
modname = path.rstrip('.') stripped = path.rstrip('.')
else: modname, qualname = split_full_qualified_name(stripped)
if qualname:
parents = qualname.split(".")
else:
parents = []
if modname is None:
# if documenting a toplevel object without explicit module, # if documenting a toplevel object without explicit module,
# it can be contained in another auto directive ... # it can be contained in another auto directive ...
modname = self.env.temp_data.get('autodoc:module') modname = self.env.temp_data.get('autodoc:module')
@ -907,8 +945,13 @@ class ClassLevelDocumenter(Documenter):
# ... if still None, there's no way to know # ... if still None, there's no way to know
if mod_cls is None: if mod_cls is None:
return None, [] return None, []
modname, cls = rpartition(mod_cls, '.')
parents = [cls] try:
modname, qualname = split_full_qualified_name(mod_cls)
parents = qualname.split(".") if qualname else []
except ImportError:
parents = mod_cls.split(".")
# if the module name is still missing, get it like above # if the module name is still missing, get it like above
if not modname: if not modname:
modname = self.env.temp_data.get('autodoc:module') modname = self.env.temp_data.get('autodoc:module')
@ -928,7 +971,7 @@ class DocstringSignatureMixin:
if encoding is not None: if encoding is not None:
warnings.warn("The 'encoding' argument to autodoc.%s._find_signature() is " warnings.warn("The 'encoding' argument to autodoc.%s._find_signature() is "
"deprecated." % self.__class__.__name__, "deprecated." % self.__class__.__name__,
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
docstrings = self.get_doc() docstrings = self.get_doc()
self._new_docstrings = docstrings[:] self._new_docstrings = docstrings[:]
result = None result = None
@ -958,11 +1001,11 @@ class DocstringSignatureMixin:
break break
return result return result
def get_doc(self, encoding: str = None, ignore: int = 1) -> List[List[str]]: def get_doc(self, encoding: str = None, ignore: int = None) -> List[List[str]]:
if encoding is not None: if encoding is not None:
warnings.warn("The 'encoding' argument to autodoc.%s.get_doc() is deprecated." warnings.warn("The 'encoding' argument to autodoc.%s.get_doc() is deprecated."
% self.__class__.__name__, % self.__class__.__name__,
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
lines = getattr(self, '_new_docstrings', None) lines = getattr(self, '_new_docstrings', None)
if lines is not None: if lines is not None:
return lines return lines
@ -1014,43 +1057,19 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
if self.env.config.autodoc_typehints in ('none', 'description'): if self.env.config.autodoc_typehints in ('none', 'description'):
kwargs.setdefault('show_annotation', False) kwargs.setdefault('show_annotation', False)
unwrapped = inspect.unwrap(self.object)
if ((inspect.isbuiltin(unwrapped) or inspect.ismethoddescriptor(unwrapped)) and
not inspect.is_cython_function_or_method(unwrapped)):
# cannot introspect arguments of a C function or method
return None
try: try:
if (not inspect.isfunction(unwrapped) and self.env.app.emit('autodoc-before-process-signature', self.object, False)
not inspect.ismethod(unwrapped) and if inspect.is_singledispatch_function(self.object):
not inspect.isbuiltin(unwrapped) and sig = inspect.signature(self.object, follow_wrapped=True)
not inspect.is_cython_function_or_method(unwrapped) and
not inspect.isclass(unwrapped) and
hasattr(unwrapped, '__call__')):
self.env.app.emit('autodoc-before-process-signature',
unwrapped.__call__, False)
sig = inspect.signature(unwrapped.__call__)
else: else:
self.env.app.emit('autodoc-before-process-signature', unwrapped, False) sig = inspect.signature(self.object)
sig = inspect.signature(unwrapped)
args = stringify_signature(sig, **kwargs) args = stringify_signature(sig, **kwargs)
except TypeError: except TypeError as exc:
if (inspect.is_builtin_class_method(unwrapped, '__new__') and logger.warning(__("Failed to get a function signature for %s: %s"),
inspect.is_builtin_class_method(unwrapped, '__init__')): self.fullname, exc)
raise TypeError('%r is a builtin class' % unwrapped) return None
except ValueError:
# if a class should be documented as function (yay duck args = ''
# typing) we try to use the constructor signature as function
# signature without the first argument.
try:
self.env.app.emit('autodoc-before-process-signature',
unwrapped.__new__, True)
sig = inspect.signature(unwrapped.__new__, bound_method=True)
args = stringify_signature(sig, show_return_annotation=False, **kwargs)
except TypeError:
self.env.app.emit('autodoc-before-process-signature',
unwrapped.__init__, True)
sig = inspect.signature(unwrapped.__init__, bound_method=True)
args = stringify_signature(sig, show_return_annotation=False, **kwargs)
if self.env.config.strip_signature_backslash: if self.env.config.strip_signature_backslash:
# escape backslashes for reST # escape backslashes for reST
@ -1067,51 +1086,23 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # typ
if inspect.iscoroutinefunction(self.object): if inspect.iscoroutinefunction(self.object):
self.add_line(' :async:', sourcename) self.add_line(' :async:', sourcename)
def format_signature(self, **kwargs: Any) -> str:
sig = super().format_signature(**kwargs)
sigs = [sig]
class SingledispatchFunctionDocumenter(FunctionDocumenter): if inspect.is_singledispatch_function(self.object):
""" # append signature of singledispatch'ed functions
Specialized Documenter subclass for singledispatch'ed functions. for typ, func in self.object.registry.items():
""" if typ is object:
objtype = 'singledispatch_function' pass # default implementation. skipped.
directivetype = 'function' else:
member_order = 30 self.annotate_to_first_argument(func, typ)
# before FunctionDocumenter documenter = FunctionDocumenter(self.directive, '')
priority = FunctionDocumenter.priority + 1 documenter.object = func
sigs.append(documenter.format_signature())
@classmethod return "\n".join(sigs)
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
) -> bool:
return (super().can_document_member(member, membername, isattr, parent) and
inspect.is_singledispatch_function(member))
def add_directive_header(self, sig: str) -> None:
sourcename = self.get_sourcename()
# intercept generated directive headers
# TODO: It is very hacky to use mock to intercept header generation
with patch.object(self, 'add_line') as add_line:
super().add_directive_header(sig)
# output first line of header
self.add_line(*add_line.call_args_list[0][0])
# inserts signature of singledispatch'ed functions
for typ, func in self.object.registry.items():
if typ is object:
pass # default implementation. skipped.
else:
self.annotate_to_first_argument(func, typ)
documenter = FunctionDocumenter(self.directive, '')
documenter.object = func
self.add_line(' %s%s' % (self.format_name(),
documenter.format_signature()),
sourcename)
# output remains of directive header
for call in add_line.call_args_list[1:]:
self.add_line(*call[0])
def annotate_to_first_argument(self, func: Callable, typ: Type) -> None: def annotate_to_first_argument(self, func: Callable, typ: Type) -> None:
"""Annotate type hint to the first argument of function if needed.""" """Annotate type hint to the first argument of function if needed."""
@ -1125,6 +1116,14 @@ class SingledispatchFunctionDocumenter(FunctionDocumenter):
func.__signature__ = sig.replace(parameters=params) # type: ignore func.__signature__ = sig.replace(parameters=params) # type: ignore
class SingledispatchFunctionDocumenter(FunctionDocumenter):
"""
Used to be a specialized Documenter subclass for singledispatch'ed functions.
Retained for backwards compatibility, now does the same as the FunctionDocumenter
"""
class DecoratorDocumenter(FunctionDocumenter): class DecoratorDocumenter(FunctionDocumenter):
""" """
Specialized Documenter subclass for decorator functions. Specialized Documenter subclass for decorator functions.
@ -1204,10 +1203,15 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
return super().format_signature(**kwargs) return super().format_signature(**kwargs)
def add_directive_header(self, sig: str) -> None: def add_directive_header(self, sig: str) -> None:
sourcename = self.get_sourcename()
if self.doc_as_attr: if self.doc_as_attr:
self.directivetype = 'attribute' self.directivetype = 'attribute'
super().add_directive_header(sig) super().add_directive_header(sig)
if self.analyzer and '.'.join(self.objpath) in self.analyzer.finals:
self.add_line(' :final:', sourcename)
# add inheritance info, if wanted # add inheritance info, if wanted
if not self.doc_as_attr and self.options.show_inheritance: if not self.doc_as_attr and self.options.show_inheritance:
sourcename = self.get_sourcename() sourcename = self.get_sourcename()
@ -1220,11 +1224,11 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
self.add_line(' ' + _('Bases: %s') % ', '.join(bases), self.add_line(' ' + _('Bases: %s') % ', '.join(bases),
sourcename) sourcename)
def get_doc(self, encoding: str = None, ignore: int = 1) -> List[List[str]]: def get_doc(self, encoding: str = None, ignore: int = None) -> List[List[str]]:
if encoding is not None: if encoding is not None:
warnings.warn("The 'encoding' argument to autodoc.%s.get_doc() is deprecated." warnings.warn("The 'encoding' argument to autodoc.%s.get_doc() is deprecated."
% self.__class__.__name__, % self.__class__.__name__,
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
lines = getattr(self, '_new_docstrings', None) lines = getattr(self, '_new_docstrings', None)
if lines is not None: if lines is not None:
return lines return lines
@ -1241,7 +1245,8 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
if content in ('both', 'init'): if content in ('both', 'init'):
__init__ = self.get_attr(self.object, '__init__', None) __init__ = self.get_attr(self.object, '__init__', None)
initdocstring = getdoc(__init__, self.get_attr, initdocstring = getdoc(__init__, self.get_attr,
self.env.config.autodoc_inherit_docstrings) self.env.config.autodoc_inherit_docstrings,
self.parent, self.object_name)
# for new-style classes, no __init__ means default __init__ # for new-style classes, no __init__ means default __init__
if (initdocstring is not None and if (initdocstring is not None and
(initdocstring == object.__init__.__doc__ or # for pypy (initdocstring == object.__init__.__doc__ or # for pypy
@ -1251,7 +1256,8 @@ class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter): # type:
# try __new__ # try __new__
__new__ = self.get_attr(self.object, '__new__', None) __new__ = self.get_attr(self.object, '__new__', None)
initdocstring = getdoc(__new__, self.get_attr, initdocstring = getdoc(__new__, self.get_attr,
self.env.config.autodoc_inherit_docstrings) self.env.config.autodoc_inherit_docstrings,
self.parent, self.object_name)
# for new-style classes, no __new__ means default __new__ # for new-style classes, no __new__ means default __new__
if (initdocstring is not None and if (initdocstring is not None and
(initdocstring == object.__new__.__doc__ or # for pypy (initdocstring == object.__new__.__doc__ or # for pypy
@ -1345,8 +1351,11 @@ class DataDocumenter(ModuleLevelDocumenter):
sourcename) sourcename)
try: try:
objrepr = object_description(self.object) if self.object is UNINITIALIZED_ATTR:
self.add_line(' :value: ' + objrepr, sourcename) pass
else:
objrepr = object_description(self.object)
self.add_line(' :value: ' + objrepr, sourcename)
except ValueError: except ValueError:
pass pass
elif self.options.annotation is SUPPRESS: elif self.options.annotation is SUPPRESS:
@ -1387,6 +1396,7 @@ class DataDeclarationDocumenter(DataDocumenter):
"""Never import anything.""" """Never import anything."""
# disguise as a data # disguise as a data
self.objtype = 'data' self.objtype = 'data'
self.object = UNINITIALIZED_ATTR
try: try:
# import module to obtain type annotation # import module to obtain type annotation
self.parent = importlib.import_module(self.modname) self.parent = importlib.import_module(self.modname)
@ -1436,18 +1446,33 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
if self.env.config.autodoc_typehints in ('none', 'description'): if self.env.config.autodoc_typehints in ('none', 'description'):
kwargs.setdefault('show_annotation', False) kwargs.setdefault('show_annotation', False)
unwrapped = inspect.unwrap(self.object) try:
if ((inspect.isbuiltin(unwrapped) or inspect.ismethoddescriptor(unwrapped)) and if self.object == object.__init__ and self.parent != object:
not inspect.is_cython_function_or_method(unwrapped)): # Classes not having own __init__() method are shown as no arguments.
# can never get arguments of a C function or method #
# Note: The signature of object.__init__() is (self, /, *args, **kwargs).
# But it makes users confused.
args = '()'
else:
if inspect.isstaticmethod(self.object, cls=self.parent, name=self.object_name):
self.env.app.emit('autodoc-before-process-signature', self.object, False)
sig = inspect.signature(self.object, bound_method=False)
else:
self.env.app.emit('autodoc-before-process-signature', self.object, True)
meth = self.parent.__dict__.get(self.objpath[-1], None)
if meth and inspect.is_singledispatch_method(meth):
sig = inspect.signature(self.object, bound_method=True,
follow_wrapped=True)
else:
sig = inspect.signature(self.object, bound_method=True)
args = stringify_signature(sig, **kwargs)
except TypeError as exc:
logger.warning(__("Failed to get a method signature for %s: %s"),
self.fullname, exc)
return None return None
if inspect.isstaticmethod(unwrapped, cls=self.parent, name=self.object_name): except ValueError:
self.env.app.emit('autodoc-before-process-signature', unwrapped, False) args = ''
sig = inspect.signature(unwrapped, bound_method=False)
else:
self.env.app.emit('autodoc-before-process-signature', unwrapped, True)
sig = inspect.signature(unwrapped, bound_method=True)
args = stringify_signature(sig, **kwargs)
if self.env.config.strip_signature_backslash: if self.env.config.strip_signature_backslash:
# escape backslashes for reST # escape backslashes for reST
@ -1467,59 +1492,32 @@ class MethodDocumenter(DocstringSignatureMixin, ClassLevelDocumenter): # type:
self.add_line(' :classmethod:', sourcename) self.add_line(' :classmethod:', sourcename)
if inspect.isstaticmethod(obj, cls=self.parent, name=self.object_name): if inspect.isstaticmethod(obj, cls=self.parent, name=self.object_name):
self.add_line(' :staticmethod:', sourcename) self.add_line(' :staticmethod:', sourcename)
if self.analyzer and '.'.join(self.objpath) in self.analyzer.finals:
self.add_line(' :final:', sourcename)
def document_members(self, all_members: bool = False) -> None: def document_members(self, all_members: bool = False) -> None:
pass pass
def format_signature(self, **kwargs: Any) -> str:
sig = super().format_signature(**kwargs)
sigs = [sig]
class SingledispatchMethodDocumenter(MethodDocumenter):
"""
Specialized Documenter subclass for singledispatch'ed methods.
"""
objtype = 'singledispatch_method'
directivetype = 'method'
member_order = 50
# before MethodDocumenter
priority = MethodDocumenter.priority + 1
@classmethod
def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any
) -> bool:
if super().can_document_member(member, membername, isattr, parent) and parent.object:
meth = parent.object.__dict__.get(membername)
return inspect.is_singledispatch_method(meth)
else:
return False
def add_directive_header(self, sig: str) -> None:
sourcename = self.get_sourcename()
# intercept generated directive headers
# TODO: It is very hacky to use mock to intercept header generation
with patch.object(self, 'add_line') as add_line:
super().add_directive_header(sig)
# output first line of header
self.add_line(*add_line.call_args_list[0][0])
# inserts signature of singledispatch'ed functions
meth = self.parent.__dict__.get(self.objpath[-1]) meth = self.parent.__dict__.get(self.objpath[-1])
for typ, func in meth.dispatcher.registry.items(): if inspect.is_singledispatch_method(meth):
if typ is object: # append signature of singledispatch'ed functions
pass # default implementation. skipped. for typ, func in meth.dispatcher.registry.items():
else: if typ is object:
self.annotate_to_first_argument(func, typ) pass # default implementation. skipped.
else:
self.annotate_to_first_argument(func, typ)
documenter = MethodDocumenter(self.directive, '') documenter = MethodDocumenter(self.directive, '')
documenter.object = func documenter.parent = self.parent
self.add_line(' %s%s' % (self.format_name(), documenter.object = func
documenter.format_signature()), documenter.objpath = [None]
sourcename) sigs.append(documenter.format_signature())
# output remains of directive header return "\n".join(sigs)
for call in add_line.call_args_list[1:]:
self.add_line(*call[0])
def annotate_to_first_argument(self, func: Callable, typ: Type) -> None: def annotate_to_first_argument(self, func: Callable, typ: Type) -> None:
"""Annotate type hint to the first argument of function if needed.""" """Annotate type hint to the first argument of function if needed."""
@ -1533,6 +1531,14 @@ class SingledispatchMethodDocumenter(MethodDocumenter):
func.__signature__ = sig.replace(parameters=params) # type: ignore func.__signature__ = sig.replace(parameters=params) # type: ignore
class SingledispatchMethodDocumenter(MethodDocumenter):
"""
Used to be a specialized Documenter subclass for singledispatch'ed methods.
Retained for backwards compatibility, now does the same as the MethodDocumenter
"""
class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): # type: ignore class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter): # type: ignore
""" """
Specialized Documenter subclass for attributes. Specialized Documenter subclass for attributes.
@ -1584,21 +1590,25 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
super().add_directive_header(sig) super().add_directive_header(sig)
sourcename = self.get_sourcename() sourcename = self.get_sourcename()
if not self.options.annotation: if not self.options.annotation:
if not self._datadescriptor: # obtain type annotation for this attribute
# obtain annotation for this attribute annotations = getattr(self.parent, '__annotations__', {})
annotations = getattr(self.parent, '__annotations__', {}) if annotations and self.objpath[-1] in annotations:
if annotations and self.objpath[-1] in annotations: objrepr = stringify_typehint(annotations.get(self.objpath[-1]))
objrepr = stringify_typehint(annotations.get(self.objpath[-1])) self.add_line(' :type: ' + objrepr, sourcename)
self.add_line(' :type: ' + objrepr, sourcename) else:
else: key = ('.'.join(self.objpath[:-1]), self.objpath[-1])
key = ('.'.join(self.objpath[:-1]), self.objpath[-1]) if self.analyzer and key in self.analyzer.annotations:
if self.analyzer and key in self.analyzer.annotations: self.add_line(' :type: ' + self.analyzer.annotations[key],
self.add_line(' :type: ' + self.analyzer.annotations[key], sourcename)
sourcename)
# data descriptors do not have useful values
if not self._datadescriptor:
try: try:
objrepr = object_description(self.object) if self.object is INSTANCEATTR:
self.add_line(' :value: ' + objrepr, sourcename) pass
else:
objrepr = object_description(self.object)
self.add_line(' :value: ' + objrepr, sourcename)
except ValueError: except ValueError:
pass pass
elif self.options.annotation is SUPPRESS: elif self.options.annotation is SUPPRESS:
@ -1669,6 +1679,7 @@ class InstanceAttributeDocumenter(AttributeDocumenter):
"""Never import anything.""" """Never import anything."""
# disguise as an attribute # disguise as an attribute
self.objtype = 'attribute' self.objtype = 'attribute'
self.object = INSTANCEATTR
self._datadescriptor = False self._datadescriptor = False
return True return True
@ -1713,8 +1724,12 @@ class SlotsAttributeDocumenter(AttributeDocumenter):
self.env.note_reread() self.env.note_reread()
return False return False
def get_doc(self, encoding: str = None, ignore: int = 1) -> List[List[str]]: def get_doc(self, encoding: str = None, ignore: int = None) -> List[List[str]]:
"""Decode and return lines of the docstring(s) for the object.""" """Decode and return lines of the docstring(s) for the object."""
if ignore is not None:
warnings.warn("The 'ignore' argument to autodoc.%s.get_doc() is deprecated."
% self.__class__.__name__,
RemovedInSphinx50Warning, stacklevel=2)
name = self.objpath[-1] name = self.objpath[-1]
__slots__ = safe_getattr(self.parent, '__slots__', []) __slots__ = safe_getattr(self.parent, '__slots__', [])
if isinstance(__slots__, dict) and isinstance(__slots__.get(name), str): if isinstance(__slots__, dict) and isinstance(__slots__.get(name), str):
@ -1726,7 +1741,7 @@ class SlotsAttributeDocumenter(AttributeDocumenter):
def get_documenters(app: Sphinx) -> Dict[str, "Type[Documenter]"]: def get_documenters(app: Sphinx) -> Dict[str, "Type[Documenter]"]:
"""Returns registered Documenter classes""" """Returns registered Documenter classes"""
warnings.warn("get_documenters() is deprecated.", RemovedInSphinx50Warning) warnings.warn("get_documenters() is deprecated.", RemovedInSphinx50Warning, stacklevel=2)
return app.registry.documenters return app.registry.documenters
@ -1739,6 +1754,14 @@ def autodoc_attrgetter(app: Sphinx, obj: Any, name: str, *defargs: Any) -> Any:
return safe_getattr(obj, name, *defargs) return safe_getattr(obj, name, *defargs)
def migrate_autodoc_member_order(app: Sphinx, config: Config) -> None:
if config.autodoc_member_order == 'alphabetic':
# RemovedInSphinx50Warning
logger.warning(__('autodoc_member_order now accepts "alphabetical" '
'instead of "alphabetic". Please update your setting.'))
config.autodoc_member_order = 'alphabetical' # type: ignore
def setup(app: Sphinx) -> Dict[str, Any]: def setup(app: Sphinx) -> Dict[str, Any]:
app.add_autodocumenter(ModuleDocumenter) app.add_autodocumenter(ModuleDocumenter)
app.add_autodocumenter(ClassDocumenter) app.add_autodocumenter(ClassDocumenter)
@ -1746,18 +1769,16 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_autodocumenter(DataDocumenter) app.add_autodocumenter(DataDocumenter)
app.add_autodocumenter(DataDeclarationDocumenter) app.add_autodocumenter(DataDeclarationDocumenter)
app.add_autodocumenter(FunctionDocumenter) app.add_autodocumenter(FunctionDocumenter)
app.add_autodocumenter(SingledispatchFunctionDocumenter)
app.add_autodocumenter(DecoratorDocumenter) app.add_autodocumenter(DecoratorDocumenter)
app.add_autodocumenter(MethodDocumenter) app.add_autodocumenter(MethodDocumenter)
app.add_autodocumenter(SingledispatchMethodDocumenter)
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_autodocumenter(SlotsAttributeDocumenter)
app.add_config_value('autoclass_content', 'class', True) app.add_config_value('autoclass_content', 'class', True, ENUM('both', 'class', 'init'))
app.add_config_value('autodoc_member_order', 'alphabetic', True) app.add_config_value('autodoc_member_order', 'alphabetical', True,
app.add_config_value('autodoc_default_flags', [], True) ENUM('alphabetic', 'alphabetical', 'bysource', 'groupwise'))
app.add_config_value('autodoc_default_options', {}, True) app.add_config_value('autodoc_default_options', {}, True)
app.add_config_value('autodoc_docstring_signature', True, True) app.add_config_value('autodoc_docstring_signature', True, True)
app.add_config_value('autodoc_mock_imports', [], True) app.add_config_value('autodoc_mock_imports', [], True)
@ -1770,6 +1791,8 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_event('autodoc-process-signature') app.add_event('autodoc-process-signature')
app.add_event('autodoc-skip-member') app.add_event('autodoc-skip-member')
app.connect('config-inited', migrate_autodoc_member_order)
app.setup_extension('sphinx.ext.autodoc.type_comment') app.setup_extension('sphinx.ext.autodoc.type_comment')
app.setup_extension('sphinx.ext.autodoc.typehints') app.setup_extension('sphinx.ext.autodoc.typehints')

View File

@ -66,7 +66,7 @@ class DocumenterBridge:
else: else:
# create fake object for self.state.document.settings.tab_width # create fake object for self.state.document.settings.tab_width
warnings.warn('DocumenterBridge requires a state object on instantiation.', warnings.warn('DocumenterBridge requires a state object on instantiation.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
settings = Struct(tab_width=8) settings = Struct(tab_width=8)
document = Struct(settings=settings) document = Struct(settings=settings)
self.state = Struct(document=document) self.state = Struct(document=document)

View File

@ -11,10 +11,10 @@
import importlib import importlib
import traceback import traceback
import warnings import warnings
from collections import namedtuple from typing import Any, Callable, Dict, List, Mapping, NamedTuple, Tuple
from typing import Any, Callable, Dict, List, Mapping, Tuple
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
from sphinx.pycode import ModuleAnalyzer
from sphinx.util import logging from sphinx.util import logging
from sphinx.util.inspect import isclass, isenumclass, safe_getattr from sphinx.util.inspect import isclass, isenumclass, safe_getattr
@ -122,11 +122,13 @@ def get_module_members(module: Any) -> List[Tuple[str, Any]]:
return sorted(list(members.values())) return sorted(list(members.values()))
Attribute = namedtuple('Attribute', ['name', 'directly_defined', 'value']) Attribute = NamedTuple('Attribute', [('name', str),
('directly_defined', bool),
('value', Any)])
def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable, def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable,
analyzer: Any = None) -> Dict[str, Attribute]: analyzer: ModuleAnalyzer = None) -> Dict[str, Attribute]:
"""Get members and attributes of target object.""" """Get members and attributes of target object."""
from sphinx.ext.autodoc import INSTANCEATTR from sphinx.ext.autodoc import INSTANCEATTR
@ -142,8 +144,9 @@ def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable,
members[name] = Attribute(name, True, value) members[name] = Attribute(name, True, value)
superclass = subject.__mro__[1] superclass = subject.__mro__[1]
for name, value in obj_dict.items(): for name in obj_dict:
if name not in superclass.__dict__: if name not in superclass.__dict__:
value = safe_getattr(subject, name)
members[name] = Attribute(name, True, value) members[name] = Attribute(name, True, value)
# members in __slots__ # members in __slots__

View File

@ -25,6 +25,7 @@ class _MockObject:
"""Used by autodoc_mock_imports.""" """Used by autodoc_mock_imports."""
__display_name__ = '_MockObject' __display_name__ = '_MockObject'
__sphinx_mock__ = True
def __new__(cls, *args: Any, **kwargs: Any) -> Any: def __new__(cls, *args: Any, **kwargs: Any) -> Any:
if len(args) == 3 and isinstance(args[1], tuple): if len(args) == 3 and isinstance(args[1], tuple):
@ -78,6 +79,7 @@ def _make_subclass(name: str, module: str, superclass: Any = _MockObject,
class _MockModule(ModuleType): class _MockModule(ModuleType):
"""Used by autodoc_mock_imports.""" """Used by autodoc_mock_imports."""
__file__ = os.devnull __file__ = os.devnull
__sphinx_mock__ = True
def __init__(self, name: str) -> None: def __init__(self, name: str) -> None:
super().__init__(name) super().__init__(name)

View File

@ -104,24 +104,16 @@ def modify_field_list(node: nodes.field_list, annotations: Dict[str, str]) -> No
continue continue
arg = arguments.get(name, {}) arg = arguments.get(name, {})
field = nodes.field() if not arg.get('type'):
if arg.get('param') and arg.get('type'): field = nodes.field()
# both param and type are already filled manually
continue
elif arg.get('param'):
# only param: fill type field
field += nodes.field_name('', 'type ' + name) field += nodes.field_name('', 'type ' + name)
field += nodes.field_body('', nodes.paragraph('', annotation)) field += nodes.field_body('', nodes.paragraph('', annotation))
elif arg.get('type'): node += field
# only type: It's odd... if not arg.get('param'):
field = nodes.field()
field += nodes.field_name('', 'param ' + name) field += nodes.field_name('', 'param ' + name)
field += nodes.field_body('', nodes.paragraph('', '')) field += nodes.field_body('', nodes.paragraph('', ''))
else: node += field
# both param and type are not found
field += nodes.field_name('', 'param ' + annotation + ' ' + name)
field += nodes.field_body('', nodes.paragraph('', ''))
node += field
if 'return' in annotations and 'return' not in arguments: if 'return' in annotations and 'return' not in arguments:
field = nodes.field() field = nodes.field()

View File

@ -228,8 +228,10 @@ class Autosummary(SphinxDirective):
final_argument_whitespace = False final_argument_whitespace = False
has_content = True has_content = True
option_spec = { option_spec = {
'caption': directives.unchanged_required,
'toctree': directives.unchanged, 'toctree': directives.unchanged,
'nosignatures': directives.flag, 'nosignatures': directives.flag,
'recursive': directives.flag,
'template': directives.unchanged, 'template': directives.unchanged,
} }
@ -270,9 +272,14 @@ class Autosummary(SphinxDirective):
tocnode['entries'] = [(None, docn) for docn in docnames] tocnode['entries'] = [(None, docn) for docn in docnames]
tocnode['maxdepth'] = -1 tocnode['maxdepth'] = -1
tocnode['glob'] = None tocnode['glob'] = None
tocnode['caption'] = self.options.get('caption')
nodes.append(autosummary_toc('', '', tocnode)) nodes.append(autosummary_toc('', '', tocnode))
if 'toctree' not in self.options and 'caption' in self.options:
logger.warning(__('A captioned autosummary requires :toctree: option. ignored.'),
location=nodes[-1])
return nodes return nodes
def get_items(self, names: List[str]) -> List[Tuple[str, str, str, str]]: def get_items(self, names: List[str]) -> List[Tuple[str, str, str, str]]:
@ -295,8 +302,7 @@ class Autosummary(SphinxDirective):
with mock(self.config.autosummary_mock_imports): with mock(self.config.autosummary_mock_imports):
real_name, obj, parent, modname = import_by_name(name, prefixes=prefixes) real_name, obj, parent, modname = import_by_name(name, prefixes=prefixes)
except ImportError: except ImportError:
logger.warning(__('failed to import %s'), name) logger.warning(__('autosummary: failed to import %s'), name)
items.append((name, '', '', name))
continue continue
self.bridge.result = StringList() # initialize for each documenter self.bridge.result = StringList() # initialize for each documenter
@ -652,7 +658,7 @@ def autolink_role(typ: str, rawtext: str, etext: str, lineno: int, inliner: Inli
Expands to ':obj:`text`' if `text` is an object that can be imported; Expands to ':obj:`text`' if `text` is an object that can be imported;
otherwise expands to '*text*'. otherwise expands to '*text*'.
""" """
warnings.warn('autolink_role() is deprecated.', RemovedInSphinx40Warning) warnings.warn('autolink_role() is deprecated.', RemovedInSphinx40Warning, stacklevel=2)
env = inliner.document.settings.env env = inliner.document.settings.env
pyobj_role = env.get_domain('py').role('obj') pyobj_role = env.get_domain('py').role('obj')
objects, msg = pyobj_role('obj', rawtext, etext, lineno, inliner, options, content) objects, msg = pyobj_role('obj', rawtext, etext, lineno, inliner, options, content)
@ -745,8 +751,7 @@ def process_generate_options(app: Sphinx) -> None:
imported_members = app.config.autosummary_imported_members imported_members = app.config.autosummary_imported_members
with mock(app.config.autosummary_mock_imports): with mock(app.config.autosummary_mock_imports):
generate_autosummary_docs(genfiles, builder=app.builder, generate_autosummary_docs(genfiles, suffix=suffix, base_path=app.srcdir,
suffix=suffix, base_path=app.srcdir,
app=app, imported_members=imported_members, app=app, imported_members=imported_members,
overwrite=app.config.autosummary_generate_overwrite) overwrite=app.config.autosummary_generate_overwrite)
@ -769,6 +774,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
app.add_directive('autosummary', Autosummary) app.add_directive('autosummary', Autosummary)
app.add_role('autolink', AutoLink()) app.add_role('autolink', AutoLink())
app.connect('builder-inited', process_generate_options) app.connect('builder-inited', process_generate_options)
app.add_config_value('autosummary_context', {}, True)
app.add_config_value('autosummary_generate', [], True, [bool]) app.add_config_value('autosummary_generate', [], True, [bool])
app.add_config_value('autosummary_generate_overwrite', True, False) app.add_config_value('autosummary_generate_overwrite', True, False)
app.add_config_value('autosummary_mock_imports', app.add_config_value('autosummary_mock_imports',

View File

@ -20,29 +20,35 @@
import argparse import argparse
import locale import locale
import os import os
import pkgutil
import pydoc import pydoc
import re import re
import sys import sys
import warnings import warnings
from typing import Any, Callable, Dict, List, NamedTuple, Set, Tuple from gettext import NullTranslations
from os import path
from typing import Any, Callable, Dict, List, NamedTuple, Set, Tuple, Union
from jinja2 import BaseLoader, FileSystemLoader, TemplateNotFound from jinja2 import TemplateNotFound
from jinja2.sandbox import SandboxedEnvironment from jinja2.sandbox import SandboxedEnvironment
import sphinx.locale import sphinx.locale
from sphinx import __display_version__ from sphinx import __display_version__
from sphinx import package_dir from sphinx import package_dir
from sphinx.application import Sphinx
from sphinx.builders import Builder from sphinx.builders import Builder
from sphinx.config import Config
from sphinx.deprecation import RemovedInSphinx40Warning, RemovedInSphinx50Warning from sphinx.deprecation import RemovedInSphinx40Warning, RemovedInSphinx50Warning
from sphinx.ext.autodoc import Documenter from sphinx.ext.autodoc import Documenter
from sphinx.ext.autosummary import import_by_name, get_documenter from sphinx.ext.autosummary import import_by_name, get_documenter
from sphinx.jinja2glue import BuiltinTemplateLoader
from sphinx.locale import __ from sphinx.locale import __
from sphinx.registry import SphinxComponentRegistry from sphinx.registry import SphinxComponentRegistry
from sphinx.util import logging from sphinx.util import logging
from sphinx.util import rst from sphinx.util import rst
from sphinx.util import split_full_qualified_name
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.template import SphinxTemplateLoader
if False: if False:
# For type annotation # For type annotation
@ -55,20 +61,27 @@ logger = logging.getLogger(__name__)
class DummyApplication: class DummyApplication:
"""Dummy Application class for sphinx-autogen command.""" """Dummy Application class for sphinx-autogen command."""
def __init__(self) -> None: def __init__(self, translator: NullTranslations) -> None:
self.config = Config()
self.registry = SphinxComponentRegistry() self.registry = SphinxComponentRegistry()
self.messagelog = [] # type: List[str] self.messagelog = [] # type: List[str]
self.srcdir = "/"
self.translator = translator
self.verbosity = 0 self.verbosity = 0
self._warncount = 0 self._warncount = 0
self.warningiserror = False self.warningiserror = False
self.config.add('autosummary_context', {}, True, None)
self.config.init_values()
def emit_firstresult(self, *args: Any) -> None: def emit_firstresult(self, *args: Any) -> None:
pass pass
AutosummaryEntry = NamedTuple('AutosummaryEntry', [('name', str), AutosummaryEntry = NamedTuple('AutosummaryEntry', [('name', str),
('path', str), ('path', str),
('template', str)]) ('template', str),
('recursive', bool)])
def setup_documenters(app: Any) -> None: def setup_documenters(app: Any) -> None:
@ -107,25 +120,37 @@ def _underline(title: str, line: str = '=') -> str:
class AutosummaryRenderer: class AutosummaryRenderer:
"""A helper class for rendering.""" """A helper class for rendering."""
def __init__(self, builder: Builder, template_dir: str) -> None: def __init__(self, app: Union[Builder, Sphinx], template_dir: str = None) -> None:
loader = None # type: BaseLoader if isinstance(app, Builder):
template_dirs = [os.path.join(package_dir, 'ext', 'autosummary', 'templates')] warnings.warn('The first argument for AutosummaryRenderer has been '
if builder is None: 'changed to Sphinx object',
if template_dir: RemovedInSphinx50Warning, stacklevel=2)
template_dirs.insert(0, template_dir) if template_dir:
loader = FileSystemLoader(template_dirs) warnings.warn('template_dir argument for AutosummaryRenderer is deprecated.',
else: RemovedInSphinx50Warning, stacklevel=2)
# allow the user to override the templates
loader = BuiltinTemplateLoader() system_templates_path = [os.path.join(package_dir, 'ext', 'autosummary', 'templates')]
loader.init(builder, dirs=template_dirs) loader = SphinxTemplateLoader(app.srcdir, app.config.templates_path,
system_templates_path)
self.env = SandboxedEnvironment(loader=loader) self.env = SandboxedEnvironment(loader=loader)
self.env.filters['escape'] = rst.escape self.env.filters['escape'] = rst.escape
self.env.filters['e'] = rst.escape self.env.filters['e'] = rst.escape
self.env.filters['underline'] = _underline self.env.filters['underline'] = _underline
if isinstance(app, (Sphinx, DummyApplication)):
if app.translator:
self.env.add_extension("jinja2.ext.i18n")
self.env.install_gettext_translations(app.translator) # type: ignore
elif isinstance(app, Builder):
if app.app.translator:
self.env.add_extension("jinja2.ext.i18n")
self.env.install_gettext_translations(app.app.translator) # type: ignore
def exists(self, template_name: str) -> bool: def exists(self, template_name: str) -> bool:
"""Check if template file exists.""" """Check if template file exists."""
warnings.warn('AutosummaryRenderer.exists() is deprecated.',
RemovedInSphinx50Warning, stacklevel=2)
try: try:
self.env.get_template(template_name) self.env.get_template(template_name)
return True return True
@ -134,7 +159,17 @@ class AutosummaryRenderer:
def render(self, template_name: str, context: Dict) -> str: def render(self, template_name: str, context: Dict) -> str:
"""Render a template file.""" """Render a template file."""
return self.env.get_template(template_name).render(context) try:
template = self.env.get_template(template_name)
except TemplateNotFound:
try:
# objtype is given as template_name
template = self.env.get_template('autosummary/%s.rst' % template_name)
except TemplateNotFound:
# fallback to base.rst
template = self.env.get_template('autosummary/base.rst')
return template.render(context)
# -- Generating output --------------------------------------------------------- # -- Generating output ---------------------------------------------------------
@ -142,14 +177,10 @@ class AutosummaryRenderer:
def generate_autosummary_content(name: str, obj: Any, parent: Any, def generate_autosummary_content(name: str, obj: Any, parent: Any,
template: AutosummaryRenderer, template_name: str, template: AutosummaryRenderer, template_name: str,
imported_members: bool, app: Any) -> str: imported_members: bool, app: Any,
recursive: bool, context: Dict) -> str:
doc = get_documenter(app, obj, parent) doc = get_documenter(app, obj, parent)
if template_name is None:
template_name = 'autosummary/%s.rst' % doc.objtype
if not template.exists(template_name):
template_name = 'autosummary/base.rst'
def skip_member(obj: Any, name: str, objtype: str) -> bool: def skip_member(obj: Any, name: str, objtype: str) -> bool:
try: try:
return app.emit_firstresult('autodoc-skip-member', objtype, name, return app.emit_firstresult('autodoc-skip-member', objtype, name,
@ -187,7 +218,16 @@ def generate_autosummary_content(name: str, obj: Any, parent: Any,
public.append(name) public.append(name)
return public, items return public, items
def get_modules(obj: Any) -> Tuple[List[str], List[str]]:
items = [] # type: List[str]
for _, modname, ispkg in pkgutil.iter_modules(obj.__path__):
fullname = name + '.' + modname
items.append(fullname)
public = [x for x in items if not x.split('.')[-1].startswith('_')]
return public, items
ns = {} # type: Dict[str, Any] ns = {} # type: Dict[str, Any]
ns.update(context)
if doc.objtype == 'module': if doc.objtype == 'module':
ns['members'] = dir(obj) ns['members'] = dir(obj)
@ -197,6 +237,9 @@ def generate_autosummary_content(name: str, obj: Any, parent: Any,
get_members(obj, {'class'}, imported=imported_members) get_members(obj, {'class'}, imported=imported_members)
ns['exceptions'], ns['all_exceptions'] = \ ns['exceptions'], ns['all_exceptions'] = \
get_members(obj, {'exception'}, imported=imported_members) get_members(obj, {'exception'}, imported=imported_members)
ispackage = hasattr(obj, '__path__')
if ispackage and recursive:
ns['modules'], ns['all_modules'] = get_modules(obj)
# Find module attributes with docstrings # Find module attributes with docstrings
attrs, public = [], [] attrs, public = [], []
@ -221,24 +264,27 @@ def generate_autosummary_content(name: str, obj: Any, parent: Any,
ns['attributes'], ns['all_attributes'] = \ ns['attributes'], ns['all_attributes'] = \
get_members(obj, {'attribute', 'property'}) get_members(obj, {'attribute', 'property'})
parts = name.split('.') modname, qualname = split_full_qualified_name(name)
if doc.objtype in ('method', 'attribute', 'property'): if doc.objtype in ('method', 'attribute', 'property'):
mod_name = '.'.join(parts[:-2]) ns['class'] = qualname.rsplit(".", 1)[0]
cls_name = parts[-2]
obj_name = '.'.join(parts[-2:]) if doc.objtype in ('class',):
ns['class'] = cls_name shortname = qualname
else: else:
mod_name, obj_name = '.'.join(parts[:-1]), parts[-1] shortname = qualname.rsplit(".", 1)[-1]
ns['fullname'] = name ns['fullname'] = name
ns['module'] = mod_name ns['module'] = modname
ns['objname'] = obj_name ns['objname'] = qualname
ns['name'] = parts[-1] ns['name'] = shortname
ns['objtype'] = doc.objtype ns['objtype'] = doc.objtype
ns['underline'] = len(name) * '=' ns['underline'] = len(name) * '='
return template.render(template_name, ns) if template_name:
return template.render(template_name, ns)
else:
return template.render(doc.objtype, ns)
def generate_autosummary_docs(sources: List[str], output_dir: str = None, def generate_autosummary_docs(sources: List[str], output_dir: str = None,
@ -249,18 +295,26 @@ def generate_autosummary_docs(sources: List[str], output_dir: str = None,
overwrite: bool = True) -> None: overwrite: bool = True) -> None:
if info: if info:
warnings.warn('info argument for generate_autosummary_docs() is deprecated.', warnings.warn('info argument for generate_autosummary_docs() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
_info = info _info = info
else: else:
_info = logger.info _info = logger.info
if warn: if warn:
warnings.warn('warn argument for generate_autosummary_docs() is deprecated.', warnings.warn('warn argument for generate_autosummary_docs() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
_warn = warn _warn = warn
else: else:
_warn = logger.warning _warn = logger.warning
if builder:
warnings.warn('builder argument for generate_autosummary_docs() is deprecated.',
RemovedInSphinx50Warning, stacklevel=2)
if template_dir:
warnings.warn('template_dir argument for generate_autosummary_docs() is deprecated.',
RemovedInSphinx50Warning, stacklevel=2)
showed_sources = list(sorted(sources)) showed_sources = list(sorted(sources))
if len(showed_sources) > 20: if len(showed_sources) > 20:
showed_sources = showed_sources[:10] + ['...'] + showed_sources[-10:] showed_sources = showed_sources[:10] + ['...'] + showed_sources[-10:]
@ -273,7 +327,7 @@ def generate_autosummary_docs(sources: List[str], output_dir: str = None,
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]
template = AutosummaryRenderer(builder, template_dir) template = AutosummaryRenderer(app)
# read # read
items = find_autosummary_in_files(sources) items = find_autosummary_in_files(sources)
@ -297,8 +351,12 @@ def generate_autosummary_docs(sources: List[str], output_dir: str = None,
_warn(__('[autosummary] failed to import %r: %s') % (entry.name, e)) _warn(__('[autosummary] failed to import %r: %s') % (entry.name, e))
continue continue
context = {}
if app:
context.update(app.config.autosummary_context)
content = generate_autosummary_content(name, obj, parent, template, entry.template, content = generate_autosummary_content(name, obj, parent, template, entry.template,
imported_members, app) imported_members, app, entry.recursive, context)
filename = os.path.join(path, name + suffix) filename = os.path.join(path, name + suffix)
if os.path.isfile(filename): if os.path.isfile(filename):
@ -320,8 +378,7 @@ def generate_autosummary_docs(sources: List[str], output_dir: str = None,
if new_files: if new_files:
generate_autosummary_docs(new_files, output_dir=output_dir, generate_autosummary_docs(new_files, output_dir=output_dir,
suffix=suffix, warn=warn, info=info, suffix=suffix, warn=warn, info=info,
base_path=base_path, builder=builder, base_path=base_path,
template_dir=template_dir,
imported_members=imported_members, app=app, imported_members=imported_members, app=app,
overwrite=overwrite) overwrite=overwrite)
@ -349,7 +406,7 @@ def find_autosummary_in_docstring(name: str, module: str = None, filename: str =
""" """
if module: if module:
warnings.warn('module argument for find_autosummary_in_docstring() is deprecated.', warnings.warn('module argument for find_autosummary_in_docstring() is deprecated.',
RemovedInSphinx50Warning) RemovedInSphinx50Warning, stacklevel=2)
try: try:
real_name, obj, parent, modname = import_by_name(name) real_name, obj, parent, modname = import_by_name(name)
@ -383,11 +440,13 @@ def find_autosummary_in_lines(lines: List[str], module: str = None, filename: st
module_re = re.compile( module_re = re.compile(
r'^\s*\.\.\s+(current)?module::\s*([a-zA-Z0-9_.]+)\s*$') r'^\s*\.\.\s+(current)?module::\s*([a-zA-Z0-9_.]+)\s*$')
autosummary_item_re = re.compile(r'^\s+(~?[_a-zA-Z][a-zA-Z0-9_.]*)\s*.*?') autosummary_item_re = re.compile(r'^\s+(~?[_a-zA-Z][a-zA-Z0-9_.]*)\s*.*?')
recursive_arg_re = re.compile(r'^\s+:recursive:\s*$')
toctree_arg_re = re.compile(r'^\s+:toctree:\s*(.*?)\s*$') toctree_arg_re = re.compile(r'^\s+:toctree:\s*(.*?)\s*$')
template_arg_re = re.compile(r'^\s+:template:\s*(.*?)\s*$') template_arg_re = re.compile(r'^\s+:template:\s*(.*?)\s*$')
documented = [] # type: List[AutosummaryEntry] documented = [] # type: List[AutosummaryEntry]
recursive = False
toctree = None # type: str toctree = None # type: str
template = None template = None
current_module = module current_module = module
@ -396,6 +455,11 @@ def find_autosummary_in_lines(lines: List[str], module: str = None, filename: st
for line in lines: for line in lines:
if in_autosummary: if in_autosummary:
m = recursive_arg_re.match(line)
if m:
recursive = True
continue
m = toctree_arg_re.match(line) m = toctree_arg_re.match(line)
if m: if m:
toctree = m.group(1) toctree = m.group(1)
@ -420,7 +484,7 @@ def find_autosummary_in_lines(lines: List[str], module: str = None, filename: st
if current_module and \ if current_module and \
not name.startswith(current_module + '.'): not name.startswith(current_module + '.'):
name = "%s.%s" % (current_module, name) name = "%s.%s" % (current_module, name)
documented.append(AutosummaryEntry(name, toctree, template)) documented.append(AutosummaryEntry(name, toctree, template, recursive))
continue continue
if not line.strip() or line.startswith(base_indent + " "): if not line.strip() or line.startswith(base_indent + " "):
@ -432,6 +496,7 @@ def find_autosummary_in_lines(lines: List[str], module: str = None, filename: st
if m: if m:
in_autosummary = True in_autosummary = True
base_indent = m.group(1) base_indent = m.group(1)
recursive = False
toctree = None toctree = None
template = None template = None
continue continue
@ -497,14 +562,18 @@ The format of the autosummary directive is documented in the
def main(argv: List[str] = sys.argv[1:]) -> None: def main(argv: List[str] = sys.argv[1:]) -> None:
sphinx.locale.setlocale(locale.LC_ALL, '') sphinx.locale.setlocale(locale.LC_ALL, '')
sphinx.locale.init_console(os.path.join(package_dir, 'locale'), 'sphinx') sphinx.locale.init_console(os.path.join(package_dir, 'locale'), 'sphinx')
translator, _ = sphinx.locale.init([], None)
app = DummyApplication() app = DummyApplication(translator)
logging.setup(app, sys.stdout, sys.stderr) # type: ignore logging.setup(app, sys.stdout, sys.stderr) # type: ignore
setup_documenters(app) setup_documenters(app)
args = get_parser().parse_args(argv) args = get_parser().parse_args(argv)
if args.templates:
app.config.templates_path.append(path.abspath(args.templates))
generate_autosummary_docs(args.source_file, args.output_dir, generate_autosummary_docs(args.source_file, args.output_dir,
'.' + args.suffix, '.' + args.suffix,
template_dir=args.templates,
imported_members=args.imported_members, imported_members=args.imported_members,
app=app) app=app)

View File

@ -8,7 +8,7 @@
.. automethod:: __init__ .. automethod:: __init__
{% if methods %} {% if methods %}
.. rubric:: Methods .. rubric:: {{ _('Methods') }}
.. autosummary:: .. autosummary::
{% for item in methods %} {% for item in methods %}
@ -19,7 +19,7 @@
{% block attributes %} {% block attributes %}
{% if attributes %} {% if attributes %}
.. rubric:: Attributes .. rubric:: {{ _('Attributes') }}
.. autosummary:: .. autosummary::
{% for item in attributes %} {% for item in attributes %}

View File

@ -15,7 +15,7 @@
{% block functions %} {% block functions %}
{% if functions %} {% if functions %}
.. rubric:: Functions .. rubric:: {{ _('Functions') }}
.. autosummary:: .. autosummary::
{% for item in functions %} {% for item in functions %}
@ -26,7 +26,7 @@
{% block classes %} {% block classes %}
{% if classes %} {% if classes %}
.. rubric:: Classes .. rubric:: {{ _('Classes') }}
.. autosummary:: .. autosummary::
{% for item in classes %} {% for item in classes %}
@ -37,7 +37,7 @@
{% block exceptions %} {% block exceptions %}
{% if exceptions %} {% if exceptions %}
.. rubric:: Exceptions .. rubric:: {{ _('Exceptions') }}
.. autosummary:: .. autosummary::
{% for item in exceptions %} {% for item in exceptions %}
@ -45,3 +45,16 @@
{%- endfor %} {%- endfor %}
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block modules %}
{% if modules %}
.. rubric:: Modules
.. autosummary::
:toctree:
:recursive:
{% for item in modules %}
{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}

View File

@ -47,7 +47,7 @@ doctestopt_re = re.compile(r'#\s*doctest:.+$', re.MULTILINE)
def doctest_encode(text: str, encoding: str) -> str: def doctest_encode(text: str, encoding: str) -> str:
warnings.warn('doctest_encode() is deprecated.', warnings.warn('doctest_encode() is deprecated.',
RemovedInSphinx40Warning) RemovedInSphinx40Warning, stacklevel=2)
return text return text

View File

@ -12,7 +12,6 @@
import posixpath import posixpath
import re import re
import subprocess import subprocess
from hashlib import sha1
from os import path from os import path
from subprocess import CalledProcessError, PIPE from subprocess import CalledProcessError, PIPE
from typing import Any, Dict, List, Tuple from typing import Any, Dict, List, Tuple
@ -25,7 +24,7 @@ import sphinx
from sphinx.application import Sphinx from sphinx.application import Sphinx
from sphinx.errors import SphinxError from sphinx.errors import SphinxError
from sphinx.locale import _, __ from sphinx.locale import _, __
from sphinx.util import logging from sphinx.util import logging, sha1
from sphinx.util.docutils import SphinxDirective, SphinxTranslator from sphinx.util.docutils import SphinxDirective, SphinxTranslator
from sphinx.util.fileutil import copy_asset from sphinx.util.fileutil import copy_asset
from sphinx.util.i18n import search_image_for_language from sphinx.util.i18n import search_image_for_language

View File

@ -9,6 +9,7 @@
""" """
import subprocess import subprocess
import sys
from subprocess import CalledProcessError, PIPE from subprocess import CalledProcessError, PIPE
from typing import Any, Dict from typing import Any, Dict
@ -74,8 +75,17 @@ class ImagemagickConverter(ImageConverter):
def setup(app: Sphinx) -> Dict[str, Any]: def setup(app: Sphinx) -> Dict[str, Any]:
app.add_post_transform(ImagemagickConverter) app.add_post_transform(ImagemagickConverter)
app.add_config_value('image_converter', 'convert', 'env') if sys.platform == 'win32':
app.add_config_value('image_converter_args', [], 'env') # On Windows, we use Imagemagik v7 by default to avoid the trouble for
# convert.exe bundled with Windows.
app.add_config_value('image_converter', 'magick', 'env')
app.add_config_value('image_converter_args', ['convert'], 'env')
else:
# On other platform, we use Imagemagick v6 by default. Especially,
# Debian/Ubuntu are still based of v6. So we can't use "magick" command
# for these platforms.
app.add_config_value('image_converter', 'convert', 'env')
app.add_config_value('image_converter_args', [], 'env')
return { return {
'version': 'builtin', 'version': 'builtin',

View File

@ -14,7 +14,6 @@ import shutil
import subprocess import subprocess
import sys import sys
import tempfile import tempfile
from hashlib import sha1
from os import path from os import path
from subprocess import CalledProcessError, PIPE from subprocess import CalledProcessError, PIPE
from typing import Any, Dict, List, Tuple from typing import Any, Dict, List, Tuple
@ -30,7 +29,7 @@ from sphinx.config import Config
from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_alias
from sphinx.errors import SphinxError from sphinx.errors import SphinxError
from sphinx.locale import _, __ from sphinx.locale import _, __
from sphinx.util import logging from sphinx.util import logging, sha1
from sphinx.util.math import get_node_equation_number, wrap_displaymath from sphinx.util.math import get_node_equation_number, wrap_displaymath
from sphinx.util.osutil import ensuredir from sphinx.util.osutil import ensuredir
from sphinx.util.png import read_png_depth, write_png_depth from sphinx.util.png import read_png_depth, write_png_depth

View File

@ -38,7 +38,6 @@ r"""
import builtins import builtins
import inspect import inspect
import re import re
from hashlib import md5
from importlib import import_module from importlib import import_module
from typing import Any, Dict, Iterable, List, Tuple from typing import Any, Dict, Iterable, List, Tuple
from typing import cast from typing import cast
@ -55,6 +54,7 @@ from sphinx.ext.graphviz import (
graphviz, figure_wrapper, graphviz, figure_wrapper,
render_dot_html, render_dot_latex, render_dot_texinfo render_dot_html, render_dot_latex, render_dot_texinfo
) )
from sphinx.util import md5
from sphinx.util.docutils import SphinxDirective from sphinx.util.docutils import SphinxDirective
from sphinx.writers.html import HTMLTranslator from sphinx.writers.html import HTMLTranslator
from sphinx.writers.latex import LaTeXTranslator from sphinx.writers.latex import LaTeXTranslator

View File

@ -168,11 +168,10 @@ class Config:
**If False**:: **If False**::
.. attribute:: attr1 .. attribute:: attr1
:type: int
Description of `attr1` Description of `attr1`
:type: int
napoleon_use_param : :obj:`bool` (Defaults to True) napoleon_use_param : :obj:`bool` (Defaults to True)
True to use a ``:param:`` role for each function parameter. False to True to use a ``:param:`` role for each function parameter. False to
use a single ``:parameters:`` role for all the parameters. use a single ``:parameters:`` role for all the parameters.

View File

@ -30,7 +30,9 @@ _google_section_regex = re.compile(r'^(\s|\w)+:\s*$')
_google_typed_arg_regex = re.compile(r'\s*(.+?)\s*\(\s*(.*[^\s]+)\s*\)') _google_typed_arg_regex = re.compile(r'\s*(.+?)\s*\(\s*(.*[^\s]+)\s*\)')
_numpy_section_regex = re.compile(r'^[=\-`:\'"~^_*+#<>]{2,}\s*$') _numpy_section_regex = re.compile(r'^[=\-`:\'"~^_*+#<>]{2,}\s*$')
_single_colon_regex = re.compile(r'(?<!:):(?!:)') _single_colon_regex = re.compile(r'(?<!:):(?!:)')
_xref_regex = re.compile(r'(:(?:[a-zA-Z0-9]+[\-_+:.])*[a-zA-Z0-9]+:`.+?`)') _xref_or_code_regex = re.compile(
r'((?::(?:[a-zA-Z0-9]+[\-_+:.])*[a-zA-Z0-9]+:`.+?`)|'
r'(?:``.+``))')
_bullet_list_regex = re.compile(r'^(\*|\+|\-)(\s+\S|\s*$)') _bullet_list_regex = re.compile(r'^(\*|\+|\-)(\s+\S|\s*$)')
_enumerated_list_regex = re.compile( _enumerated_list_regex = re.compile(
r'^(?P<paren>\()?' r'^(?P<paren>\()?'
@ -586,13 +588,12 @@ class GoogleDocstring:
lines.append('.. attribute:: ' + _name) lines.append('.. attribute:: ' + _name)
if self._opt and 'noindex' in self._opt: if self._opt and 'noindex' in self._opt:
lines.append(' :noindex:') lines.append(' :noindex:')
if _type:
lines.extend(self._indent([':type: %s' % _type], 3))
lines.append('') lines.append('')
fields = self._format_field('', '', _desc) fields = self._format_field('', '', _desc)
lines.extend(self._indent(fields, 3)) lines.extend(self._indent(fields, 3))
if _type:
lines.append('')
lines.extend(self._indent([':type: %s' % _type], 3))
lines.append('') lines.append('')
if self._config.napoleon_use_ivar: if self._config.napoleon_use_ivar:
lines.append('') lines.append('')
@ -728,7 +729,7 @@ class GoogleDocstring:
after_colon = [] after_colon = []
colon = '' colon = ''
found_colon = False found_colon = False
for i, source in enumerate(_xref_regex.split(line)): for i, source in enumerate(_xref_or_code_regex.split(line)):
if found_colon: if found_colon:
after_colon.append(source) after_colon.append(source)
else: else:

View File

@ -11,7 +11,7 @@
""" """
import collections import collections
from typing import Any, Iterable from typing import Any, Iterable, Optional
class peek_iter: class peek_iter:
@ -62,7 +62,7 @@ class peek_iter:
def __next__(self, n: int = None) -> Any: def __next__(self, n: int = None) -> Any:
return self.next(n) return self.next(n)
def _fillcache(self, n: int) -> None: def _fillcache(self, n: Optional[int]) -> None:
"""Cache `n` items. If `n` is 0 or None, then 1 item is cached.""" """Cache `n` items. If `n` is 0 or None, then 1 item is cached."""
if not n: if not n:
n = 1 n = 1
@ -123,7 +123,7 @@ class peek_iter:
result = [self._cache.popleft() for i in range(n)] result = [self._cache.popleft() for i in range(n)]
return result return result
def peek(self, n: int = None) -> Any: def peek(self, n: Optional[int] = None) -> Any:
"""Preview the next item or `n` items of the iterator. """Preview the next item or `n` items of the iterator.
The iterator is not advanced when peek is called. The iterator is not advanced when peek is called.
@ -220,7 +220,7 @@ class modify_iter(peek_iter):
'modifier must be callable') 'modifier must be callable')
super().__init__(*args) super().__init__(*args)
def _fillcache(self, n: int) -> None: def _fillcache(self, n: Optional[int]) -> None:
"""Cache `n` modified items. If `n` is 0 or None, 1 item is cached. """Cache `n` modified items. If `n` is 0 or None, 1 item is cached.
Each item returned by the iterator is passed through the Each item returned by the iterator is passed through the

View File

@ -105,7 +105,7 @@ class TodoDomain(Domain):
def process_todos(app: Sphinx, doctree: nodes.document) -> None: def process_todos(app: Sphinx, doctree: nodes.document) -> None:
warnings.warn('process_todos() is deprecated.', RemovedInSphinx40Warning) warnings.warn('process_todos() is deprecated.', RemovedInSphinx40Warning, stacklevel=2)
# collect all todos in the environment # collect all todos in the environment
# this is not done in the directive itself because it some transformations # this is not done in the directive itself because it some transformations
# must have already been run, e.g. substitutions # must have already been run, e.g. substitutions
@ -221,7 +221,8 @@ def process_todo_nodes(app: Sphinx, doctree: nodes.document, fromdocname: str) -
"""Replace all todolist nodes with a list of the collected todos. """Replace all todolist nodes with a list of the collected todos.
Augment each todo with a backlink to the original location. Augment each todo with a backlink to the original location.
""" """
warnings.warn('process_todo_nodes() is deprecated.', RemovedInSphinx40Warning) warnings.warn('process_todo_nodes() is deprecated.',
RemovedInSphinx40Warning, stacklevel=2)
domain = cast(TodoDomain, app.env.get_domain('todo')) domain = cast(TodoDomain, app.env.get_domain('todo'))
todos = sum(domain.todos.values(), []) # type: List[todo_node] todos = sum(domain.todos.values(), []) # type: List[todo_node]
@ -273,7 +274,7 @@ def process_todo_nodes(app: Sphinx, doctree: nodes.document, fromdocname: str) -
def purge_todos(app: Sphinx, env: BuildEnvironment, docname: str) -> None: def purge_todos(app: Sphinx, env: BuildEnvironment, docname: str) -> None:
warnings.warn('purge_todos() is deprecated.', RemovedInSphinx40Warning) warnings.warn('purge_todos() is deprecated.', RemovedInSphinx40Warning, stacklevel=2)
if not hasattr(env, 'todo_all_todos'): if not hasattr(env, 'todo_all_todos'):
return return
env.todo_all_todos = [todo for todo in env.todo_all_todos # type: ignore env.todo_all_todos = [todo for todo in env.todo_all_todos # type: ignore
@ -282,7 +283,7 @@ def purge_todos(app: Sphinx, env: BuildEnvironment, docname: str) -> None:
def merge_info(app: Sphinx, env: BuildEnvironment, docnames: Iterable[str], def merge_info(app: Sphinx, env: BuildEnvironment, docnames: Iterable[str],
other: BuildEnvironment) -> None: other: BuildEnvironment) -> None:
warnings.warn('merge_info() is deprecated.', RemovedInSphinx40Warning) warnings.warn('merge_info() is deprecated.', RemovedInSphinx40Warning, stacklevel=2)
if not hasattr(other, 'todo_all_todos'): if not hasattr(other, 'todo_all_todos'):
return return
if not hasattr(env, 'todo_all_todos'): if not hasattr(env, 'todo_all_todos'):

View File

@ -131,8 +131,10 @@ def env_merge_info(app: Sphinx, env: BuildEnvironment, docnames: Iterable[str],
def missing_reference(app: Sphinx, env: BuildEnvironment, node: Element, contnode: Node def missing_reference(app: Sphinx, env: BuildEnvironment, node: Element, contnode: Node
) -> Node: ) -> Node:
# resolve our "viewcode" reference nodes -- they need special treatment if app.builder.format != 'html':
if node['reftype'] == 'viewcode': return None
elif node['reftype'] == 'viewcode':
# resolve our "viewcode" reference nodes -- they need special treatment
return make_refnode(app.builder, node['refdoc'], node['reftarget'], return make_refnode(app.builder, node['refdoc'], node['reftarget'],
node['refid'], contnode) node['refid'], contnode)

View File

@ -10,7 +10,6 @@
import codecs import codecs
import warnings import warnings
from typing import Any, List from typing import Any, List
from typing import Type # for python3.5.1
from docutils import nodes from docutils import nodes
from docutils.core import Publisher from docutils.core import Publisher
@ -40,6 +39,7 @@ from sphinx.versioning import UIDTransform
if False: if False:
# For type annotation # For type annotation
from typing import Type # for python3.5.1
from sphinx.application import Sphinx from sphinx.application import Sphinx
@ -80,7 +80,7 @@ class SphinxBaseReader(standalone.Reader):
self._app = app # hold application object only for compatibility self._app = app # hold application object only for compatibility
self._env = app.env self._env = app.env
def get_transforms(self) -> List[Type[Transform]]: def get_transforms(self) -> List["Type[Transform]"]:
transforms = super().get_transforms() + self.transforms transforms = super().get_transforms() + self.transforms
# remove transforms which is not needed for Sphinx # remove transforms which is not needed for Sphinx

View File

@ -12,12 +12,12 @@ import gettext
import locale import locale
from collections import UserString, defaultdict from collections import UserString, defaultdict
from gettext import NullTranslations from gettext import NullTranslations
from typing import Any, Callable, Dict, Iterable, List, Tuple, Union from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple, Union
class _TranslationProxy(UserString): class _TranslationProxy(UserString):
""" """
Class for proxy strings from gettext translations. This is a helper for the Class for proxy strings from gettext translations. This is a helper for the
lazy_* functions from this module. lazy_* functions from this module.
The proxy implementation attempts to be as complete as possible, so that The proxy implementation attempts to be as complete as possible, so that
@ -109,7 +109,7 @@ translators = defaultdict(NullTranslations) # type: Dict[Tuple[str, str], NullT
def init(locale_dirs: List[str], language: str, def init(locale_dirs: List[str], language: str,
catalog: str = 'sphinx', namespace: str = 'general') -> Tuple[NullTranslations, bool]: catalog: str = 'sphinx', namespace: str = 'general') -> Tuple[NullTranslations, bool]:
"""Look for message catalogs in `locale_dirs` and *ensure* that there is at """Look for message catalogs in `locale_dirs` and *ensure* that there is at
least a NullTranslations catalog set in `translators`. If called multiple least a NullTranslations catalog set in `translators`. If called multiple
times or if several ``.mo`` files are found, their contents are merged times or if several ``.mo`` files are found, their contents are merged
together (thus making ``init`` reentrant). together (thus making ``init`` reentrant).
""" """
@ -173,7 +173,7 @@ def init_console(locale_dir: str, catalog: str) -> Tuple[NullTranslations, bool]
""" """
try: try:
# encoding is ignored # encoding is ignored
language, _ = locale.getlocale(locale.LC_MESSAGES) language, _ = locale.getlocale(locale.LC_MESSAGES) # type: Tuple[Optional[str], Any]
except AttributeError: except AttributeError:
# LC_MESSAGES is not always defined. Fallback to the default language # LC_MESSAGES is not always defined. Fallback to the default language
# in case it is not. # in case it is not.

View File

@ -41,7 +41,7 @@ msgstr "تشغيل Sphinx v%s"
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1131,7 +1131,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1168,7 +1168,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1455,7 +1455,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1484,7 +1484,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -40,7 +40,7 @@ msgstr ""
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1130,7 +1130,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1167,7 +1167,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1454,7 +1454,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1483,7 +1483,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -41,7 +41,7 @@ msgstr ""
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1131,7 +1131,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1168,7 +1168,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1455,7 +1455,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1484,7 +1484,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -41,7 +41,7 @@ msgstr ""
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1131,7 +1131,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1168,7 +1168,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1455,7 +1455,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1484,7 +1484,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -41,7 +41,7 @@ msgstr ""
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1131,7 +1131,7 @@ msgstr "Rusachoj kamulunem:"
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1168,7 +1168,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1455,7 +1455,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1484,7 +1484,7 @@ msgstr "Ruch'ab'äl samaj"
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -42,7 +42,7 @@ msgstr ""
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1132,7 +1132,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1169,7 +1169,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1456,7 +1456,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1485,7 +1485,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -42,7 +42,7 @@ msgstr ""
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1132,7 +1132,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1169,7 +1169,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1456,7 +1456,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1485,7 +1485,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -43,7 +43,7 @@ msgstr "Kører Sphinx v%s"
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1133,7 +1133,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1170,7 +1170,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1457,7 +1457,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1486,7 +1486,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -44,7 +44,7 @@ msgstr "Sphinx v%s in Verwendung"
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1134,7 +1134,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1171,7 +1171,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1458,7 +1458,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1487,7 +1487,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -42,7 +42,7 @@ msgstr "Εκτέλεση Sphinx έκδοση %s"
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1132,7 +1132,7 @@ msgstr "Σφάλμα αναδρομής:"
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "Αυτό μπορεί να συμβεί με πολύ μεγάλα ή βαθιά εμφωλιασμένα αρχεία πηγής. Μπορείτε προσεκτικά να αυξήσετε την προεπιλεγμένη τιμή αναδρομικότητας Python στο conf.py με π.χ.:" msgstr "Αυτό μπορεί να συμβεί με πολύ μεγάλα ή βαθιά εμφωλιασμένα αρχεία πηγής. Μπορείτε προσεκτικά να αυξήσετε την προεπιλεγμένη τιμή αναδρομικότητας Python στο conf.py με π.χ.:"
@ -1169,7 +1169,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1456,7 +1456,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1485,7 +1485,7 @@ msgstr "Γλώσσα έργου"
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300
@ -2447,7 +2447,7 @@ msgstr "τοποθέτηση βιβλιογραφίας δομοστοιχείο
msgid "" msgid ""
"interpret module paths according to PEP-0420 implicit namespaces " "interpret module paths according to PEP-0420 implicit namespaces "
"specification" "specification"
msgstr "ερμηνεία μονοπατιών δομοστοιχείων σύμφωνα με την προδιαγραφή POP-0420 αυτονόητων namespaces" msgstr "ερμηνεία μονοπατιών δομοστοιχείων σύμφωνα με την προδιαγραφή POP-0420 αυτονόητων namespaces"
#: sphinx/ext/apidoc.py:411 #: sphinx/ext/apidoc.py:411
msgid "file suffix (default: rst)" msgid "file suffix (default: rst)"

View File

@ -41,7 +41,7 @@ msgstr ""
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1131,7 +1131,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1168,7 +1168,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1455,7 +1455,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1484,7 +1484,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -47,7 +47,7 @@ msgstr "Ejecutando Sphinx v%s"
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "Por razones de seguridad, el modo paralelo está deshabilitado en macOS y python3.8 y superior. Para más detalles, lea https://github.com/sphinx-doc/sphinx/issues/6803" msgstr "Por razones de seguridad, el modo paralelo está deshabilitado en macOS y python3.8 y superior. Para más detalles, lea https://github.com/sphinx-doc/sphinx/issues/6803"
@ -154,7 +154,7 @@ msgid ""
"the %s extension does not declare if it is safe for parallel reading, " "the %s extension does not declare if it is safe for parallel reading, "
"assuming it isn't - please ask the extension author to check and make it " "assuming it isn't - please ask the extension author to check and make it "
"explicit" "explicit"
msgstr "la extensión de %s no declara si es seguro para la lectura en paralelo, asumiendo que no es - consulte con el autor de la extensión para comprobar y hacer explícito" msgstr "la extensión de %s no declara si es seguro para la lectura en paralelo, asumiendo que no es - consulte con el autor de la extensión para comprobar y hacer explícito"
#: sphinx/application.py:1128 #: sphinx/application.py:1128
#, python-format #, python-format
@ -1137,7 +1137,7 @@ msgstr "Error de recursión:"
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "Esto puede suceder con archivos fuente muy grandes o profundamente anidados. Puede aumentar cuidadosamente el límite de recursión de Python predeterminado de 1000 en el archivo conf.py con, por ejemplo:" msgstr "Esto puede suceder con archivos fuente muy grandes o profundamente anidados. Puede aumentar cuidadosamente el límite de recursión de Python predeterminado de 1000 en el archivo conf.py con, por ejemplo:"
@ -1174,7 +1174,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1184,7 +1184,7 @@ msgid ""
"\n" "\n"
"By default, everything that is outdated is built. Output only for selected\n" "By default, everything that is outdated is built. Output only for selected\n"
"files can be built by specifying individual filenames.\n" "files can be built by specifying individual filenames.\n"
msgstr "\nGenerar documentación a partir de archivos fuente.\n\nsphinx-build genera documentación de los archivos en SOURCEDIR y la coloca\nen OUTPUTDIR. Busca el archivo 'conf.py' en SOURCEDIR para los ajustes de la \nconfiguración. La herramienta 'sphinx-quickstart' puede usarse para generar archivos de plantilla,\nincluyendo el archivo 'conf.py'\n\nsphinx-build puede crear documentación en diferentes formatos. Un formato es\nseleccionado especificando el nombre del constructor en la línea de comando; por defecto es\nHTML. Los constructores también pueden realizar otras tareas relacionadas con la\ndocumentación.\n\nPor defecto, todo lo que está desactualizado está construido. Salida solo para los archivos\nseleccionados se pueden construir especificando nombres de archivo individuales.\n" msgstr "\nGenerar documentación a partir de archivos fuente.\n\nsphinx-build genera documentación de los archivos en SOURCEDIR y la coloca\nen OUTPUTDIR. Busca el archivo 'conf.py' en SOURCEDIR para los ajustes de la \nconfiguración. La herramienta 'sphinx-quickstart' puede usarse para generar archivos de plantilla,\nincluyendo el archivo 'conf.py'\n\nsphinx-build puede crear documentación en diferentes formatos. Un formato es\nseleccionado especificando el nombre del constructor en la línea de comando; por defecto es\nHTML. Los constructores también pueden realizar otras tareas relacionadas con la\ndocumentación.\n\nPor defecto, todo lo que está desactualizado está construido. Salida solo para los archivos\nseleccionados se pueden construir especificando nombres de archivo individuales.\n"
#: sphinx/cmd/build.py:122 #: sphinx/cmd/build.py:122
msgid "path to documentation source files" msgid "path to documentation source files"
@ -1461,7 +1461,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "Sphinx tiene la noción de una \"version\" y un \"release\" para el\nsoftware. Cada versión puede tener múltiples versiones. Por ejemplo, para\nPython la versión es algo así como 2.5 o 3.0, mientras que el lanzamiento es\nalgo así como 2.5.1 o 3.0a1. Si no necesita esta estructura dual,\nsolo establezca ambos en el mismo valor." msgstr "Sphinx tiene la noción de una \"version\" y un \"release\" para el\nsoftware. Cada versión puede tener múltiples versiones. Por ejemplo, para\nPython la versión es algo así como 2.5 o 3.0, mientras que el lanzamiento es\nalgo así como 2.5.1 o 3.0a1. Si no necesita esta estructura dual,\nsolo establezca ambos en el mismo valor."
@ -1490,7 +1490,7 @@ msgstr "Lenguaje del proyecto"
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "El sufijo del nombre de archivo para los archivos de origen. Comúnmente, esto es \".txt\"\no \".rst\". Solo los archivos con este sufijo se consideran documentos." msgstr "El sufijo del nombre de archivo para los archivos de origen. Comúnmente, esto es \".txt\"\no \".rst\". Solo los archivos con este sufijo se consideran documentos."
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300
@ -2617,7 +2617,7 @@ msgstr "[gráfica]"
#: sphinx/ext/imgconverter.py:41 sphinx/ext/imgconverter.py:65 #: sphinx/ext/imgconverter.py:41 sphinx/ext/imgconverter.py:65
#, python-format #, python-format
msgid "convert command %r cannot be run, check the image_converter setting" msgid "convert command %r cannot be run, check the image_converter setting"
msgstr "el comando convert %r no puede ejecutar, compruebe el valor de configuración image_converter" msgstr "el comando convert %r no puede ejecutar, compruebe el valor de configuración image_converter"
#: sphinx/ext/imgconverter.py:46 sphinx/ext/imgconverter.py:70 #: sphinx/ext/imgconverter.py:46 sphinx/ext/imgconverter.py:70
#, python-format #, python-format

View File

@ -44,7 +44,7 @@ msgstr "Sphinx v%s käitamine"
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1134,7 +1134,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1171,7 +1171,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1458,7 +1458,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1487,7 +1487,7 @@ msgstr "Projekti keel"
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -42,7 +42,7 @@ msgstr ""
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1132,7 +1132,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1169,7 +1169,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1456,7 +1456,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1485,7 +1485,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -40,7 +40,7 @@ msgstr ""
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1130,7 +1130,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1167,7 +1167,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1454,7 +1454,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1483,7 +1483,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -41,7 +41,7 @@ msgstr ""
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1131,7 +1131,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1168,7 +1168,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1455,7 +1455,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1484,7 +1484,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -61,7 +61,7 @@ msgstr "Sphinx v%s en cours d'exécution"
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -321,7 +321,7 @@ msgstr "Nom d'évènement inconnu : %s"
msgid "" msgid ""
"The %s extension is required by needs_extensions settings, but it is not " "The %s extension is required by needs_extensions settings, but it is not "
"loaded." "loaded."
msgstr "L'extension %s est exigée par le paramètre needs_extensions, mais n'est pas chargée." msgstr "L'extension %s est exigée par le paramètre needs_extensions, mais n'est pas chargée."
#: sphinx/extension.py:56 #: sphinx/extension.py:56
#, python-format #, python-format
@ -1151,7 +1151,7 @@ msgstr "Erreur de récursion :"
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "Cela peut se produire avec des fichiers sources très volumineux ou profondément imbriqués. Vous pouvez soigneusement augmenter la limite de récursivité par défaut de Python de 1000 dans conf.py avec p. ex. :" msgstr "Cela peut se produire avec des fichiers sources très volumineux ou profondément imbriqués. Vous pouvez soigneusement augmenter la limite de récursivité par défaut de Python de 1000 dans conf.py avec p. ex. :"
@ -1188,7 +1188,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1475,7 +1475,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1504,7 +1504,7 @@ msgstr "Langue du projet"
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300
@ -2611,7 +2611,7 @@ msgstr "dot a terminé avec une erreur :\n[stderr]\n%r\n[stdout]\n%r"
#: sphinx/ext/graphviz.py:269 #: sphinx/ext/graphviz.py:269
#, python-format #, python-format
msgid "graphviz_output_format must be one of 'png', 'svg', but is %r" msgid "graphviz_output_format must be one of 'png', 'svg', but is %r"
msgstr "graphviz_output_format doit être « png » ou « svg », mais est %r" msgstr "graphviz_output_format doit être « png » ou « svg », mais est %r"
#: sphinx/ext/graphviz.py:273 sphinx/ext/graphviz.py:324 #: sphinx/ext/graphviz.py:273 sphinx/ext/graphviz.py:324
#: sphinx/ext/graphviz.py:361 #: sphinx/ext/graphviz.py:361

View File

@ -41,7 +41,7 @@ msgstr ""
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1131,7 +1131,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1168,7 +1168,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1455,7 +1455,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1484,7 +1484,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -44,7 +44,7 @@ msgstr "स्फिंक्स %s संस्करण चल रहा ह
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "सुरक्षा कारण वर्ष macOS तथा python 3.8 और अधिक, के साथ समानांतर कार्य शैली कि सुविधा उपलब्ध नहीं हैं | अधिक जानकारी के लिए, कृपया \"https://github.com/sphinx-doc/sphinx/issues/6803\" पढ़े |" msgstr "सुरक्षा कारण वर्ष macOS तथा python 3.8 और अधिक, के साथ समानांतर कार्य शैली कि सुविधा उपलब्ध नहीं हैं | अधिक जानकारी के लिए, कृपया \"https://github.com/sphinx-doc/sphinx/issues/6803\" पढ़े |"
@ -1134,7 +1134,7 @@ msgstr "पुनरावर्तन त्रुटि:"
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "ऐसा बहुत बड़ी अथवा गहरे स्तर तक गई स्रोत फाइलों से संभव है. आप स्वतः मानक पाइथन पुनरावर्तन सीमा 1000 को conf.py में बाधा सकते हैं. जैसे कि:" msgstr "ऐसा बहुत बड़ी अथवा गहरे स्तर तक गई स्रोत फाइलों से संभव है. आप स्वतः मानक पाइथन पुनरावर्तन सीमा 1000 को conf.py में बाधा सकते हैं. जैसे कि:"
@ -1171,7 +1171,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1458,7 +1458,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "स्फिंक्स सॉफ्टवेयर के लिए संस्करण और आवृत्ति को मान्यता देता है.\nहर संस्करण की कई आवृत्तियाँ हो सकती हैं. उदाहरण के लिए,\nपाइथन संस्करण 2.5 अथवा 3.0 आदि हैं, और आवृत्ति\n2.5.1 अथवा 3.0a1 आदि हैं. यदि आपको इसे दो स्तर पर रखना नहीं चाहिए\nतो दोनों मान एक ही रख दें." msgstr "स्फिंक्स सॉफ्टवेयर के लिए संस्करण और आवृत्ति को मान्यता देता है.\nहर संस्करण की कई आवृत्तियाँ हो सकती हैं. उदाहरण के लिए,\nपाइथन संस्करण 2.5 अथवा 3.0 आदि हैं, और आवृत्ति\n2.5.1 अथवा 3.0a1 आदि हैं. यदि आपको इसे दो स्तर पर रखना नहीं चाहिए\nतो दोनों मान एक ही रख दें."
@ -1487,7 +1487,7 @@ msgstr "परियोजना की भाषा"
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300
@ -2789,7 +2789,7 @@ msgstr "स्वतः-प्रभाग %s के लिए हस्ता
msgid "" msgid ""
"__all__ should be a list of strings, not %r (in module %s) -- ignoring " "__all__ should be a list of strings, not %r (in module %s) -- ignoring "
"__all__" "__all__"
msgstr "__all__ अंतिम अक्षरमाला होनी चाहिए, न कि %r (%s प्रभाग में) -- __all__ की उपेक्षा की जाएगी" msgstr "__all__ अंतिम अक्षरमाला होनी चाहिए, न कि %r (%s प्रभाग में) -- __all__ की उपेक्षा की जाएगी"
#: sphinx/ext/autodoc/__init__.py:852 #: sphinx/ext/autodoc/__init__.py:852
#, python-format #, python-format

View File

@ -40,7 +40,7 @@ msgstr ""
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1130,7 +1130,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1167,7 +1167,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1454,7 +1454,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1483,7 +1483,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -41,7 +41,7 @@ msgstr "Izrada pomoću Sphinx v%s"
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -449,7 +449,7 @@ msgstr "%s proširenje traži Sphinx verzije v%s; stoga projekt ne može biti iz
msgid "" msgid ""
"extension %r returned an unsupported object from its setup() function; it " "extension %r returned an unsupported object from its setup() function; it "
"should return None or a metadata dictionary" "should return None or a metadata dictionary"
msgstr "proširenje %r vratio je nepodržan objekt iz setup() funkcije; rezultat treba biti None ili riječnik metapodataka" msgstr "proširenje %r vratio je nepodržan objekt iz setup() funkcije; rezultat treba biti None ili riječnik metapodataka"
#: sphinx/roles.py:221 sphinx/roles.py:271 #: sphinx/roles.py:221 sphinx/roles.py:271
#, python-format #, python-format
@ -1131,7 +1131,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1168,7 +1168,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1455,7 +1455,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1484,7 +1484,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -45,7 +45,7 @@ msgstr "Sphinx %s verzió futtatása"
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1135,7 +1135,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1172,7 +1172,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1459,7 +1459,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1488,7 +1488,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -45,9 +45,9 @@ msgstr "Menjalankan Sphinx v%s"
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "Untuk alasan keamanan, mode paralel dinonaktifkan di macOS dan python3.8 dan di atasnya. Untuk detail lebih lanjut, silakan baca https://github.com/sphinx-doc/sphinx/issues/6803" msgstr "Untuk alasan keamanan, mode paralel dinonaktifkan di macOS dan python3.8 dan di atasnya. Untuk detail lebih lanjut, silakan baca https://github.com/sphinx-doc/sphinx/issues/6803"
#: sphinx/application.py:226 #: sphinx/application.py:226
#, python-format #, python-format
@ -1135,7 +1135,7 @@ msgstr "Kesalahan rekursi:"
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "Hal ini dapat terjadi dengan berkas sumber yang besar atau sangat dalam bertingkat. Anda dapat secara hati-hati meningkatkan batas standar recursi Python dari 1000 di conf.py contohnya:" msgstr "Hal ini dapat terjadi dengan berkas sumber yang besar atau sangat dalam bertingkat. Anda dapat secara hati-hati meningkatkan batas standar recursi Python dari 1000 di conf.py contohnya:"
@ -1172,7 +1172,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1182,7 +1182,7 @@ msgid ""
"\n" "\n"
"By default, everything that is outdated is built. Output only for selected\n" "By default, everything that is outdated is built. Output only for selected\n"
"files can be built by specifying individual filenames.\n" "files can be built by specifying individual filenames.\n"
msgstr "\nMenghasilkan dokumentasi ari berkas sumber.\n\nsphinx-build menghasilkan dokumentasi dari berkas-berkas di SOURCEDIR dan menyimpannya\ndi OUTPUTDIR. Program tersebut mencari berkas 'conf.py' di SOURCEDIR untuk pengaturan\nkonfigurasinya. Alat 'sphinx-quickstart' dapat digunakan untuk menghasilkan berkas templat,\ntermasuk 'conf.py'\n\nsphinx-build dapat membuat dokumentasi dalam beragam format. Sebuah format\ndipilih berdasarkan nama builder pada command line; standarnya\nHTML. Builders pun dapat menjalankan tugas lainnya berhubungan dengan pemrosesan\ndocumentasi.\n\nSecara umum, semua yang usang akan dibuat. Output hanya untuk berkas\npilihan dapat dibuat dengan menentukan berkas satuan.\n" msgstr "\nMenghasilkan dokumentasi ari berkas sumber.\n\nsphinx-build menghasilkan dokumentasi dari berkas-berkas di SOURCEDIR dan menyimpannya\ndi OUTPUTDIR. Program tersebut mencari berkas 'conf.py' di SOURCEDIR untuk pengaturan\nkonfigurasinya. Alat 'sphinx-quickstart' dapat digunakan untuk menghasilkan berkas templat,\ntermasuk 'conf.py'\n\nsphinx-build dapat membuat dokumentasi dalam beragam format. Sebuah format\ndipilih berdasarkan nama builder pada command line; standarnya\nHTML. Builders pun dapat menjalankan tugas lainnya berhubungan dengan pemrosesan\ndocumentasi.\n\nSecara umum, semua yang usang akan dibuat. Output hanya untuk berkas\npilihan dapat dibuat dengan menentukan berkas satuan.\n"
#: sphinx/cmd/build.py:122 #: sphinx/cmd/build.py:122
msgid "path to documentation source files" msgid "path to documentation source files"
@ -1459,7 +1459,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1488,7 +1488,7 @@ msgstr "Bahasa proyek"
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -45,7 +45,7 @@ msgstr ""
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "" msgstr ""
@ -1135,7 +1135,7 @@ msgstr ""
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "" msgstr ""
@ -1172,7 +1172,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1459,7 +1459,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "" msgstr ""
@ -1488,7 +1488,7 @@ msgstr ""
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "" msgstr ""
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

View File

@ -55,7 +55,7 @@ msgstr "Sphinx v%s を実行中"
#: sphinx/application.py:202 #: sphinx/application.py:202
msgid "" msgid ""
"For security reason, parallel mode is disabled on macOS and python3.8 and " "For security reason, parallel mode is disabled on macOS and python3.8 and "
"above. For more details, please read https://github.com/sphinx-" "above. For more details, please read https://github.com/sphinx-"
"doc/sphinx/issues/6803" "doc/sphinx/issues/6803"
msgstr "セキュリティ上の理由から、macOSおよびpython3.8以降では並列モードが無効になっています。 詳細については https://github.com/sphinx-doc/sphinx/issues/6803 をご覧ください。" msgstr "セキュリティ上の理由から、macOSおよびpython3.8以降では並列モードが無効になっています。 詳細については https://github.com/sphinx-doc/sphinx/issues/6803 をご覧ください。"
@ -1145,7 +1145,7 @@ msgstr "再起呼び出しエラー:"
#: sphinx/cmd/build.py:62 #: sphinx/cmd/build.py:62
msgid "" msgid ""
"This can happen with very large or deeply nested source files. You can " "This can happen with very large or deeply nested source files. You can "
"carefully increase the default Python recursion limit of 1000 in conf.py " "carefully increase the default Python recursion limit of 1000 in conf.py "
"with e.g.:" "with e.g.:"
msgstr "この例外エラーは、非常に大きな、または深くネストされたソースファイルで発生する可能性があります。再帰処理の呼び出しの上限値 1000 は conf.py で変更できますが、慎重に行ってください。" msgstr "この例外エラーは、非常に大きな、または深くネストされたソースファイルで発生する可能性があります。再帰処理の呼び出しの上限値 1000 は conf.py で変更できますが、慎重に行ってください。"
@ -1182,7 +1182,7 @@ msgid ""
"\n" "\n"
"sphinx-build generates documentation from the files in SOURCEDIR and places it\n" "sphinx-build generates documentation from the files in SOURCEDIR and places it\n"
"in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n" "in OUTPUTDIR. It looks for 'conf.py' in SOURCEDIR for the configuration\n"
"settings. The 'sphinx-quickstart' tool may be used to generate template files,\n" "settings. The 'sphinx-quickstart' tool may be used to generate template files,\n"
"including 'conf.py'\n" "including 'conf.py'\n"
"\n" "\n"
"sphinx-build can create documentation in different formats. A format is\n" "sphinx-build can create documentation in different formats. A format is\n"
@ -1469,7 +1469,7 @@ msgid ""
"Sphinx has the notion of a \"version\" and a \"release\" for the\n" "Sphinx has the notion of a \"version\" and a \"release\" for the\n"
"software. Each version can have multiple releases. For example, for\n" "software. Each version can have multiple releases. For example, for\n"
"Python the version is something like 2.5 or 3.0, while the release is\n" "Python the version is something like 2.5 or 3.0, while the release is\n"
"something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n" "something like 2.5.1 or 3.0a1. If you don't need this dual structure,\n"
"just set both to the same value." "just set both to the same value."
msgstr "Sphinx には、ソフトウェアに対して \"バージョン\" と \"リリース\" という概念が\nあります。各バージョンは複数のリリースを持つことができます。\n例えば、Python だとバージョンが 2.5 や 3.0 のように分かれているように、\nリリースも 2.5.1 や 3.0a1 のように分けて持つことができます。もしこのような多重構成が必要ない場合は、\n両方を同じ値に設定するだけです。" msgstr "Sphinx には、ソフトウェアに対して \"バージョン\" と \"リリース\" という概念が\nあります。各バージョンは複数のリリースを持つことができます。\n例えば、Python だとバージョンが 2.5 や 3.0 のように分かれているように、\nリリースも 2.5.1 や 3.0a1 のように分けて持つことができます。もしこのような多重構成が必要ない場合は、\n両方を同じ値に設定するだけです。"
@ -1498,7 +1498,7 @@ msgstr "プロジェクトの言語"
#: sphinx/cmd/quickstart.py:298 #: sphinx/cmd/quickstart.py:298
msgid "" msgid ""
"The file name suffix for source files. Commonly, this is either \".txt\"\n" "The file name suffix for source files. Commonly, this is either \".txt\"\n"
"or \".rst\". Only files with this suffix are considered documents." "or \".rst\". Only files with this suffix are considered documents."
msgstr "拡張子の名前はソースファイルに使います。\n通常は \".txt\" または \".rst\" です。これらの拡張子を持つファイルのみがドキュメントと見なされます。" msgstr "拡張子の名前はソースファイルに使います。\n通常は \".txt\" または \".rst\" です。これらの拡張子を持つファイルのみがドキュメントと見なされます。"
#: sphinx/cmd/quickstart.py:300 #: sphinx/cmd/quickstart.py:300

Some files were not shown because too many files have changed in this diff Show More