mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch '5.x'
This commit is contained in:
commit
6f530ca3ea
34
CHANGES
34
CHANGES
@ -36,12 +36,46 @@ Deprecated
|
|||||||
Features added
|
Features added
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
|
- #10286: C++, support requires clauses not just between the template
|
||||||
|
parameter lists and the declaration.
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
|
|
||||||
Testing
|
Testing
|
||||||
--------
|
--------
|
||||||
|
|
||||||
|
Release 5.1.2 (in development)
|
||||||
|
==============================
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
|
||||||
|
Incompatible changes
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Deprecated
|
||||||
|
----------
|
||||||
|
|
||||||
|
Features added
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Bugs fixed
|
||||||
|
----------
|
||||||
|
|
||||||
|
Testing
|
||||||
|
--------
|
||||||
|
|
||||||
|
Release 5.1.1 (released Jul 26, 2022)
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
Bugs fixed
|
||||||
|
----------
|
||||||
|
|
||||||
|
* #10701: Fix ValueError in the new ``deque`` based ``sphinx.ext.napolean``
|
||||||
|
iterator implementation.
|
||||||
|
* #10702: Restore compatability with third-party builders.
|
||||||
|
|
||||||
Release 5.1.0 (released Jul 24, 2022)
|
Release 5.1.0 (released Jul 24, 2022)
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
|
@ -89,10 +89,11 @@ class Builder:
|
|||||||
self.env: BuildEnvironment = env
|
self.env: BuildEnvironment = env
|
||||||
self.env.set_versioning_method(self.versioning_method,
|
self.env.set_versioning_method(self.versioning_method,
|
||||||
self.versioning_compare)
|
self.versioning_compare)
|
||||||
elif env is not Ellipsis:
|
else:
|
||||||
# ... is passed by SphinxComponentRegistry.create_builder to not show two warnings.
|
# ... is passed by SphinxComponentRegistry.create_builder to not show two warnings.
|
||||||
warnings.warn("The 'env' argument to Builder will be required from Sphinx 7.",
|
warnings.warn("The 'env' argument to Builder will be required from Sphinx 7.",
|
||||||
RemovedInSphinx70Warning, stacklevel=2)
|
RemovedInSphinx70Warning, stacklevel=2)
|
||||||
|
self.env = None
|
||||||
self.events: EventManager = app.events
|
self.events: EventManager = app.events
|
||||||
self.config: Config = app.config
|
self.config: Config = app.config
|
||||||
self.tags: Tags = app.tags
|
self.tags: Tags = app.tags
|
||||||
|
@ -3687,17 +3687,23 @@ class ASTTemplateParamNonType(ASTTemplateParam):
|
|||||||
|
|
||||||
|
|
||||||
class ASTTemplateParams(ASTBase):
|
class ASTTemplateParams(ASTBase):
|
||||||
def __init__(self, params: List[ASTTemplateParam]) -> None:
|
def __init__(self, params: List[ASTTemplateParam],
|
||||||
|
requiresClause: Optional["ASTRequiresClause"]) -> None:
|
||||||
assert params is not None
|
assert params is not None
|
||||||
self.params = params
|
self.params = params
|
||||||
|
self.requiresClause = requiresClause
|
||||||
|
|
||||||
def get_id(self, version: int) -> str:
|
def get_id(self, version: int, excludeRequires: bool = False) -> str:
|
||||||
assert version >= 2
|
assert version >= 2
|
||||||
res = []
|
res = []
|
||||||
res.append("I")
|
res.append("I")
|
||||||
for param in self.params:
|
for param in self.params:
|
||||||
res.append(param.get_id(version))
|
res.append(param.get_id(version))
|
||||||
res.append("E")
|
res.append("E")
|
||||||
|
if not excludeRequires and self.requiresClause:
|
||||||
|
res.append('IQ')
|
||||||
|
res.append(self.requiresClause.expr.get_id(version))
|
||||||
|
res.append('E')
|
||||||
return ''.join(res)
|
return ''.join(res)
|
||||||
|
|
||||||
def _stringify(self, transform: StringifyTransform) -> str:
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||||||
@ -3705,6 +3711,9 @@ class ASTTemplateParams(ASTBase):
|
|||||||
res.append("template<")
|
res.append("template<")
|
||||||
res.append(", ".join(transform(a) for a in self.params))
|
res.append(", ".join(transform(a) for a in self.params))
|
||||||
res.append("> ")
|
res.append("> ")
|
||||||
|
if self.requiresClause is not None:
|
||||||
|
res.append(transform(self.requiresClause))
|
||||||
|
res.append(" ")
|
||||||
return ''.join(res)
|
return ''.join(res)
|
||||||
|
|
||||||
def describe_signature(self, signode: TextElement, mode: str,
|
def describe_signature(self, signode: TextElement, mode: str,
|
||||||
@ -3719,6 +3728,9 @@ class ASTTemplateParams(ASTBase):
|
|||||||
first = False
|
first = False
|
||||||
param.describe_signature(signode, mode, env, symbol)
|
param.describe_signature(signode, mode, env, symbol)
|
||||||
signode += addnodes.desc_sig_punctuation('>', '>')
|
signode += addnodes.desc_sig_punctuation('>', '>')
|
||||||
|
if self.requiresClause is not None:
|
||||||
|
signode += addnodes.desc_sig_space()
|
||||||
|
self.requiresClause.describe_signature(signode, mode, env, symbol)
|
||||||
|
|
||||||
def describe_signature_as_introducer(
|
def describe_signature_as_introducer(
|
||||||
self, parentNode: desc_signature, mode: str, env: "BuildEnvironment",
|
self, parentNode: desc_signature, mode: str, env: "BuildEnvironment",
|
||||||
@ -3743,6 +3755,11 @@ class ASTTemplateParams(ASTBase):
|
|||||||
if lineSpec and not first:
|
if lineSpec and not first:
|
||||||
lineNode = makeLine(parentNode)
|
lineNode = makeLine(parentNode)
|
||||||
lineNode += addnodes.desc_sig_punctuation('>', '>')
|
lineNode += addnodes.desc_sig_punctuation('>', '>')
|
||||||
|
if self.requiresClause:
|
||||||
|
reqNode = addnodes.desc_signature_line()
|
||||||
|
reqNode.sphinx_line_type = 'requiresClause'
|
||||||
|
parentNode += reqNode
|
||||||
|
self.requiresClause.describe_signature(reqNode, 'markType', env, symbol)
|
||||||
|
|
||||||
|
|
||||||
# Template introducers
|
# Template introducers
|
||||||
@ -3861,11 +3878,23 @@ class ASTTemplateDeclarationPrefix(ASTBase):
|
|||||||
# templates is None means it's an explicit instantiation of a variable
|
# templates is None means it's an explicit instantiation of a variable
|
||||||
self.templates = templates
|
self.templates = templates
|
||||||
|
|
||||||
def get_id(self, version: int) -> str:
|
def get_requires_clause_in_last(self) -> Optional["ASTRequiresClause"]:
|
||||||
|
if self.templates is None:
|
||||||
|
return None
|
||||||
|
lastList = self.templates[-1]
|
||||||
|
if not isinstance(lastList, ASTTemplateParams):
|
||||||
|
return None
|
||||||
|
return lastList.requiresClause # which may be None
|
||||||
|
|
||||||
|
def get_id_except_requires_clause_in_last(self, version: int) -> str:
|
||||||
assert version >= 2
|
assert version >= 2
|
||||||
# this is not part of a normal name mangling system
|
# This is not part of the Itanium ABI mangling system.
|
||||||
res = []
|
res = []
|
||||||
for t in self.templates:
|
lastIndex = len(self.templates) - 1
|
||||||
|
for i, t in enumerate(self.templates):
|
||||||
|
if isinstance(t, ASTTemplateParams):
|
||||||
|
res.append(t.get_id(version, excludeRequires=(i == lastIndex)))
|
||||||
|
else:
|
||||||
res.append(t.get_id(version))
|
res.append(t.get_id(version))
|
||||||
return ''.join(res)
|
return ''.join(res)
|
||||||
|
|
||||||
@ -3889,7 +3918,7 @@ class ASTRequiresClause(ASTBase):
|
|||||||
def _stringify(self, transform: StringifyTransform) -> str:
|
def _stringify(self, transform: StringifyTransform) -> str:
|
||||||
return 'requires ' + transform(self.expr)
|
return 'requires ' + transform(self.expr)
|
||||||
|
|
||||||
def describe_signature(self, signode: addnodes.desc_signature_line, mode: str,
|
def describe_signature(self, signode: nodes.TextElement, mode: str,
|
||||||
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
env: "BuildEnvironment", symbol: "Symbol") -> None:
|
||||||
signode += addnodes.desc_sig_keyword('requires', 'requires')
|
signode += addnodes.desc_sig_keyword('requires', 'requires')
|
||||||
signode += addnodes.desc_sig_space()
|
signode += addnodes.desc_sig_space()
|
||||||
@ -3900,16 +3929,16 @@ class ASTRequiresClause(ASTBase):
|
|||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
class ASTDeclaration(ASTBase):
|
class ASTDeclaration(ASTBase):
|
||||||
def __init__(self, objectType: str, directiveType: str, visibility: str,
|
def __init__(self, objectType: str, directiveType: Optional[str] = None,
|
||||||
templatePrefix: ASTTemplateDeclarationPrefix,
|
visibility: Optional[str] = None,
|
||||||
requiresClause: ASTRequiresClause, declaration: Any,
|
templatePrefix: Optional[ASTTemplateDeclarationPrefix] = None,
|
||||||
trailingRequiresClause: ASTRequiresClause,
|
declaration: Any = None,
|
||||||
|
trailingRequiresClause: Optional[ASTRequiresClause] = None,
|
||||||
semicolon: bool = False) -> None:
|
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.requiresClause = requiresClause
|
|
||||||
self.declaration = declaration
|
self.declaration = declaration
|
||||||
self.trailingRequiresClause = trailingRequiresClause
|
self.trailingRequiresClause = trailingRequiresClause
|
||||||
self.semicolon = semicolon
|
self.semicolon = semicolon
|
||||||
@ -3920,11 +3949,10 @@ class ASTDeclaration(ASTBase):
|
|||||||
|
|
||||||
def clone(self) -> "ASTDeclaration":
|
def clone(self) -> "ASTDeclaration":
|
||||||
templatePrefixClone = self.templatePrefix.clone() if self.templatePrefix else None
|
templatePrefixClone = self.templatePrefix.clone() if self.templatePrefix else None
|
||||||
requiresClasueClone = self.requiresClause.clone() if self.requiresClause else None
|
|
||||||
trailingRequiresClasueClone = self.trailingRequiresClause.clone() \
|
trailingRequiresClasueClone = self.trailingRequiresClause.clone() \
|
||||||
if self.trailingRequiresClause else None
|
if self.trailingRequiresClause else None
|
||||||
return ASTDeclaration(self.objectType, self.directiveType, self.visibility,
|
return ASTDeclaration(self.objectType, self.directiveType, self.visibility,
|
||||||
templatePrefixClone, requiresClasueClone,
|
templatePrefixClone,
|
||||||
self.declaration.clone(), trailingRequiresClasueClone,
|
self.declaration.clone(), trailingRequiresClasueClone,
|
||||||
self.semicolon)
|
self.semicolon)
|
||||||
|
|
||||||
@ -3940,7 +3968,7 @@ class ASTDeclaration(ASTBase):
|
|||||||
|
|
||||||
def get_id(self, version: int, prefixed: bool = True) -> str:
|
def get_id(self, version: int, prefixed: bool = True) -> str:
|
||||||
if version == 1:
|
if version == 1:
|
||||||
if self.templatePrefix:
|
if self.templatePrefix or self.trailingRequiresClause:
|
||||||
raise NoOldIdError()
|
raise NoOldIdError()
|
||||||
if self.objectType == 'enumerator' and self.enumeratorScopedSymbol:
|
if self.objectType == 'enumerator' and self.enumeratorScopedSymbol:
|
||||||
return self.enumeratorScopedSymbol.declaration.get_id(version)
|
return self.enumeratorScopedSymbol.declaration.get_id(version)
|
||||||
@ -3952,16 +3980,31 @@ class ASTDeclaration(ASTBase):
|
|||||||
res = [_id_prefix[version]]
|
res = [_id_prefix[version]]
|
||||||
else:
|
else:
|
||||||
res = []
|
res = []
|
||||||
if self.templatePrefix:
|
# (See also https://github.com/sphinx-doc/sphinx/pull/10286#issuecomment-1168102147)
|
||||||
res.append(self.templatePrefix.get_id(version))
|
# The first implementation of requires clauses only supported a single clause after the
|
||||||
if self.requiresClause or self.trailingRequiresClause:
|
# template prefix, and no trailing clause. It put the ID after the template parameter
|
||||||
|
# list, i.e.,
|
||||||
|
# "I" + template_parameter_list_id + "E" + "IQ" + requires_clause_id + "E"
|
||||||
|
# but the second implementation associates the requires clause with each list, i.e.,
|
||||||
|
# "I" + template_parameter_list_id + "IQ" + requires_clause_id + "E" + "E"
|
||||||
|
# To avoid making a new ID version, we make an exception for the last requires clause
|
||||||
|
# in the template prefix, and still put it in the end.
|
||||||
|
# As we now support trailing requires clauses we add that as if it was a conjunction.
|
||||||
|
if self.templatePrefix is not None:
|
||||||
|
res.append(self.templatePrefix.get_id_except_requires_clause_in_last(version))
|
||||||
|
requiresClauseInLast = self.templatePrefix.get_requires_clause_in_last()
|
||||||
|
else:
|
||||||
|
requiresClauseInLast = None
|
||||||
|
|
||||||
|
if requiresClauseInLast or self.trailingRequiresClause:
|
||||||
if version < 4:
|
if version < 4:
|
||||||
raise NoOldIdError()
|
raise NoOldIdError()
|
||||||
res.append('IQ')
|
res.append('IQ')
|
||||||
if self.requiresClause and self.trailingRequiresClause:
|
if requiresClauseInLast and self.trailingRequiresClause:
|
||||||
|
# make a conjunction of them
|
||||||
res.append('aa')
|
res.append('aa')
|
||||||
if self.requiresClause:
|
if requiresClauseInLast:
|
||||||
res.append(self.requiresClause.expr.get_id(version))
|
res.append(requiresClauseInLast.expr.get_id(version))
|
||||||
if self.trailingRequiresClause:
|
if self.trailingRequiresClause:
|
||||||
res.append(self.trailingRequiresClause.expr.get_id(version))
|
res.append(self.trailingRequiresClause.expr.get_id(version))
|
||||||
res.append('E')
|
res.append('E')
|
||||||
@ -3978,9 +4021,6 @@ class ASTDeclaration(ASTBase):
|
|||||||
res.append(' ')
|
res.append(' ')
|
||||||
if self.templatePrefix:
|
if self.templatePrefix:
|
||||||
res.append(transform(self.templatePrefix))
|
res.append(transform(self.templatePrefix))
|
||||||
if self.requiresClause:
|
|
||||||
res.append(transform(self.requiresClause))
|
|
||||||
res.append(' ')
|
|
||||||
res.append(transform(self.declaration))
|
res.append(transform(self.declaration))
|
||||||
if self.trailingRequiresClause:
|
if self.trailingRequiresClause:
|
||||||
res.append(' ')
|
res.append(' ')
|
||||||
@ -4005,11 +4045,6 @@ class ASTDeclaration(ASTBase):
|
|||||||
self.templatePrefix.describe_signature(signode, mode, env,
|
self.templatePrefix.describe_signature(signode, mode, env,
|
||||||
symbol=self.symbol,
|
symbol=self.symbol,
|
||||||
lineSpec=options.get('tparam-line-spec'))
|
lineSpec=options.get('tparam-line-spec'))
|
||||||
if self.requiresClause:
|
|
||||||
reqNode = addnodes.desc_signature_line()
|
|
||||||
reqNode.sphinx_line_type = 'requiresClause'
|
|
||||||
signode.append(reqNode)
|
|
||||||
self.requiresClause.describe_signature(reqNode, 'markType', env, self.symbol)
|
|
||||||
signode += mainDeclNode
|
signode += mainDeclNode
|
||||||
if self.visibility and self.visibility != "public":
|
if self.visibility and self.visibility != "public":
|
||||||
mainDeclNode += addnodes.desc_sig_keyword(self.visibility, self.visibility)
|
mainDeclNode += addnodes.desc_sig_keyword(self.visibility, self.visibility)
|
||||||
@ -4192,7 +4227,7 @@ class Symbol:
|
|||||||
continue
|
continue
|
||||||
# only add a declaration if we our self are from a declaration
|
# only add a declaration if we our self are from a declaration
|
||||||
if self.declaration:
|
if self.declaration:
|
||||||
decl = ASTDeclaration('templateParam', None, None, None, None, tp, None)
|
decl = ASTDeclaration(objectType='templateParam', declaration=tp)
|
||||||
else:
|
else:
|
||||||
decl = None
|
decl = None
|
||||||
nne = ASTNestedNameElement(tp.get_identifier(), None)
|
nne = ASTNestedNameElement(tp.get_identifier(), None)
|
||||||
@ -4207,7 +4242,7 @@ class Symbol:
|
|||||||
if nn is None:
|
if nn is None:
|
||||||
continue
|
continue
|
||||||
# (comparing to the template params: we have checked that we are a declaration)
|
# (comparing to the template params: we have checked that we are a declaration)
|
||||||
decl = ASTDeclaration('functionParam', None, None, None, None, fp, None)
|
decl = ASTDeclaration(objectType='functionParam', declaration=fp)
|
||||||
assert not nn.rooted
|
assert not nn.rooted
|
||||||
assert len(nn.names) == 1
|
assert len(nn.names) == 1
|
||||||
self._add_symbols(nn, [], decl, self.docname, self.line)
|
self._add_symbols(nn, [], decl, self.docname, self.line)
|
||||||
@ -6504,6 +6539,13 @@ 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)
|
||||||
|
mustEnd = True
|
||||||
|
if outer == 'function':
|
||||||
|
# Allow trailing requires on functions.
|
||||||
|
self.skip_ws()
|
||||||
|
if re.compile(r'requires\b').match(self.definition, self.pos):
|
||||||
|
mustEnd = False
|
||||||
|
if mustEnd:
|
||||||
self.assert_end(allowSemicolon=True)
|
self.assert_end(allowSemicolon=True)
|
||||||
except DefinitionError as exUntyped:
|
except DefinitionError as exUntyped:
|
||||||
if outer == 'type':
|
if outer == 'type':
|
||||||
@ -6761,7 +6803,8 @@ class DefinitionParser(BaseParser):
|
|||||||
err = eParam
|
err = eParam
|
||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
if self.skip_string('>'):
|
if self.skip_string('>'):
|
||||||
return ASTTemplateParams(templateParams)
|
requiresClause = self._parse_requires_clause()
|
||||||
|
return ASTTemplateParams(templateParams, requiresClause)
|
||||||
elif self.skip_string(','):
|
elif self.skip_string(','):
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
@ -6883,6 +6926,8 @@ class DefinitionParser(BaseParser):
|
|||||||
return ASTTemplateDeclarationPrefix(None)
|
return ASTTemplateDeclarationPrefix(None)
|
||||||
else:
|
else:
|
||||||
raise e
|
raise e
|
||||||
|
if objectType == 'concept' and params.requiresClause is not None:
|
||||||
|
self.fail('requires-clause not allowed for concept')
|
||||||
else:
|
else:
|
||||||
params = self._parse_template_introduction()
|
params = self._parse_template_introduction()
|
||||||
if not params:
|
if not params:
|
||||||
@ -6931,7 +6976,7 @@ class DefinitionParser(BaseParser):
|
|||||||
|
|
||||||
newTemplates: List[Union[ASTTemplateParams, ASTTemplateIntroduction]] = []
|
newTemplates: List[Union[ASTTemplateParams, ASTTemplateIntroduction]] = []
|
||||||
for _i in range(numExtra):
|
for _i in range(numExtra):
|
||||||
newTemplates.append(ASTTemplateParams([]))
|
newTemplates.append(ASTTemplateParams([], requiresClause=None))
|
||||||
if templatePrefix and not isMemberInstantiation:
|
if templatePrefix and not isMemberInstantiation:
|
||||||
newTemplates.extend(templatePrefix.templates)
|
newTemplates.extend(templatePrefix.templates)
|
||||||
templatePrefix = ASTTemplateDeclarationPrefix(newTemplates)
|
templatePrefix = ASTTemplateDeclarationPrefix(newTemplates)
|
||||||
@ -6947,7 +6992,6 @@ class DefinitionParser(BaseParser):
|
|||||||
raise Exception('Internal error, unknown directiveType "%s".' % directiveType)
|
raise Exception('Internal error, unknown directiveType "%s".' % directiveType)
|
||||||
visibility = None
|
visibility = None
|
||||||
templatePrefix = None
|
templatePrefix = None
|
||||||
requiresClause = None
|
|
||||||
trailingRequiresClause = None
|
trailingRequiresClause = None
|
||||||
declaration: Any = None
|
declaration: Any = None
|
||||||
|
|
||||||
@ -6955,10 +6999,8 @@ class DefinitionParser(BaseParser):
|
|||||||
if self.match(_visibility_re):
|
if self.match(_visibility_re):
|
||||||
visibility = self.matched_text
|
visibility = self.matched_text
|
||||||
|
|
||||||
if objectType in ('type', 'concept', 'member', 'function', 'class'):
|
if objectType in ('type', 'concept', 'member', 'function', 'class', 'union'):
|
||||||
templatePrefix = self._parse_template_declaration_prefix(objectType)
|
templatePrefix = self._parse_template_declaration_prefix(objectType)
|
||||||
if objectType == 'function' and templatePrefix is not None:
|
|
||||||
requiresClause = self._parse_requires_clause()
|
|
||||||
|
|
||||||
if objectType == 'type':
|
if objectType == 'type':
|
||||||
prevErrors = []
|
prevErrors = []
|
||||||
@ -6984,7 +7026,6 @@ class DefinitionParser(BaseParser):
|
|||||||
declaration = self._parse_type_with_init(named=True, outer='member')
|
declaration = self._parse_type_with_init(named=True, outer='member')
|
||||||
elif objectType == 'function':
|
elif objectType == 'function':
|
||||||
declaration = self._parse_type(named=True, outer='function')
|
declaration = self._parse_type(named=True, outer='function')
|
||||||
if templatePrefix is not None:
|
|
||||||
trailingRequiresClause = self._parse_requires_clause()
|
trailingRequiresClause = self._parse_requires_clause()
|
||||||
elif objectType == 'class':
|
elif objectType == 'class':
|
||||||
declaration = self._parse_class()
|
declaration = self._parse_class()
|
||||||
@ -7003,7 +7044,7 @@ class DefinitionParser(BaseParser):
|
|||||||
self.skip_ws()
|
self.skip_ws()
|
||||||
semicolon = self.skip_string(';')
|
semicolon = self.skip_string(';')
|
||||||
return ASTDeclaration(objectType, directiveType, visibility,
|
return ASTDeclaration(objectType, directiveType, visibility,
|
||||||
templatePrefix, requiresClause, declaration,
|
templatePrefix, declaration,
|
||||||
trailingRequiresClause, semicolon)
|
trailingRequiresClause, semicolon)
|
||||||
|
|
||||||
def parse_namespace_object(self) -> ASTNamespace:
|
def parse_namespace_object(self) -> ASTNamespace:
|
||||||
@ -8048,7 +8089,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
'version': 'builtin',
|
'version': 'builtin',
|
||||||
'env_version': 6,
|
'env_version': 7,
|
||||||
'parallel_read_safe': True,
|
'parallel_read_safe': True,
|
||||||
'parallel_write_safe': True,
|
'parallel_write_safe': True,
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,11 @@ _SINGLETONS = ("None", "True", "False", "Ellipsis")
|
|||||||
|
|
||||||
|
|
||||||
class Deque(collections.deque):
|
class Deque(collections.deque):
|
||||||
"""A subclass of deque with an additional `.Deque.get` method."""
|
"""
|
||||||
|
A subclass of deque that mimics ``pockets.iterators.modify_iter``.
|
||||||
|
|
||||||
|
The `.Deque.get` and `.Deque.next` methods are added.
|
||||||
|
"""
|
||||||
|
|
||||||
sentinel = object()
|
sentinel = object()
|
||||||
|
|
||||||
@ -55,6 +59,12 @@ class Deque(collections.deque):
|
|||||||
"""
|
"""
|
||||||
return self[n] if n < len(self) else self.sentinel
|
return self[n] if n < len(self) else self.sentinel
|
||||||
|
|
||||||
|
def next(self) -> Any:
|
||||||
|
if self:
|
||||||
|
return super().popleft()
|
||||||
|
else:
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
|
||||||
def _convert_type_spec(_type: str, translations: Dict[str, str] = {}) -> str:
|
def _convert_type_spec(_type: str, translations: Dict[str, str] = {}) -> str:
|
||||||
"""Convert type specification to reference in reST."""
|
"""Convert type specification to reference in reST."""
|
||||||
@ -238,7 +248,7 @@ class GoogleDocstring:
|
|||||||
line = self._lines.get(0)
|
line = self._lines.get(0)
|
||||||
while(not self._is_section_break() and
|
while(not self._is_section_break() and
|
||||||
(not line or self._is_indented(line, indent))):
|
(not line or self._is_indented(line, indent))):
|
||||||
lines.append(self._lines.popleft())
|
lines.append(self._lines.next())
|
||||||
line = self._lines.get(0)
|
line = self._lines.get(0)
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
@ -247,20 +257,20 @@ class GoogleDocstring:
|
|||||||
while (self._lines and
|
while (self._lines and
|
||||||
self._lines.get(0) and
|
self._lines.get(0) and
|
||||||
not self._is_section_header()):
|
not self._is_section_header()):
|
||||||
lines.append(self._lines.popleft())
|
lines.append(self._lines.next())
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
def _consume_empty(self) -> List[str]:
|
def _consume_empty(self) -> List[str]:
|
||||||
lines = []
|
lines = []
|
||||||
line = self._lines.get(0)
|
line = self._lines.get(0)
|
||||||
while self._lines and not line:
|
while self._lines and not line:
|
||||||
lines.append(self._lines.popleft())
|
lines.append(self._lines.next())
|
||||||
line = self._lines.get(0)
|
line = self._lines.get(0)
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
def _consume_field(self, parse_type: bool = True, prefer_type: bool = False
|
def _consume_field(self, parse_type: bool = True, prefer_type: bool = False
|
||||||
) -> Tuple[str, str, List[str]]:
|
) -> Tuple[str, str, List[str]]:
|
||||||
line = self._lines.popleft()
|
line = self._lines.next()
|
||||||
|
|
||||||
before, colon, after = self._partition_field_on_colon(line)
|
before, colon, after = self._partition_field_on_colon(line)
|
||||||
_name, _type, _desc = before, '', after
|
_name, _type, _desc = before, '', after
|
||||||
@ -298,7 +308,7 @@ class GoogleDocstring:
|
|||||||
return fields
|
return fields
|
||||||
|
|
||||||
def _consume_inline_attribute(self) -> Tuple[str, List[str]]:
|
def _consume_inline_attribute(self) -> Tuple[str, List[str]]:
|
||||||
line = self._lines.popleft()
|
line = self._lines.next()
|
||||||
_type, colon, _desc = self._partition_field_on_colon(line)
|
_type, colon, _desc = self._partition_field_on_colon(line)
|
||||||
if not colon or not _desc:
|
if not colon or not _desc:
|
||||||
_type, _desc = _desc, _type
|
_type, _desc = _desc, _type
|
||||||
@ -336,7 +346,7 @@ class GoogleDocstring:
|
|||||||
return lines
|
return lines
|
||||||
|
|
||||||
def _consume_section_header(self) -> str:
|
def _consume_section_header(self) -> str:
|
||||||
section = self._lines.popleft()
|
section = self._lines.next()
|
||||||
stripped_section = section.strip(':')
|
stripped_section = section.strip(':')
|
||||||
if stripped_section.lower() in self._sections:
|
if stripped_section.lower() in self._sections:
|
||||||
section = stripped_section
|
section = stripped_section
|
||||||
@ -345,14 +355,14 @@ class GoogleDocstring:
|
|||||||
def _consume_to_end(self) -> List[str]:
|
def _consume_to_end(self) -> List[str]:
|
||||||
lines = []
|
lines = []
|
||||||
while self._lines:
|
while self._lines:
|
||||||
lines.append(self._lines.popleft())
|
lines.append(self._lines.next())
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
def _consume_to_next_section(self) -> List[str]:
|
def _consume_to_next_section(self) -> List[str]:
|
||||||
self._consume_empty()
|
self._consume_empty()
|
||||||
lines = []
|
lines = []
|
||||||
while not self._is_section_break():
|
while not self._is_section_break():
|
||||||
lines.append(self._lines.popleft())
|
lines.append(self._lines.next())
|
||||||
return lines + self._consume_empty()
|
return lines + self._consume_empty()
|
||||||
|
|
||||||
def _dedent(self, lines: List[str], full: bool = False) -> List[str]:
|
def _dedent(self, lines: List[str], full: bool = False) -> List[str]:
|
||||||
@ -1155,7 +1165,7 @@ class NumpyDocstring(GoogleDocstring):
|
|||||||
|
|
||||||
def _consume_field(self, parse_type: bool = True, prefer_type: bool = False
|
def _consume_field(self, parse_type: bool = True, prefer_type: bool = False
|
||||||
) -> Tuple[str, str, List[str]]:
|
) -> Tuple[str, str, List[str]]:
|
||||||
line = self._lines.popleft()
|
line = self._lines.next()
|
||||||
if parse_type:
|
if parse_type:
|
||||||
_name, _, _type = self._partition_field_on_colon(line)
|
_name, _, _type = self._partition_field_on_colon(line)
|
||||||
else:
|
else:
|
||||||
@ -1186,10 +1196,10 @@ class NumpyDocstring(GoogleDocstring):
|
|||||||
return self._consume_fields(prefer_type=True)
|
return self._consume_fields(prefer_type=True)
|
||||||
|
|
||||||
def _consume_section_header(self) -> str:
|
def _consume_section_header(self) -> str:
|
||||||
section = self._lines.popleft()
|
section = self._lines.next()
|
||||||
if not _directive_regex.match(section):
|
if not _directive_regex.match(section):
|
||||||
# Consume the header underline
|
# Consume the header underline
|
||||||
self._lines.popleft()
|
self._lines.next()
|
||||||
return section
|
return section
|
||||||
|
|
||||||
def _is_section_break(self) -> bool:
|
def _is_section_break(self) -> bool:
|
||||||
|
@ -161,7 +161,7 @@ class SphinxComponentRegistry:
|
|||||||
f"'env'argument. Report this bug to the developers of your custom builder, "
|
f"'env'argument. Report this bug to the developers of your custom builder, "
|
||||||
f"this is likely not a issue with Sphinx. The 'env' argument will be required "
|
f"this is likely not a issue with Sphinx. The 'env' argument will be required "
|
||||||
f"from Sphinx 7.", RemovedInSphinx70Warning, stacklevel=2)
|
f"from Sphinx 7.", RemovedInSphinx70Warning, stacklevel=2)
|
||||||
builder = self.builders[name](app, env=...) # type: ignore[arg-type]
|
builder = self.builders[name](app)
|
||||||
if env is not None:
|
if env is not None:
|
||||||
builder.set_environment(env)
|
builder.set_environment(env)
|
||||||
return builder
|
return builder
|
||||||
|
@ -891,8 +891,33 @@ def test_domain_cpp_ast_requires_clauses():
|
|||||||
{4: 'I0EIQaa1A1BE1fvv'})
|
{4: 'I0EIQaa1A1BE1fvv'})
|
||||||
check('function', 'template<typename T> requires A || B or C void f()',
|
check('function', 'template<typename T> requires A || B or C void f()',
|
||||||
{4: 'I0EIQoo1Aoo1B1CE1fvv'})
|
{4: 'I0EIQoo1Aoo1B1CE1fvv'})
|
||||||
|
check('function', 'void f() requires A || B || C',
|
||||||
|
{4: 'IQoo1Aoo1B1CE1fv'})
|
||||||
|
check('function', 'Foo() requires A || B || C',
|
||||||
|
{4: 'IQoo1Aoo1B1CE3Foov'})
|
||||||
check('function', 'template<typename T> requires A && B || C and D void f()',
|
check('function', 'template<typename T> requires A && B || C and D void f()',
|
||||||
{4: 'I0EIQooaa1A1Baa1C1DE1fvv'})
|
{4: 'I0EIQooaa1A1Baa1C1DE1fvv'})
|
||||||
|
check('function',
|
||||||
|
'template<typename T> requires R<T> ' +
|
||||||
|
'template<typename U> requires S<T> ' +
|
||||||
|
'void A<T>::f() requires B',
|
||||||
|
{4: 'I0EIQ1RI1TEEI0EIQaa1SI1TE1BEN1AI1TE1fEvv'})
|
||||||
|
check('function',
|
||||||
|
'template<template<typename T> requires R<T> typename X> ' +
|
||||||
|
'void f()',
|
||||||
|
{2: 'II0EIQ1RI1TEE0E1fv', 4: 'II0EIQ1RI1TEE0E1fvv'})
|
||||||
|
check('type',
|
||||||
|
'template<typename T> requires IsValid<T> {key}T = true_type',
|
||||||
|
{4: 'I0EIQ7IsValidI1TEE1T'}, key='using')
|
||||||
|
check('class',
|
||||||
|
'template<typename T> requires IsValid<T> {key}T : Base',
|
||||||
|
{4: 'I0EIQ7IsValidI1TEE1T'}, key='class')
|
||||||
|
check('union',
|
||||||
|
'template<typename T> requires IsValid<T> {key}T',
|
||||||
|
{4: 'I0EIQ7IsValidI1TEE1T'}, key='union')
|
||||||
|
check('member',
|
||||||
|
'template<typename T> requires IsValid<T> int Val = 7',
|
||||||
|
{4: 'I0EIQ7IsValidI1TEE3Val'})
|
||||||
|
|
||||||
|
|
||||||
def test_domain_cpp_ast_template_args():
|
def test_domain_cpp_ast_template_args():
|
||||||
|
Loading…
Reference in New Issue
Block a user