Skip to content

Commit

Permalink
Merge branch '3.2.x' into 3.x
Browse files Browse the repository at this point in the history
  • Loading branch information
tk0miya committed Aug 14, 2020
2 parents ec7e8aa + 90e9b31 commit b2d524d
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 49 deletions.
9 changes: 9 additions & 0 deletions CHANGES
Expand Up @@ -38,12 +38,21 @@ Deprecated
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
* C++, fix parsing of template template paramters, broken by the fix of #7944

Testing
--------
Expand Down
21 changes: 18 additions & 3 deletions sphinx/domains/c.py
Expand Up @@ -32,7 +32,7 @@
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,
Expand Down Expand Up @@ -652,8 +652,9 @@ def describe_signature(self, signode: Any, mode: str,


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]:
Expand All @@ -669,6 +670,9 @@ def _stringify(self, transform: StringifyTransform) -> str:
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,
Expand All @@ -683,6 +687,9 @@ def describe_signature(self, signode: TextElement, mode: str,
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):
Expand Down Expand Up @@ -2572,7 +2579,15 @@ def _parse_parameters(self, paramMode: str) -> ASTParameters:
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."""
Expand Down
20 changes: 18 additions & 2 deletions sphinx/domains/cpp.py
Expand Up @@ -1879,7 +1879,8 @@ def describe_signature(self, signode: TextElement, mode: str,
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
Expand All @@ -1888,6 +1889,7 @@ def __init__(self, args: List[ASTFunctionParameter], volatile: bool, const: bool
self.trailingReturn = trailingReturn
self.override = override
self.final = final
self.attrs = attrs
self.initializer = initializer

@property
Expand Down Expand Up @@ -1947,6 +1949,9 @@ def _stringify(self, transform: StringifyTransform) -> str:
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)
Expand Down Expand Up @@ -1988,6 +1993,9 @@ def _add_text(signode: TextElement, text: str) -> None:
_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))

Expand Down Expand Up @@ -5709,6 +5717,13 @@ def _parse_parameters_and_qualifiers(self, paramMode: str) -> ASTParametersQuali
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('='):
Expand All @@ -5725,7 +5740,7 @@ def _parse_parameters_and_qualifiers(self, paramMode: str) -> ASTParametersQuali

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."""
Expand Down Expand Up @@ -6251,6 +6266,7 @@ def parser() -> ASTExpression:
# ==========================================================================

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()
Expand Down
6 changes: 6 additions & 0 deletions sphinx/ext/autodoc/__init__.py
Expand Up @@ -1613,6 +1613,9 @@ def add_directive_header(self, sig: str) -> None:
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]))
Expand Down Expand Up @@ -1986,6 +1989,9 @@ def add_directive_header(self, sig: str) -> None:
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]))
Expand Down
7 changes: 6 additions & 1 deletion sphinx/ext/napoleon/__init__.py
Expand Up @@ -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
Expand Down Expand Up @@ -237,9 +238,12 @@ def __unicode__(self):
: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.
Expand Down Expand Up @@ -268,6 +272,7 @@ def __unicode__(self):
'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')
}
Expand Down
11 changes: 6 additions & 5 deletions sphinx/ext/napoleon/docstring.py
Expand Up @@ -1104,11 +1104,12 @@ def _consume_field(self, parse_type: bool = True, prefer_type: bool = False
_name, _type = line, ''
_name, _type = _name.strip(), _type.strip()
_name = self._escape_args_and_kwargs(_name)
_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 {},
)

if prefer_type and not _type:
_type, _name = _name, _type
Expand Down
2 changes: 1 addition & 1 deletion sphinx/util/cfamily.py
Expand Up @@ -391,7 +391,7 @@ def _parse_balanced_token_seq(self, end: List[str]) -> str:
% 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
Expand Down
9 changes: 4 additions & 5 deletions tests/test_domain_c.py
Expand Up @@ -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)',
Expand Down
7 changes: 4 additions & 3 deletions tests/test_domain_cpp.py
Expand Up @@ -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"})
Expand Down Expand Up @@ -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():
Expand Down

0 comments on commit b2d524d

Please sign in to comment.