mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '3.x' into preprocess-other-sections
This commit is contained in:
5
.github/ISSUE_TEMPLATE/config.yml
vendored
5
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -2,5 +2,8 @@
|
||||
blank_issues_enabled: false # default: true
|
||||
contact_links:
|
||||
- name: Question
|
||||
url: https://stackoverflow.com/questions/tagged/python-sphinx
|
||||
about: For Q&A purpose, please use Stackoverflow with the tag python-sphinx
|
||||
- name: Discussion
|
||||
url: https://groups.google.com/forum/#!forum/sphinx-users
|
||||
about: For Q&A purpose, please use sphinx-users mailing list.
|
||||
about: For general discussion, please use sphinx-users mailing list.
|
||||
|
||||
95
CHANGES
95
CHANGES
@@ -1,4 +1,4 @@
|
||||
Release 3.2.0 (in development)
|
||||
Release 3.3.0 (in development)
|
||||
==============================
|
||||
|
||||
Dependencies
|
||||
@@ -10,6 +10,69 @@ Incompatible changes
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
Features added
|
||||
--------------
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* #8085: i18n: Add support for having single text domain
|
||||
* #8093: The highlight warning has wrong location in some builders (LaTeX,
|
||||
singlehtml and so on)
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
Release 3.2.2 (in development)
|
||||
==============================
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Incompatible changes
|
||||
--------------------
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
Features added
|
||||
--------------
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
Release 3.2.1 (released Aug 14, 2020)
|
||||
=====================================
|
||||
|
||||
Features added
|
||||
--------------
|
||||
|
||||
* #8095: napoleon: Add :confval:`napoleon_preprocess_types` to enable the type
|
||||
preprocessor for numpy style docstrings
|
||||
* #8114: C and C++, parse function attributes after parameters and qualifiers.
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* #8074: napoleon: Crashes during processing C-ext module
|
||||
* #8088: napoleon: "Inline literal start-string without end-string" warning in
|
||||
Numpy style Parameters section
|
||||
* #8084: autodoc: KeyError is raised on documenting an attribute of the broken
|
||||
class
|
||||
* #8091: autodoc: AttributeError is raised on documenting an attribute on Python
|
||||
3.5.2
|
||||
* #8099: autodoc: NameError is raised when target code uses ``TYPE_CHECKING``
|
||||
* C++, fix parsing of template template paramters, broken by the fix of #7944
|
||||
|
||||
Release 3.2.0 (released Aug 08, 2020)
|
||||
=====================================
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
* ``sphinx.ext.autodoc.members_set_option()``
|
||||
* ``sphinx.ext.autodoc.merge_special_members_option()``
|
||||
* ``sphinx.writers.texinfo.TexinfoWriter.desc``
|
||||
@@ -56,6 +119,7 @@ Features added
|
||||
:confval:`c_warn_on_allowed_pre_v3`` to ``True``.
|
||||
The functionality is immediately deprecated.
|
||||
* #7999: C, add support for named variadic macro arguments.
|
||||
* #8071: Allow to suppress "self referenced toctrees" warning
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
@@ -71,6 +135,8 @@ Bugs fixed
|
||||
when ``:inherited-members:`` option given
|
||||
* #8032: autodoc: A type hint for the instance variable defined at parent class
|
||||
is not shown in the document of the derived class
|
||||
* #8041: autodoc: An annotated instance variable on super class is not
|
||||
documented when derived class has other annotated instance variables
|
||||
* #7839: autosummary: cannot handle umlauts in function names
|
||||
* #7865: autosummary: Failed to extract summary line when abbreviations found
|
||||
* #7866: autosummary: Failed to extract correct summary line when docstring
|
||||
@@ -80,6 +146,8 @@ Bugs fixed
|
||||
module has submodules
|
||||
* #4258: napoleon: decorated special methods are not shown
|
||||
* #7799: napoleon: parameters are not escaped for combined params in numpydoc
|
||||
* #7780: napoleon: multiple paramaters declaration in numpydoc was wrongly
|
||||
recognized when napoleon_use_params=True
|
||||
* #7715: LaTeX: ``numfig_secnum_depth > 1`` leads to wrong figure links
|
||||
* #7846: html theme: XML-invalid files were generated
|
||||
* #7894: gettext: Wrong source info is shown when using rst_epilog
|
||||
@@ -106,34 +174,9 @@ Bugs fixed
|
||||
* #7986: CSS: make "highlight" selector more robust
|
||||
* #7944: C++, parse non-type template parameters starting with
|
||||
a dependent qualified name.
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
Release 3.1.3 (in development)
|
||||
==============================
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Incompatible changes
|
||||
--------------------
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
Features added
|
||||
--------------
|
||||
|
||||
Bugs fixed
|
||||
----------
|
||||
|
||||
* C, don't deepcopy the entire symbol table and make a mess every time an
|
||||
enumerator is handled.
|
||||
|
||||
Testing
|
||||
--------
|
||||
|
||||
Release 3.1.2 (released Jul 05, 2020)
|
||||
=====================================
|
||||
|
||||
|
||||
4
Makefile
4
Makefile
@@ -64,10 +64,6 @@ type-check:
|
||||
doclinter:
|
||||
python utils/doclinter.py CHANGES *.rst doc/
|
||||
|
||||
.PHONY: pylint
|
||||
pylint:
|
||||
@pylint --rcfile utils/pylintrc sphinx
|
||||
|
||||
.PHONY: test
|
||||
test:
|
||||
@$(PYTHON) -m pytest -v $(TEST)
|
||||
|
||||
@@ -12,6 +12,9 @@ Getting help
|
||||
|
||||
The Sphinx community maintains a number of mailing lists and IRC channels.
|
||||
|
||||
Stack Overflow with tag `python-sphinx`_
|
||||
Questions and answers about use and development.
|
||||
|
||||
sphinx-users <sphinx-users@googlegroups.com>
|
||||
Mailing list for user support.
|
||||
|
||||
@@ -21,6 +24,7 @@ sphinx-dev <sphinx-dev@googlegroups.com>
|
||||
#sphinx-doc on irc.freenode.net
|
||||
IRC channel for development questions and user support.
|
||||
|
||||
.. _python-sphinx: https://stackoverflow.com/questions/tagged/python-sphinx
|
||||
|
||||
Bug Reports and Feature Requests
|
||||
--------------------------------
|
||||
|
||||
@@ -756,9 +756,15 @@ documentation on :ref:`intl` for details.
|
||||
If true, a document's text domain is its docname if it is a top-level
|
||||
project file and its very base directory otherwise.
|
||||
|
||||
If set to string, all document's text domain is this string, making all
|
||||
documents use single text domain.
|
||||
|
||||
By default, the document ``markup/code.rst`` ends up in the ``markup`` text
|
||||
domain. With this option set to ``False``, it is ``markup/code``.
|
||||
|
||||
.. versionchanged:: 3.3
|
||||
The string value is now accepted.
|
||||
|
||||
.. confval:: gettext_uuid
|
||||
|
||||
If true, Sphinx generates uuid information for version tracking in message
|
||||
|
||||
@@ -32,8 +32,8 @@ if 'PYTHONWARNINGS' not in os.environ:
|
||||
warnings.filterwarnings('ignore', "'U' mode is deprecated",
|
||||
DeprecationWarning, module='docutils.io')
|
||||
|
||||
__version__ = '3.2.0'
|
||||
__released__ = '3.2.0' # used when Sphinx builds its own docs
|
||||
__version__ = '3.3.0+'
|
||||
__released__ = '3.3.0' # used when Sphinx builds its own docs
|
||||
|
||||
#: Version info for better programmatic use.
|
||||
#:
|
||||
@@ -43,7 +43,7 @@ __released__ = '3.2.0' # used when Sphinx builds its own docs
|
||||
#:
|
||||
#: .. versionadded:: 1.2
|
||||
#: Before version 1.2, check the string ``sphinx.__version__``.
|
||||
version_info = (3, 2, 0, 'final', 0)
|
||||
version_info = (3, 3, 0, 'beta', 0)
|
||||
|
||||
package_dir = path.abspath(path.dirname(__file__))
|
||||
|
||||
|
||||
@@ -316,7 +316,7 @@ class MessageCatalogBuilder(I18nBuilder):
|
||||
def setup(app: Sphinx) -> Dict[str, Any]:
|
||||
app.add_builder(MessageCatalogBuilder)
|
||||
|
||||
app.add_config_value('gettext_compact', True, 'gettext')
|
||||
app.add_config_value('gettext_compact', True, 'gettext', Any)
|
||||
app.add_config_value('gettext_location', True, 'gettext')
|
||||
app.add_config_value('gettext_uuid', False, 'gettext')
|
||||
app.add_config_value('gettext_auto_build', True, 'env')
|
||||
|
||||
@@ -32,7 +32,7 @@ from sphinx.transforms import SphinxTransform
|
||||
from sphinx.transforms.post_transforms import ReferencesResolver
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.cfamily import (
|
||||
NoOldIdError, ASTBaseBase, ASTBaseParenExprList,
|
||||
NoOldIdError, ASTBaseBase, ASTAttribute, ASTBaseParenExprList,
|
||||
verify_description_mode, StringifyTransform,
|
||||
BaseParser, DefinitionError, UnsupportedMultiCharacterCharLiteral,
|
||||
identifier_re, anon_identifier_re, integer_literal_re, octal_literal_re,
|
||||
@@ -652,8 +652,9 @@ class ASTFunctionParameter(ASTBase):
|
||||
|
||||
|
||||
class ASTParameters(ASTBase):
|
||||
def __init__(self, args: List[ASTFunctionParameter]) -> None:
|
||||
def __init__(self, args: List[ASTFunctionParameter], attrs: List[ASTAttribute]) -> None:
|
||||
self.args = args
|
||||
self.attrs = attrs
|
||||
|
||||
@property
|
||||
def function_params(self) -> List[ASTFunctionParameter]:
|
||||
@@ -669,6 +670,9 @@ class ASTParameters(ASTBase):
|
||||
first = False
|
||||
res.append(str(a))
|
||||
res.append(')')
|
||||
for attr in self.attrs:
|
||||
res.append(' ')
|
||||
res.append(transform(attr))
|
||||
return ''.join(res)
|
||||
|
||||
def describe_signature(self, signode: TextElement, mode: str,
|
||||
@@ -683,6 +687,9 @@ class ASTParameters(ASTBase):
|
||||
arg.describe_signature(param, 'markType', env, symbol=symbol)
|
||||
paramlist += param
|
||||
signode += paramlist
|
||||
for attr in self.attrs:
|
||||
signode += nodes.Text(' ')
|
||||
attr.describe_signature(signode)
|
||||
|
||||
|
||||
class ASTDeclSpecsSimple(ASTBaseBase):
|
||||
@@ -2572,7 +2579,15 @@ class DefinitionParser(BaseParser):
|
||||
self.fail(
|
||||
'Expecting "," or ")" in parameters, '
|
||||
'got "%s".' % self.current_char)
|
||||
return ASTParameters(args)
|
||||
|
||||
attrs = []
|
||||
while True:
|
||||
attr = self._parse_attribute()
|
||||
if attr is None:
|
||||
break
|
||||
attrs.append(attr)
|
||||
|
||||
return ASTParameters(args, attrs)
|
||||
|
||||
def _parse_decl_specs_simple(self, outer: str, typed: bool) -> ASTDeclSpecsSimple:
|
||||
"""Just parse the simple ones."""
|
||||
|
||||
@@ -1879,7 +1879,8 @@ class ASTNoexceptSpec(ASTBase):
|
||||
class ASTParametersQualifiers(ASTBase):
|
||||
def __init__(self, args: List[ASTFunctionParameter], volatile: bool, const: bool,
|
||||
refQual: str, exceptionSpec: ASTNoexceptSpec, trailingReturn: "ASTType",
|
||||
override: bool, final: bool, initializer: str) -> None:
|
||||
override: bool, final: bool, attrs: List[ASTAttribute],
|
||||
initializer: str) -> None:
|
||||
self.args = args
|
||||
self.volatile = volatile
|
||||
self.const = const
|
||||
@@ -1888,6 +1889,7 @@ class ASTParametersQualifiers(ASTBase):
|
||||
self.trailingReturn = trailingReturn
|
||||
self.override = override
|
||||
self.final = final
|
||||
self.attrs = attrs
|
||||
self.initializer = initializer
|
||||
|
||||
@property
|
||||
@@ -1947,6 +1949,9 @@ class ASTParametersQualifiers(ASTBase):
|
||||
res.append(' final')
|
||||
if self.override:
|
||||
res.append(' override')
|
||||
for attr in self.attrs:
|
||||
res.append(' ')
|
||||
res.append(transform(attr))
|
||||
if self.initializer:
|
||||
res.append(' = ')
|
||||
res.append(self.initializer)
|
||||
@@ -1988,6 +1993,9 @@ class ASTParametersQualifiers(ASTBase):
|
||||
_add_anno(signode, 'final')
|
||||
if self.override:
|
||||
_add_anno(signode, 'override')
|
||||
for attr in self.attrs:
|
||||
signode += nodes.Text(' ')
|
||||
attr.describe_signature(signode)
|
||||
if self.initializer:
|
||||
_add_text(signode, '= ' + str(self.initializer))
|
||||
|
||||
@@ -5709,6 +5717,13 @@ class DefinitionParser(BaseParser):
|
||||
override = self.skip_word_and_ws(
|
||||
'override') # they can be permuted
|
||||
|
||||
attrs = []
|
||||
while True:
|
||||
attr = self._parse_attribute()
|
||||
if attr is None:
|
||||
break
|
||||
attrs.append(attr)
|
||||
|
||||
self.skip_ws()
|
||||
initializer = None
|
||||
if self.skip_string('='):
|
||||
@@ -5725,7 +5740,7 @@ class DefinitionParser(BaseParser):
|
||||
|
||||
return ASTParametersQualifiers(
|
||||
args, volatile, const, refQual, exceptionSpec, trailingReturn,
|
||||
override, final, initializer)
|
||||
override, final, attrs, initializer)
|
||||
|
||||
def _parse_decl_specs_simple(self, outer: str, typed: bool) -> ASTDeclSpecsSimple:
|
||||
"""Just parse the simple ones."""
|
||||
@@ -6251,6 +6266,7 @@ class DefinitionParser(BaseParser):
|
||||
# ==========================================================================
|
||||
|
||||
def _parse_template_paramter(self) -> ASTTemplateParam:
|
||||
self.skip_ws()
|
||||
if self.skip_word('template'):
|
||||
# declare a tenplate template parameter
|
||||
nestedParams = self._parse_template_parameter_list()
|
||||
|
||||
@@ -594,7 +594,9 @@ class BuildEnvironment:
|
||||
|
||||
def traverse_toctree(parent: str, docname: str) -> Iterator[Tuple[str, str]]:
|
||||
if parent == docname:
|
||||
logger.warning(__('self referenced toctree found. Ignored.'), location=docname)
|
||||
logger.warning(__('self referenced toctree found. Ignored.'),
|
||||
location=docname, type='toc',
|
||||
subtype='circular')
|
||||
return
|
||||
|
||||
# traverse toctree by pre-order
|
||||
|
||||
@@ -18,6 +18,7 @@ from types import ModuleType
|
||||
from typing import (
|
||||
Any, Callable, Dict, Iterator, List, Optional, Sequence, Set, Tuple, Type, TypeVar, Union
|
||||
)
|
||||
from typing import get_type_hints
|
||||
|
||||
from docutils.statemachine import StringList
|
||||
|
||||
@@ -1605,8 +1606,21 @@ class DataDocumenter(ModuleLevelDocumenter):
|
||||
sourcename = self.get_sourcename()
|
||||
if not self.options.annotation:
|
||||
# obtain annotation for this data
|
||||
annotations = getattr(self.parent, '__annotations__', {})
|
||||
if annotations and self.objpath[-1] in annotations:
|
||||
try:
|
||||
annotations = get_type_hints(self.parent)
|
||||
except NameError:
|
||||
# Failed to evaluate ForwardRef (maybe TYPE_CHECKING)
|
||||
annotations = safe_getattr(self.parent, '__annotations__', {})
|
||||
except TypeError:
|
||||
annotations = {}
|
||||
except KeyError:
|
||||
# a broken class found (refs: https://github.com/sphinx-doc/sphinx/issues/8084)
|
||||
annotations = {}
|
||||
except AttributeError:
|
||||
# AttributeError is raised on 3.5.2 (fixed by 3.5.3)
|
||||
annotations = {}
|
||||
|
||||
if self.objpath[-1] in annotations:
|
||||
objrepr = stringify_typehint(annotations.get(self.objpath[-1]))
|
||||
self.add_line(' :type: ' + objrepr, sourcename)
|
||||
else:
|
||||
@@ -1971,8 +1985,21 @@ class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):
|
||||
sourcename = self.get_sourcename()
|
||||
if not self.options.annotation:
|
||||
# obtain type annotation for this attribute
|
||||
annotations = getattr(self.parent, '__annotations__', {})
|
||||
if annotations and self.objpath[-1] in annotations:
|
||||
try:
|
||||
annotations = get_type_hints(self.parent)
|
||||
except NameError:
|
||||
# Failed to evaluate ForwardRef (maybe TYPE_CHECKING)
|
||||
annotations = safe_getattr(self.parent, '__annotations__', {})
|
||||
except TypeError:
|
||||
annotations = {}
|
||||
except KeyError:
|
||||
# a broken class found (refs: https://github.com/sphinx-doc/sphinx/issues/8084)
|
||||
annotations = {}
|
||||
except AttributeError:
|
||||
# AttributeError is raised on 3.5.2 (fixed by 3.5.3)
|
||||
annotations = {}
|
||||
|
||||
if self.objpath[-1] in annotations:
|
||||
objrepr = stringify_typehint(annotations.get(self.objpath[-1]))
|
||||
self.add_line(' :type: ' + objrepr, sourcename)
|
||||
else:
|
||||
|
||||
@@ -18,6 +18,10 @@ from sphinx.pycode import ModuleAnalyzer
|
||||
from sphinx.util import logging
|
||||
from sphinx.util.inspect import isclass, isenumclass, safe_getattr
|
||||
|
||||
if False:
|
||||
# For type annotation
|
||||
from typing import Type # NOQA
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -158,6 +162,24 @@ Attribute = NamedTuple('Attribute', [('name', str),
|
||||
('value', Any)])
|
||||
|
||||
|
||||
def _getmro(obj: Any) -> Tuple["Type", ...]:
|
||||
"""Get __mro__ from given *obj* safely."""
|
||||
__mro__ = safe_getattr(obj, '__mro__', None)
|
||||
if isinstance(__mro__, tuple):
|
||||
return __mro__
|
||||
else:
|
||||
return tuple()
|
||||
|
||||
|
||||
def _getannotations(obj: Any) -> Mapping[str, Any]:
|
||||
"""Get __annotations__ from given *obj* safely."""
|
||||
__annotations__ = safe_getattr(obj, '__annotations__', None)
|
||||
if isinstance(__annotations__, Mapping):
|
||||
return __annotations__
|
||||
else:
|
||||
return {}
|
||||
|
||||
|
||||
def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable,
|
||||
analyzer: ModuleAnalyzer = None) -> Dict[str, Attribute]:
|
||||
"""Get members and attributes of target object."""
|
||||
@@ -199,11 +221,11 @@ def get_object_members(subject: Any, objpath: List[str], attrgetter: Callable,
|
||||
continue
|
||||
|
||||
# annotation only member (ex. attr: int)
|
||||
if hasattr(subject, '__annotations__') and isinstance(subject.__annotations__, Mapping):
|
||||
for name in subject.__annotations__:
|
||||
name = unmangle(subject, name)
|
||||
for i, cls in enumerate(_getmro(subject)):
|
||||
for name in _getannotations(cls):
|
||||
name = unmangle(cls, name)
|
||||
if name and name not in members:
|
||||
members[name] = Attribute(name, True, INSTANCEATTR)
|
||||
members[name] = Attribute(name, i == 0, INSTANCEATTR)
|
||||
|
||||
if analyzer:
|
||||
# append instance attributes (cf. self.attr1) if analyzer knows
|
||||
|
||||
@@ -298,6 +298,16 @@ class Autosummary(SphinxDirective):
|
||||
|
||||
raise exc # re-raise ImportError if instance attribute not found
|
||||
|
||||
def create_documenter(self, app: Sphinx, obj: Any,
|
||||
parent: Any, full_name: str) -> "Documenter":
|
||||
"""Get an autodoc.Documenter class suitable for documenting the given
|
||||
object.
|
||||
|
||||
Wraps get_documenter and is meant as a hook for extensions.
|
||||
"""
|
||||
doccls = get_documenter(app, obj, parent)
|
||||
return doccls(self.bridge, full_name)
|
||||
|
||||
def get_items(self, names: List[str]) -> List[Tuple[str, str, str, str]]:
|
||||
"""Try to import the given names, and return a list of
|
||||
``[(name, signature, summary_string, real_name), ...]``.
|
||||
@@ -329,8 +339,7 @@ class Autosummary(SphinxDirective):
|
||||
full_name = modname + '::' + full_name[len(modname) + 1:]
|
||||
# NB. using full_name here is important, since Documenters
|
||||
# handle module prefixes slightly differently
|
||||
doccls = get_documenter(self.env.app, obj, parent)
|
||||
documenter = doccls(self.bridge, full_name)
|
||||
documenter = self.create_documenter(self.env.app, obj, parent, full_name)
|
||||
if not documenter.parse_name():
|
||||
logger.warning(__('failed to parse name %s'), real_name,
|
||||
location=self.get_source_info())
|
||||
|
||||
@@ -41,6 +41,7 @@ class Config:
|
||||
napoleon_use_param = True
|
||||
napoleon_use_rtype = True
|
||||
napoleon_use_keyword = True
|
||||
napoleon_preprocess_types = False
|
||||
napoleon_type_aliases = None
|
||||
napoleon_custom_sections = None
|
||||
|
||||
@@ -237,9 +238,12 @@ class Config:
|
||||
|
||||
:returns: *bool* -- True if successful, False otherwise
|
||||
|
||||
napoleon_preprocess_types : :obj:`bool` (Defaults to False)
|
||||
Enable the type preprocessor for numpy style docstrings.
|
||||
|
||||
napoleon_type_aliases : :obj:`dict` (Defaults to None)
|
||||
Add a mapping of strings to string, translating types in numpy
|
||||
style docstrings.
|
||||
style docstrings. Only works if ``napoleon_preprocess_types = True``.
|
||||
|
||||
napoleon_custom_sections : :obj:`list` (Defaults to None)
|
||||
Add a list of custom sections to include, expanding the list of parsed sections.
|
||||
@@ -268,6 +272,7 @@ class Config:
|
||||
'napoleon_use_param': (True, 'env'),
|
||||
'napoleon_use_rtype': (True, 'env'),
|
||||
'napoleon_use_keyword': (True, 'env'),
|
||||
'napoleon_preprocess_types': (False, 'env'),
|
||||
'napoleon_type_aliases': (None, 'env'),
|
||||
'napoleon_custom_sections': (None, 'env')
|
||||
}
|
||||
|
||||
@@ -266,13 +266,16 @@ class GoogleDocstring:
|
||||
_descs = self.__class__(_descs, self._config).lines()
|
||||
return _name, _type, _descs
|
||||
|
||||
def _consume_fields(self, parse_type: bool = True, prefer_type: bool = False
|
||||
) -> List[Tuple[str, str, List[str]]]:
|
||||
def _consume_fields(self, parse_type: bool = True, prefer_type: bool = False,
|
||||
multiple: bool = False) -> List[Tuple[str, str, List[str]]]:
|
||||
self._consume_empty()
|
||||
fields = []
|
||||
while not self._is_section_break():
|
||||
_name, _type, _desc = self._consume_field(parse_type, prefer_type)
|
||||
if _name or _type or _desc:
|
||||
if multiple and _name:
|
||||
for name in _name.split(","):
|
||||
fields.append((name.strip(), _type, _desc))
|
||||
elif _name or _type or _desc:
|
||||
fields.append((_name, _type, _desc,))
|
||||
return fields
|
||||
|
||||
@@ -681,10 +684,12 @@ class GoogleDocstring:
|
||||
return self._format_fields(_('Other Parameters'), self._consume_fields())
|
||||
|
||||
def _parse_parameters_section(self, section: str) -> List[str]:
|
||||
fields = self._consume_fields()
|
||||
if self._config.napoleon_use_param:
|
||||
# Allow to declare multiple parameters at once (ex: x, y: int)
|
||||
fields = self._consume_fields(multiple=True)
|
||||
return self._format_docutils_params(fields)
|
||||
else:
|
||||
fields = self._consume_fields()
|
||||
return self._format_fields(_('Parameters'), fields)
|
||||
|
||||
def _parse_raises_section(self, section: str) -> List[str]:
|
||||
@@ -1072,7 +1077,10 @@ class NumpyDocstring(GoogleDocstring):
|
||||
super().__init__(docstring, config, app, what, name, obj, options)
|
||||
|
||||
def _get_location(self) -> str:
|
||||
filepath = inspect.getfile(self._obj) if self._obj is not None else None
|
||||
try:
|
||||
filepath = inspect.getfile(self._obj) if self._obj is not None else None
|
||||
except TypeError:
|
||||
filepath = None
|
||||
name = self._name
|
||||
|
||||
if filepath is None and name is None:
|
||||
@@ -1103,11 +1111,12 @@ class NumpyDocstring(GoogleDocstring):
|
||||
if prefer_type and not _type:
|
||||
_type, _name = _name, _type
|
||||
|
||||
_type = _convert_numpy_type_spec(
|
||||
_type,
|
||||
location=self._get_location(),
|
||||
translations=self._config.napoleon_type_aliases or {},
|
||||
)
|
||||
if self._config.napoleon_preprocess_types:
|
||||
_type = _convert_numpy_type_spec(
|
||||
_type,
|
||||
location=self._get_location(),
|
||||
translations=self._config.napoleon_type_aliases or {},
|
||||
)
|
||||
|
||||
indent = self._get_indent(line) + 1
|
||||
_desc = self._dedent(self._consume_indented_block(indent))
|
||||
|
||||
@@ -367,7 +367,14 @@ class SphinxComponentRegistry:
|
||||
logger.debug('[app] adding js_file: %r, %r', filename, attributes)
|
||||
self.js_files.append((filename, attributes))
|
||||
|
||||
def has_latex_package(self, name: str) -> bool:
|
||||
packages = self.latex_packages + self.latex_packages_after_hyperref
|
||||
return bool([x for x in packages if x[0] == name])
|
||||
|
||||
def add_latex_package(self, name: str, options: str, after_hyperref: bool = False) -> None:
|
||||
if self.has_latex_package(name):
|
||||
logger.warn("latex package '%s' already included" % name)
|
||||
|
||||
logger.debug('[app] adding latex package: %r', name)
|
||||
if after_hyperref:
|
||||
self.latex_packages_after_hyperref.append((name, options))
|
||||
|
||||
@@ -391,7 +391,7 @@ class BaseParser:
|
||||
% startPos)
|
||||
return self.definition[startPos:self.pos]
|
||||
|
||||
def _parse_attribute(self) -> ASTAttribute:
|
||||
def _parse_attribute(self) -> Optional[ASTAttribute]:
|
||||
self.skip_ws()
|
||||
# try C++11 style
|
||||
startPos = self.pos
|
||||
|
||||
@@ -14,7 +14,7 @@ import warnings
|
||||
from collections import namedtuple
|
||||
from datetime import datetime, timezone
|
||||
from os import path
|
||||
from typing import Callable, Generator, List, Set, Tuple
|
||||
from typing import Callable, Generator, List, Set, Tuple, Union
|
||||
|
||||
import babel.dates
|
||||
from babel.messages.mofile import write_mo
|
||||
@@ -128,8 +128,10 @@ def find_catalog(docname: str, compaction: bool) -> str:
|
||||
return ret
|
||||
|
||||
|
||||
def docname_to_domain(docname: str, compation: bool) -> str:
|
||||
def docname_to_domain(docname: str, compation: Union[bool, str]) -> str:
|
||||
"""Convert docname to domain for catalogs."""
|
||||
if isinstance(compation, str):
|
||||
return compation
|
||||
if compation:
|
||||
return docname.split(SEP, 1)[0]
|
||||
else:
|
||||
|
||||
@@ -84,6 +84,8 @@ class LaTeXRenderer(SphinxRenderer):
|
||||
self.env.variable_end_string = '%>'
|
||||
self.env.block_start_string = '<%'
|
||||
self.env.block_end_string = '%>'
|
||||
self.env.comment_start_string = '<#'
|
||||
self.env.comment_end_string = '<#'
|
||||
|
||||
|
||||
class ReSTRenderer(SphinxRenderer):
|
||||
|
||||
@@ -450,7 +450,7 @@ class HTMLTranslator(SphinxTranslator, BaseTranslator):
|
||||
|
||||
highlighted = self.highlighter.highlight_block(
|
||||
node.rawsource, lang, opts=opts, linenos=linenos,
|
||||
location=(self.builder.current_docname, node.line), **highlight_args
|
||||
location=node, **highlight_args
|
||||
)
|
||||
starttag = self.starttag(node, 'div', suffix='',
|
||||
CLASS='highlight-%s notranslate' % lang)
|
||||
|
||||
@@ -402,7 +402,7 @@ class HTML5Translator(SphinxTranslator, BaseTranslator):
|
||||
|
||||
highlighted = self.highlighter.highlight_block(
|
||||
node.rawsource, lang, opts=opts, linenos=linenos,
|
||||
location=(self.builder.current_docname, node.line), **highlight_args
|
||||
location=node, **highlight_args
|
||||
)
|
||||
starttag = self.starttag(node, 'div', suffix='',
|
||||
CLASS='highlight-%s notranslate' % lang)
|
||||
|
||||
@@ -651,7 +651,7 @@ class LaTeXTranslator(SphinxTranslator):
|
||||
if len(node.children) != 1 and not isinstance(node.children[0],
|
||||
nodes.Text):
|
||||
logger.warning(__('document title is not a single Text node'),
|
||||
location=(self.curfilestack[-1], node.line))
|
||||
location=node)
|
||||
if not self.elements['title']:
|
||||
# text needs to be escaped since it is inserted into
|
||||
# the output literally
|
||||
@@ -684,7 +684,7 @@ class LaTeXTranslator(SphinxTranslator):
|
||||
else:
|
||||
logger.warning(__('encountered title node not in section, topic, table, '
|
||||
'admonition or sidebar'),
|
||||
location=(self.curfilestack[-1], node.line or ''))
|
||||
location=node)
|
||||
self.body.append('\\sphinxstyleothertitle{')
|
||||
self.context.append('}\n')
|
||||
self.in_title = 1
|
||||
@@ -1762,7 +1762,7 @@ class LaTeXTranslator(SphinxTranslator):
|
||||
|
||||
hlcode = self.highlighter.highlight_block(
|
||||
node.rawsource, lang, opts=opts, linenos=linenos,
|
||||
location=(self.curfilestack[-1], node.line), **highlight_args
|
||||
location=node, **highlight_args
|
||||
)
|
||||
if self.in_footnote:
|
||||
self.body.append('\n\\sphinxSetupCodeBlockInFootnote')
|
||||
|
||||
@@ -628,7 +628,7 @@ class TexinfoTranslator(SphinxTranslator):
|
||||
elif not isinstance(parent, nodes.section):
|
||||
logger.warning(__('encountered title node not in section, topic, table, '
|
||||
'admonition or sidebar'),
|
||||
location=(self.curfilestack[-1], node.line))
|
||||
location=node)
|
||||
self.visit_rubric(node)
|
||||
else:
|
||||
try:
|
||||
@@ -1186,7 +1186,7 @@ class TexinfoTranslator(SphinxTranslator):
|
||||
self.body.append('\n@caption{')
|
||||
else:
|
||||
logger.warning(__('caption not inside a figure.'),
|
||||
location=(self.curfilestack[-1], node.line))
|
||||
location=node)
|
||||
|
||||
def depart_caption(self, node: Element) -> None:
|
||||
if (isinstance(node.parent, nodes.figure) or
|
||||
@@ -1262,11 +1262,11 @@ class TexinfoTranslator(SphinxTranslator):
|
||||
|
||||
def unimplemented_visit(self, node: Element) -> None:
|
||||
logger.warning(__("unimplemented node type: %r"), node,
|
||||
location=(self.curfilestack[-1], node.line))
|
||||
location=node)
|
||||
|
||||
def unknown_visit(self, node: Node) -> None:
|
||||
logger.warning(__("unknown node type: %r"), node,
|
||||
location=(self.curfilestack[-1], node.line))
|
||||
location=node)
|
||||
|
||||
def unknown_departure(self, node: Node) -> None:
|
||||
pass
|
||||
|
||||
8
tests/roots/test-ext-autodoc/target/TYPE_CHECKING.py
Normal file
8
tests/roots/test-ext-autodoc/target/TYPE_CHECKING.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from io import StringIO
|
||||
|
||||
|
||||
class Foo:
|
||||
attr1: "StringIO"
|
||||
@@ -28,4 +28,4 @@ class Class:
|
||||
|
||||
|
||||
class Derived(Class):
|
||||
pass
|
||||
attr7: int
|
||||
|
||||
@@ -174,3 +174,21 @@ def test_gettext_template_msgid_order_in_sphinxpot(app):
|
||||
'msgid "This is Template 2\\.".*'),
|
||||
result,
|
||||
flags=re.S)
|
||||
|
||||
|
||||
@pytest.mark.sphinx(
|
||||
'gettext', srcdir='root-gettext',
|
||||
confoverrides={'gettext_compact': 'documentation'})
|
||||
def test_build_single_pot(app):
|
||||
app.builder.build_all()
|
||||
|
||||
assert (app.outdir / 'documentation.pot').isfile()
|
||||
|
||||
result = (app.outdir / 'documentation.pot').read_text()
|
||||
assert re.search(
|
||||
('msgid "Todo".*'
|
||||
'msgid "Like footnotes.".*'
|
||||
'msgid "The minute.".*'
|
||||
'msgid "Generated section".*'),
|
||||
result,
|
||||
flags=re.S)
|
||||
|
||||
@@ -497,17 +497,16 @@ def test_attributes():
|
||||
parse('member', 'paren_attr({]}) int f')
|
||||
|
||||
# position: decl specs
|
||||
check('function', 'static inline __attribute__(()) void f()',
|
||||
{1: 'f'},
|
||||
check('function', 'static inline __attribute__(()) void f()', {1: 'f'},
|
||||
output='__attribute__(()) static inline void f()')
|
||||
check('function', '[[attr1]] [[attr2]] void f()',
|
||||
{1: 'f'},
|
||||
output='[[attr1]] [[attr2]] void f()')
|
||||
check('function', '[[attr1]] [[attr2]] void f()', {1: 'f'})
|
||||
# position: declarator
|
||||
check('member', 'int *[[attr]] i', {1: 'i'})
|
||||
check('member', 'int *const [[attr]] volatile i', {1: 'i'},
|
||||
output='int *[[attr]] volatile const i')
|
||||
check('member', 'int *[[attr]] *i', {1: 'i'})
|
||||
# position: parameters
|
||||
check('function', 'void f() [[attr1]] [[attr2]]', {1: 'f'})
|
||||
|
||||
# issue michaeljones/breathe#500
|
||||
check('function', 'LIGHTGBM_C_EXPORT int LGBM_BoosterFree(int handle)',
|
||||
|
||||
@@ -764,6 +764,7 @@ def test_templates():
|
||||
check('class', "template<template<typename> typename> {key}A", {2: "II0E0E1A"})
|
||||
check('class', "template<template<typename> typename ...T> {key}A", {2: "II0EDpE1A"})
|
||||
check('class', "template<template<typename> typename...> {key}A", {2: "II0EDpE1A"})
|
||||
check('class', "template<typename T, template<typename> typename...> {key}A", {2: "I0I0EDpE1A"})
|
||||
|
||||
check('class', "template<int> {key}A", {2: "I_iE1A"})
|
||||
check('class', "template<int T> {key}A", {2: "I_iE1A"})
|
||||
@@ -937,15 +938,15 @@ def test_attributes():
|
||||
check('function', 'static inline __attribute__(()) void f()',
|
||||
{1: 'f', 2: '1fv'},
|
||||
output='__attribute__(()) static inline void f()')
|
||||
check('function', '[[attr1]] [[attr2]] void f()',
|
||||
{1: 'f', 2: '1fv'},
|
||||
output='[[attr1]] [[attr2]] void f()')
|
||||
check('function', '[[attr1]] [[attr2]] void f()', {1: 'f', 2: '1fv'})
|
||||
# position: declarator
|
||||
check('member', 'int *[[attr]] i', {1: 'i__iP', 2: '1i'})
|
||||
check('member', 'int *const [[attr]] volatile i', {1: 'i__iPVC', 2: '1i'},
|
||||
output='int *[[attr]] volatile const i')
|
||||
check('member', 'int &[[attr]] i', {1: 'i__iR', 2: '1i'})
|
||||
check('member', 'int *[[attr]] *i', {1: 'i__iPP', 2: '1i'})
|
||||
# position: parameters and qualifiers
|
||||
check('function', 'void f() [[attr1]] [[attr2]]', {1: 'f', 2: '1fv'})
|
||||
|
||||
|
||||
def test_xref_parsing():
|
||||
|
||||
@@ -1580,12 +1580,7 @@ def test_autodoc_typed_instance_variables(app):
|
||||
' :module: target.typed_vars',
|
||||
'',
|
||||
'',
|
||||
' .. py:attribute:: Derived.attr2',
|
||||
' :module: target.typed_vars',
|
||||
' :type: int',
|
||||
'',
|
||||
'',
|
||||
' .. py:attribute:: Derived.descr4',
|
||||
' .. py:attribute:: Derived.attr7',
|
||||
' :module: target.typed_vars',
|
||||
' :type: int',
|
||||
'',
|
||||
@@ -1615,6 +1610,47 @@ def test_autodoc_typed_instance_variables(app):
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 6), reason='py36+ is available since python3.6.')
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_autodoc_typed_inherited_instance_variables(app):
|
||||
options = {"members": None,
|
||||
"undoc-members": True,
|
||||
"inherited-members": True}
|
||||
actual = do_autodoc(app, 'class', 'target.typed_vars.Derived', options)
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:class:: Derived()',
|
||||
' :module: target.typed_vars',
|
||||
'',
|
||||
'',
|
||||
' .. py:attribute:: Derived.attr1',
|
||||
' :module: target.typed_vars',
|
||||
' :type: int',
|
||||
' :value: 0',
|
||||
'',
|
||||
'',
|
||||
' .. py:attribute:: Derived.attr2',
|
||||
' :module: target.typed_vars',
|
||||
' :type: int',
|
||||
'',
|
||||
'',
|
||||
' .. py:attribute:: Derived.attr3',
|
||||
' :module: target.typed_vars',
|
||||
' :value: 0',
|
||||
'',
|
||||
'',
|
||||
' .. py:attribute:: Derived.attr7',
|
||||
' :module: target.typed_vars',
|
||||
' :type: int',
|
||||
'',
|
||||
'',
|
||||
' .. py:attribute:: Derived.descr4',
|
||||
' :module: target.typed_vars',
|
||||
' :type: int',
|
||||
'',
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_autodoc_GenericAlias(app):
|
||||
options = {"members": None,
|
||||
@@ -1704,6 +1740,28 @@ def test_autodoc_Annotated(app):
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 6), reason='py36+ is required.')
|
||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||
def test_autodoc_TYPE_CHECKING(app):
|
||||
options = {"members": None,
|
||||
"undoc-members": None}
|
||||
actual = do_autodoc(app, 'module', 'target.TYPE_CHECKING', options)
|
||||
assert list(actual) == [
|
||||
'',
|
||||
'.. py:module:: target.TYPE_CHECKING',
|
||||
'',
|
||||
'',
|
||||
'.. py:class:: Foo()',
|
||||
' :module: target.TYPE_CHECKING',
|
||||
'',
|
||||
'',
|
||||
' .. py:attribute:: Foo.attr1',
|
||||
' :module: target.TYPE_CHECKING',
|
||||
' :type: StringIO',
|
||||
'',
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.sphinx('html', testroot='pycode-egg')
|
||||
def test_autodoc_for_egged_code(app):
|
||||
options = {"members": None,
|
||||
|
||||
@@ -66,19 +66,19 @@ Sample namedtuple subclass
|
||||
|
||||
Quick description of attr1
|
||||
|
||||
:type: :class:`Arbitrary type`
|
||||
:type: Arbitrary type
|
||||
|
||||
.. attribute:: attr2
|
||||
|
||||
Quick description of attr2
|
||||
|
||||
:type: :class:`Another arbitrary type`
|
||||
:type: Another arbitrary type
|
||||
|
||||
.. attribute:: attr3
|
||||
|
||||
Adds a newline after the type
|
||||
|
||||
:type: :class:`Type`
|
||||
:type: Type
|
||||
"""
|
||||
|
||||
self.assertEqual(expected, actual)
|
||||
@@ -1311,12 +1311,34 @@ class NumpyDocstringTest(BaseDocstringTest):
|
||||
config = Config(
|
||||
napoleon_use_param=False,
|
||||
napoleon_use_rtype=False,
|
||||
napoleon_use_keyword=False)
|
||||
napoleon_use_keyword=False,
|
||||
napoleon_preprocess_types=True)
|
||||
for docstring, expected in self.docstrings:
|
||||
actual = str(NumpyDocstring(dedent(docstring), config))
|
||||
expected = dedent(expected)
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_type_preprocessor(self):
|
||||
docstring = dedent("""
|
||||
Single line summary
|
||||
|
||||
Parameters
|
||||
----------
|
||||
arg1:str
|
||||
Extended
|
||||
description of arg1
|
||||
""")
|
||||
|
||||
config = Config(napoleon_preprocess_types=False, napoleon_use_param=False)
|
||||
actual = str(NumpyDocstring(docstring, config))
|
||||
expected = dedent("""
|
||||
Single line summary
|
||||
|
||||
:Parameters: **arg1** (*str*) -- Extended
|
||||
description of arg1
|
||||
""")
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_parameters_with_class_reference(self):
|
||||
docstring = """\
|
||||
Parameters
|
||||
@@ -1337,6 +1359,32 @@ param1 : :class:`MyClass <name.space.MyClass>` instance
|
||||
expected = """\
|
||||
:param param1:
|
||||
:type param1: :class:`MyClass <name.space.MyClass>` instance
|
||||
"""
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_multiple_parameters(self):
|
||||
docstring = """\
|
||||
Parameters
|
||||
----------
|
||||
x1, x2 : array_like
|
||||
Input arrays, description of ``x1``, ``x2``.
|
||||
|
||||
"""
|
||||
|
||||
config = Config(napoleon_use_param=False)
|
||||
actual = str(NumpyDocstring(docstring, config))
|
||||
expected = """\
|
||||
:Parameters: **x1, x2** (*array_like*) -- Input arrays, description of ``x1``, ``x2``.
|
||||
"""
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
config = Config(napoleon_use_param=True)
|
||||
actual = str(NumpyDocstring(dedent(docstring), config))
|
||||
expected = """\
|
||||
:param x1: Input arrays, description of ``x1``, ``x2``.
|
||||
:type x1: array_like
|
||||
:param x2: Input arrays, description of ``x1``, ``x2``.
|
||||
:type x2: array_like
|
||||
"""
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
@@ -1351,7 +1399,7 @@ param1 : MyClass instance
|
||||
config = Config(napoleon_use_param=False)
|
||||
actual = str(NumpyDocstring(docstring, config))
|
||||
expected = """\
|
||||
:Parameters: **param1** (:class:`MyClass instance`)
|
||||
:Parameters: **param1** (*MyClass instance*)
|
||||
"""
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
@@ -1359,7 +1407,7 @@ param1 : MyClass instance
|
||||
actual = str(NumpyDocstring(dedent(docstring), config))
|
||||
expected = """\
|
||||
:param param1:
|
||||
:type param1: :class:`MyClass instance`
|
||||
:type param1: MyClass instance
|
||||
"""
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
@@ -1448,7 +1496,7 @@ arg_ : type
|
||||
|
||||
expected = """
|
||||
:ivar arg_: some description
|
||||
:vartype arg_: :class:`type`
|
||||
:vartype arg_: type
|
||||
"""
|
||||
|
||||
config = Config(napoleon_use_ivar=True)
|
||||
@@ -1468,7 +1516,7 @@ arg_ : type
|
||||
|
||||
expected = """
|
||||
:ivar arg\\_: some description
|
||||
:vartype arg\\_: :class:`type`
|
||||
:vartype arg\\_: type
|
||||
"""
|
||||
|
||||
config = Config(napoleon_use_ivar=True)
|
||||
@@ -1913,59 +1961,59 @@ definition_after_normal_text : int
|
||||
expected = """One line summary.
|
||||
|
||||
:param no_list:
|
||||
:type no_list: :class:`int`
|
||||
:type no_list: int
|
||||
:param one_bullet_empty:
|
||||
*
|
||||
:type one_bullet_empty: :class:`int`
|
||||
:type one_bullet_empty: int
|
||||
:param one_bullet_single_line:
|
||||
- first line
|
||||
:type one_bullet_single_line: :class:`int`
|
||||
:type one_bullet_single_line: int
|
||||
:param one_bullet_two_lines:
|
||||
+ first line
|
||||
continued
|
||||
:type one_bullet_two_lines: :class:`int`
|
||||
:type one_bullet_two_lines: int
|
||||
:param two_bullets_single_line:
|
||||
- first line
|
||||
- second line
|
||||
:type two_bullets_single_line: :class:`int`
|
||||
:type two_bullets_single_line: int
|
||||
:param two_bullets_two_lines:
|
||||
* first line
|
||||
continued
|
||||
* second line
|
||||
continued
|
||||
:type two_bullets_two_lines: :class:`int`
|
||||
:type two_bullets_two_lines: int
|
||||
:param one_enumeration_single_line:
|
||||
1. first line
|
||||
:type one_enumeration_single_line: :class:`int`
|
||||
:type one_enumeration_single_line: int
|
||||
:param one_enumeration_two_lines:
|
||||
1) first line
|
||||
continued
|
||||
:type one_enumeration_two_lines: :class:`int`
|
||||
:type one_enumeration_two_lines: int
|
||||
:param two_enumerations_one_line:
|
||||
(iii) first line
|
||||
(iv) second line
|
||||
:type two_enumerations_one_line: :class:`int`
|
||||
:type two_enumerations_one_line: int
|
||||
:param two_enumerations_two_lines:
|
||||
a. first line
|
||||
continued
|
||||
b. second line
|
||||
continued
|
||||
:type two_enumerations_two_lines: :class:`int`
|
||||
:type two_enumerations_two_lines: int
|
||||
:param one_definition_one_line:
|
||||
item 1
|
||||
first line
|
||||
:type one_definition_one_line: :class:`int`
|
||||
:type one_definition_one_line: int
|
||||
:param one_definition_two_lines:
|
||||
item 1
|
||||
first line
|
||||
continued
|
||||
:type one_definition_two_lines: :class:`int`
|
||||
:type one_definition_two_lines: int
|
||||
:param two_definitions_one_line:
|
||||
item 1
|
||||
first line
|
||||
item 2
|
||||
second line
|
||||
:type two_definitions_one_line: :class:`int`
|
||||
:type two_definitions_one_line: int
|
||||
:param two_definitions_two_lines:
|
||||
item 1
|
||||
first line
|
||||
@@ -1973,14 +2021,14 @@ definition_after_normal_text : int
|
||||
item 2
|
||||
second line
|
||||
continued
|
||||
:type two_definitions_two_lines: :class:`int`
|
||||
:type two_definitions_two_lines: int
|
||||
:param one_definition_blank_line:
|
||||
item 1
|
||||
|
||||
first line
|
||||
|
||||
extra first line
|
||||
:type one_definition_blank_line: :class:`int`
|
||||
:type one_definition_blank_line: int
|
||||
:param two_definitions_blank_lines:
|
||||
item 1
|
||||
|
||||
@@ -1993,12 +2041,12 @@ definition_after_normal_text : int
|
||||
second line
|
||||
|
||||
extra second line
|
||||
:type two_definitions_blank_lines: :class:`int`
|
||||
:type two_definitions_blank_lines: int
|
||||
:param definition_after_normal_text: text line
|
||||
|
||||
item 1
|
||||
first line
|
||||
:type definition_after_normal_text: :class:`int`
|
||||
:type definition_after_normal_text: int
|
||||
"""
|
||||
config = Config(napoleon_use_param=True)
|
||||
actual = str(NumpyDocstring(docstring, config))
|
||||
@@ -2092,7 +2140,7 @@ definition_after_normal_text : int
|
||||
item 1
|
||||
first line
|
||||
"""
|
||||
config = Config(napoleon_use_param=False)
|
||||
config = Config(napoleon_use_param=False, napoleon_preprocess_types=True)
|
||||
actual = str(NumpyDocstring(docstring, config))
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
@@ -2273,6 +2321,7 @@ definition_after_normal_text : int
|
||||
config = Config(
|
||||
napoleon_use_param=True,
|
||||
napoleon_use_rtype=True,
|
||||
napoleon_preprocess_types=True,
|
||||
napoleon_type_aliases=translations,
|
||||
)
|
||||
actual = str(NumpyDocstring(docstring, config))
|
||||
|
||||
11
tox.ini
11
tox.ini
@@ -26,6 +26,7 @@ extras =
|
||||
test
|
||||
setenv =
|
||||
PYTHONWARNINGS = all,ignore::ImportWarning:importlib._bootstrap_external,ignore::DeprecationWarning:site,ignore::DeprecationWarning:distutils
|
||||
PYTEST_ADDOPTS = --color yes
|
||||
commands=
|
||||
pytest --durations 25 {posargs}
|
||||
|
||||
@@ -40,16 +41,6 @@ extras =
|
||||
commands =
|
||||
flake8 {posargs}
|
||||
|
||||
[testenv:pylint]
|
||||
basepython = python3
|
||||
description =
|
||||
Run source code analyzer.
|
||||
deps =
|
||||
pylint
|
||||
{[testenv]deps}
|
||||
commands =
|
||||
pylint --rcfile utils/pylintrc sphinx
|
||||
|
||||
[testenv:coverage]
|
||||
basepython = python3
|
||||
description =
|
||||
|
||||
301
utils/pylintrc
301
utils/pylintrc
@@ -1,301 +0,0 @@
|
||||
# lint Python modules using external checkers.
|
||||
#
|
||||
# This is the main checker controlling the other ones and the reports
|
||||
# generation. It is itself both a raw checker and an astng checker in order
|
||||
# to:
|
||||
# * handle message activation / deactivation at the module level
|
||||
# * handle some basic but necessary stats'data (number of classes, methods...)
|
||||
#
|
||||
[MASTER]
|
||||
|
||||
# Specify a configuration file.
|
||||
#rcfile=
|
||||
|
||||
# Profiled execution.
|
||||
profile=no
|
||||
|
||||
# Add <file or directory> to the black list. It should be a base name, not a
|
||||
# path. You may set this option multiple times.
|
||||
ignore=.svn
|
||||
|
||||
# Pickle collected data for later comparisons.
|
||||
persistent=yes
|
||||
|
||||
# Set the cache size for astng objects.
|
||||
cache-size=500
|
||||
|
||||
# List of plugins (as comma separated values of python modules names) to load,
|
||||
# usually to register additional checkers.
|
||||
load-plugins=
|
||||
|
||||
|
||||
[MESSAGES CONTROL]
|
||||
|
||||
# Enable only checker(s) with the given id(s). This option conflict with the
|
||||
# disable-checker option
|
||||
#enable-checker=
|
||||
|
||||
# Enable all checker(s) except those with the given id(s). This option conflict
|
||||
# with the disable-checker option
|
||||
#disable-checker=
|
||||
|
||||
# Enable all messages in the listed categories.
|
||||
#enable-msg-cat=
|
||||
|
||||
# Disable all messages in the listed categories.
|
||||
#disable-msg-cat=
|
||||
|
||||
# Enable the message(s) with the given id(s).
|
||||
#enable-msg=
|
||||
|
||||
# Disable the message(s) with the given id(s).
|
||||
disable-msg=C0323,W0142,C0301,C0103,C0111,E0213,C0302,C0203,W0703,R0201,W0613,W0612,W0622
|
||||
|
||||
|
||||
[REPORTS]
|
||||
|
||||
# set the output format. Available formats are text, parseable, colorized and
|
||||
# html
|
||||
output-format=colorized
|
||||
|
||||
# Include message's id in output
|
||||
include-ids=yes
|
||||
|
||||
# Put messages in a separate file for each module / package specified on the
|
||||
# command line instead of printing them on stdout. Reports (if any) will be
|
||||
# written in a file name "pylint_global.[txt|html]".
|
||||
files-output=no
|
||||
|
||||
# Tells wether to display a full report or only the messages
|
||||
reports=yes
|
||||
|
||||
# Python expression which should return a note less than 10 (10 is the highest
|
||||
# note).You have access to the variables errors warning, statement which
|
||||
# respectively contain the number of errors / warnings messages and the total
|
||||
# number of statements analyzed. This is used by the global evaluation report
|
||||
# (R0004).
|
||||
evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
|
||||
|
||||
# Add a comment according to your evaluation note. This is used by the global
|
||||
# evaluation report (R0004).
|
||||
comment=no
|
||||
|
||||
# Enable the report(s) with the given id(s).
|
||||
#enable-report=
|
||||
|
||||
# Disable the report(s) with the given id(s).
|
||||
#disable-report=
|
||||
|
||||
|
||||
# checks for
|
||||
# * unused variables / imports
|
||||
# * undefined variables
|
||||
# * redefinition of variable from builtins or from an outer scope
|
||||
# * use of variable before assigment
|
||||
#
|
||||
[VARIABLES]
|
||||
|
||||
# Tells wether we should check for unused import in __init__ files.
|
||||
init-import=no
|
||||
|
||||
# A regular expression matching names used for dummy variables (i.e. not used).
|
||||
dummy-variables-rgx=_|dummy
|
||||
|
||||
# List of additional names supposed to be defined in builtins. Remember that
|
||||
# you should avoid to define new builtins when possible.
|
||||
additional-builtins=
|
||||
|
||||
|
||||
# try to find bugs in the code using type inference
|
||||
#
|
||||
[TYPECHECK]
|
||||
|
||||
# Tells wether missing members accessed in mixin class should be ignored. A
|
||||
# mixin class is detected if its name ends with "mixin" (case insensitive).
|
||||
ignore-mixin-members=yes
|
||||
|
||||
# When zope mode is activated, consider the acquired-members option to ignore
|
||||
# access to some undefined attributes.
|
||||
zope=no
|
||||
|
||||
# List of members which are usually get through zope's acquisition mecanism and
|
||||
# so shouldn't trigger E0201 when accessed (need zope=yes to be considered).
|
||||
acquired-members=REQUEST,acl_users,aq_parent
|
||||
|
||||
|
||||
# checks for :
|
||||
# * doc strings
|
||||
# * modules / classes / functions / methods / arguments / variables name
|
||||
# * number of arguments, local variables, branchs, returns and statements in
|
||||
# functions, methods
|
||||
# * required module attributes
|
||||
# * dangerous default values as arguments
|
||||
# * redefinition of function / method / class
|
||||
# * uses of the global statement
|
||||
#
|
||||
[BASIC]
|
||||
|
||||
# Required attributes for module, separated by a comma
|
||||
required-attributes=
|
||||
|
||||
# Regular expression which should only match functions or classes name which do
|
||||
# not require a docstring
|
||||
no-docstring-rgx=__.*__
|
||||
|
||||
# Regular expression which should only match correct module names
|
||||
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
|
||||
|
||||
# Regular expression which should only match correct module level names
|
||||
const-rgx=(([A-Z_][A-Z1-9_]*)|(__.*__))$
|
||||
|
||||
# Regular expression which should only match correct class names
|
||||
class-rgx=[A-Z_][a-zA-Z0-9]+$
|
||||
|
||||
# Regular expression which should only match correct function names
|
||||
function-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match correct method names
|
||||
method-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match correct instance attribute names
|
||||
attr-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match correct argument names
|
||||
argument-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match correct variable names
|
||||
variable-rgx=[a-z_][a-z0-9_]{2,30}$
|
||||
|
||||
# Regular expression which should only match correct list comprehension /
|
||||
# generator expression variable names
|
||||
inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
|
||||
|
||||
# Good variable names which should always be accepted, separated by a comma
|
||||
good-names=i,j,k,ex,Run,_
|
||||
|
||||
# Bad variable names which should always be refused, separated by a comma
|
||||
bad-names=foo,bar,baz,toto,tutu,tata
|
||||
|
||||
# List of builtins function names that should not be used, separated by a comma
|
||||
bad-functions=apply,input
|
||||
|
||||
|
||||
# checks for sign of poor/misdesign:
|
||||
# * number of methods, attributes, local variables...
|
||||
# * size, complexity of functions, methods
|
||||
#
|
||||
[DESIGN]
|
||||
|
||||
# Maximum number of arguments for function / method
|
||||
max-args=12
|
||||
|
||||
# Maximum number of locals for function / method body
|
||||
max-locals=30
|
||||
|
||||
# Maximum number of return / yield for function / method body
|
||||
max-returns=12
|
||||
|
||||
# Maximum number of branch for function / method body
|
||||
max-branchs=30
|
||||
|
||||
# Maximum number of statements in function / method body
|
||||
max-statements=60
|
||||
|
||||
# Maximum number of parents for a class (see R0901).
|
||||
max-parents=7
|
||||
|
||||
# Maximum number of attributes for a class (see R0902).
|
||||
max-attributes=20
|
||||
|
||||
# Minimum number of public methods for a class (see R0903).
|
||||
min-public-methods=0
|
||||
|
||||
# Maximum number of public methods for a class (see R0904).
|
||||
max-public-methods=20
|
||||
|
||||
|
||||
# checks for
|
||||
# * external modules dependencies
|
||||
# * relative / wildcard imports
|
||||
# * cyclic imports
|
||||
# * uses of deprecated modules
|
||||
#
|
||||
[IMPORTS]
|
||||
|
||||
# Deprecated modules which should not be used, separated by a comma
|
||||
deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
|
||||
|
||||
# Create a graph of every (i.e. internal and external) dependencies in the
|
||||
# given file (report R0402 must not be disabled)
|
||||
import-graph=
|
||||
|
||||
# Create a graph of external dependencies in the given file (report R0402 must
|
||||
# not be disabled)
|
||||
ext-import-graph=
|
||||
|
||||
# Create a graph of internal dependencies in the given file (report R0402 must
|
||||
# not be disabled)
|
||||
int-import-graph=
|
||||
|
||||
|
||||
# checks for :
|
||||
# * methods without self as first argument
|
||||
# * overridden methods signature
|
||||
# * access only to existant members via self
|
||||
# * attributes not defined in the __init__ method
|
||||
# * supported interfaces implementation
|
||||
# * unreachable code
|
||||
#
|
||||
[CLASSES]
|
||||
|
||||
# List of interface methods to ignore, separated by a comma. This is used for
|
||||
# instance to not check methods defines in Zope's Interface base class.
|
||||
ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
|
||||
|
||||
# List of method names used to declare (i.e. assign) instance attributes.
|
||||
defining-attr-methods=__init__,__new__,setUp
|
||||
|
||||
|
||||
# checks for similarities and duplicated code. This computation may be
|
||||
# memory / CPU intensive, so you should disable it if you experiments some
|
||||
# problems.
|
||||
#
|
||||
[SIMILARITIES]
|
||||
|
||||
# Minimum lines number of a similarity.
|
||||
min-similarity-lines=10
|
||||
|
||||
# Ignore comments when computing similarities.
|
||||
ignore-comments=yes
|
||||
|
||||
# Ignore docstrings when computing similarities.
|
||||
ignore-docstrings=yes
|
||||
|
||||
|
||||
# checks for:
|
||||
# * warning notes in the code
|
||||
# * PEP 263: source code with non ascii character but no encoding declaration
|
||||
#
|
||||
[MISCELLANEOUS]
|
||||
|
||||
# List of note tags to take in consideration, separated by a comma.
|
||||
notes=FIXME,XXX,TODO
|
||||
|
||||
|
||||
# checks for :
|
||||
# * unauthorized constructions
|
||||
# * strict indentation
|
||||
# * line length
|
||||
# * use of <> instead of !=
|
||||
#
|
||||
[FORMAT]
|
||||
|
||||
# Maximum number of characters on a single line.
|
||||
max-line-length=90
|
||||
|
||||
# Maximum number of lines in a module
|
||||
max-module-lines=1000
|
||||
|
||||
# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
|
||||
# tab).
|
||||
indent-string=' '
|
||||
Reference in New Issue
Block a user