Merge branch '5.x'

This commit is contained in:
Jean-François B
2022-08-06 18:31:14 +02:00
148 changed files with 16835 additions and 16164 deletions

View File

@@ -30,6 +30,7 @@ Contributors
* Antonio Valentino -- qthelp builder, docstring inheritance
* Antti Kaihola -- doctest extension (skipif option)
* Barry Warsaw -- setup command improvements
* Ben Egan -- Napoleon improvements
* Benjamin Peterson -- unittests
* Blaise Laflamme -- pyramid theme
* Bruce Mitchener -- Minor epub improvement

10
CHANGES
View File

@@ -42,6 +42,10 @@ Features added
Bugs fixed
----------
- #10257: C++, ensure consistent non-specialization template argument
representation.
- #10729: C++, fix parsing of certain non-type template parameter packs.
Testing
--------
@@ -60,9 +64,15 @@ Deprecated
Features added
--------------
* #10738: napoleon: Add support for docstring types using 'of', like
``type of type``. Example: ``tuple of int``.
Bugs fixed
----------
* #10723: LaTeX: 5.1.0 has made the 'sphinxsetup' ``verbatimwithframe=false``
become without effect.
Testing
--------

View File

@@ -121,7 +121,7 @@ class RecipeDomain(Domain):
def get_objects(self):
for obj in self.data['recipes']:
yield(obj)
yield obj
def resolve_xref(self, env, fromdocname, builder, typ, target, node,
contnode):

View File

@@ -192,7 +192,7 @@ contents:
steps:
- uses: actions/checkout@v3
- name: Build HTML
uses: ammaraskar/sphinx-action@0.4
uses: ammaraskar/sphinx-action@master
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:

View File

@@ -182,8 +182,6 @@ tends to use more horizontal space. Google style tends to be easier to
read for short and simple docstrings, whereas NumPy style tends be easier
to read for long and in-depth docstrings.
The `Khan Academy`_ recommends using Google style.
The choice between styles is largely aesthetic, but the two styles should
not be mixed. Choose one style for your project and be consistent with it.

View File

@@ -31,10 +31,76 @@ ignore_missing_imports = True
follow_imports = skip
check_untyped_defs = True
warn_unused_ignores = True
strict_optional = False
strict_optional = True
no_implicit_optional = True
warn_redundant_casts = True
[mypy-sphinx.application]
strict_optional = False
[mypy-sphinx.builders]
strict_optional = False
[mypy-sphinx.builders.gettext]
strict_optional = False
[mypy-sphinx.builders.html]
strict_optional = False
[mypy-sphinx.builders.latex.*]
strict_optional = False
[mypy-sphinx.builders.linkcheck]
strict_optional = False
[mypy-sphinx.builders.singlehtml]
strict_optional = False
[mypy-sphinx.cmd.*]
strict_optional = False
[mypy-sphinx.directives]
strict_optional = False
[mypy-sphinx.directives.code]
strict_optional = False
[mypy-sphinx.domains.*]
strict_optional = False
[mypy-sphinx.environment.*]
strict_optional = False
[mypy-sphinx.ext.*]
strict_optional = False
[mypy-sphinx.locale]
strict_optional = False
[mypy-sphinx.pycode.parser]
strict_optional = False
[mypy-sphinx.registry.*]
strict_optional = False
[mypy-sphinx.search]
strict_optional = False
[mypy-sphinx.setup_command]
strict_optional = False
[mypy-sphinx.testing.util]
strict_optional = False
[mypy-sphinx.transforms.*]
strict_optional = False
[mypy-sphinx.util.*]
strict_optional = False
[mypy-sphinx.writers.*]
strict_optional = False
[tool:pytest]
filterwarnings =
all

View File

@@ -1,6 +1,6 @@
"""Additional docutils nodes."""
from typing import TYPE_CHECKING, Any, Dict, List, Sequence
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence
import docutils
from docutils import nodes
@@ -27,7 +27,7 @@ class document(nodes.document):
in your extensions. It will be removed without deprecation period.
"""
def set_id(self, node: Element, msgnode: Element = None,
def set_id(self, node: Element, msgnode: Optional[Element] = None,
suggested_prefix: str = '') -> str:
if docutils.__version_info__ >= (0, 16):
ret = super().set_id(node, msgnode, suggested_prefix) # type: ignore

View File

@@ -1018,7 +1018,7 @@ class StandaloneHTMLBuilder(Builder):
return quote(docname) + self.link_suffix
def handle_page(self, pagename: str, addctx: Dict, templatename: str = 'page.html',
outfilename: str = None, event_arg: Any = None) -> None:
outfilename: Optional[str] = None, event_arg: Any = None) -> None:
ctx = self.globalcontext.copy()
# current_page_name is backwards compatibility
ctx['pagename'] = ctx['current_page_name'] = pagename

View File

@@ -424,7 +424,7 @@ def correct_copyright_year(app: "Sphinx", config: Config) -> None:
config[k] = copyright_year_re.sub(replace, config[k])
def check_confval_types(app: "Sphinx", config: Config) -> None:
def check_confval_types(app: Optional["Sphinx"], config: Config) -> None:
"""Check all values for deviation from the default value's type, since
that can result in TypeErrors all over the place NB.
"""

View File

@@ -2604,6 +2604,10 @@ class ASTDeclaratorPtr(ASTDeclarator):
def name(self, name: ASTNestedName) -> None:
self.next.name = name
@property
def isPack(self) -> bool:
return self.next.isPack
@property
def function_params(self) -> List[ASTFunctionParameter]:
return self.next.function_params
@@ -2707,7 +2711,7 @@ class ASTDeclaratorRef(ASTDeclarator):
@property
def isPack(self) -> bool:
return True
return self.next.isPack
@property
def function_params(self) -> List[ASTFunctionParameter]:
@@ -2779,6 +2783,10 @@ class ASTDeclaratorParamPack(ASTDeclarator):
def trailingReturn(self) -> "ASTType":
return self.next.trailingReturn
@property
def isPack(self) -> bool:
return True
def require_space_after_declSpecs(self) -> bool:
return False
@@ -2835,6 +2843,10 @@ class ASTDeclaratorMemPtr(ASTDeclarator):
def name(self, name: ASTNestedName) -> None:
self.next.name = name
@property
def isPack(self):
return self.next.isPack
@property
def function_params(self) -> List[ASTFunctionParameter]:
return self.next.function_params
@@ -2932,6 +2944,10 @@ class ASTDeclaratorParen(ASTDeclarator):
def name(self, name: ASTNestedName) -> None:
self.inner.name = name
@property
def isPack(self):
return self.inner.isPack or self.next.isPack
@property
def function_params(self) -> List[ASTFunctionParameter]:
return self.inner.function_params
@@ -3510,6 +3526,14 @@ class ASTTemplateParam(ASTBase):
env: "BuildEnvironment", symbol: "Symbol") -> None:
raise NotImplementedError(repr(self))
@property
def isPack(self) -> bool:
raise NotImplementedError(repr(self))
@property
def name(self) -> ASTNestedName:
raise NotImplementedError(repr(self))
class ASTTemplateKeyParamPackIdDefault(ASTTemplateParam):
def __init__(self, key: str, identifier: ASTIdentifier,
@@ -3644,9 +3668,11 @@ class ASTTemplateParamTemplateType(ASTTemplateParam):
class ASTTemplateParamNonType(ASTTemplateParam):
def __init__(self,
param: Union[ASTTypeWithInit,
ASTTemplateParamConstrainedTypeWithInit]) -> None:
ASTTemplateParamConstrainedTypeWithInit],
parameterPack: bool = False) -> None:
assert param
self.param = param
self.parameterPack = parameterPack
@property
def name(self) -> ASTNestedName:
@@ -3655,7 +3681,7 @@ class ASTTemplateParamNonType(ASTTemplateParam):
@property
def isPack(self) -> bool:
return self.param.isPack
return self.param.isPack or self.parameterPack
def get_identifier(self) -> ASTIdentifier:
name = self.param.name
@@ -3676,14 +3702,22 @@ class ASTTemplateParamNonType(ASTTemplateParam):
# the anchor will be our parent
return symbol.parent.declaration.get_id(version, prefixed=None)
else:
return '_' + self.param.get_id(version)
res = '_'
if self.parameterPack:
res += 'Dp'
return res + self.param.get_id(version)
def _stringify(self, transform: StringifyTransform) -> str:
return transform(self.param)
res = transform(self.param)
if self.parameterPack:
res += '...'
return res
def describe_signature(self, signode: TextElement, mode: str,
env: "BuildEnvironment", symbol: "Symbol") -> None:
self.param.describe_signature(signode, mode, env, symbol)
if self.parameterPack:
signode += addnodes.desc_sig_punctuation('...', '...')
class ASTTemplateParams(ASTBase):
@@ -4129,6 +4163,31 @@ class LookupKey:
self.data = data
def _is_specialization(templateParams: Union[ASTTemplateParams, ASTTemplateIntroduction],
templateArgs: ASTTemplateArgs) -> bool:
# Checks if `templateArgs` does not exactly match `templateParams`.
# the names of the template parameters must be given exactly as args
# and params that are packs must in the args be the name expanded
if len(templateParams.params) != len(templateArgs.args):
return True
# having no template params and no arguments is also a specialization
if len(templateParams.params) == 0:
return True
for i in range(len(templateParams.params)):
param = templateParams.params[i]
arg = templateArgs.args[i]
# TODO: doing this by string manipulation is probably not the most efficient
paramName = str(param.name)
argTxt = str(arg)
isArgPackExpansion = argTxt.endswith('...')
if param.isPack != isArgPackExpansion:
return True
argName = argTxt[:-3] if isArgPackExpansion else argTxt
if paramName != argName:
return True
return False
class Symbol:
debug_indent = 0
debug_indent_string = " "
@@ -4177,6 +4236,16 @@ class Symbol:
self.siblingAbove: Symbol = None
self.siblingBelow: Symbol = None
self.identOrOp = identOrOp
# Ensure the same symbol for `A` is created for:
#
# .. cpp:class:: template <typename T> class A
#
# and
#
# .. cpp:function:: template <typename T> int A<T>::foo()
if (templateArgs is not None and
not _is_specialization(templateParams, templateArgs)):
templateArgs = None
self.templateParams = templateParams # template<templateParams>
self.templateArgs = templateArgs # identifier<templateArgs>
self.declaration = declaration
@@ -4357,33 +4426,12 @@ class Symbol:
Symbol.debug_print("correctPrimaryTemplateAargs:", correctPrimaryTemplateArgs)
Symbol.debug_print("searchInSiblings: ", searchInSiblings)
def isSpecialization() -> bool:
# the names of the template parameters must be given exactly as args
# and params that are packs must in the args be the name expanded
if len(templateParams.params) != len(templateArgs.args):
return True
# having no template params and no arguments is also a specialization
if len(templateParams.params) == 0:
return True
for i in range(len(templateParams.params)):
param = templateParams.params[i]
arg = templateArgs.args[i]
# TODO: doing this by string manipulation is probably not the most efficient
paramName = str(param.name)
argTxt = str(arg)
isArgPackExpansion = argTxt.endswith('...')
if param.isPack != isArgPackExpansion:
return True
argName = argTxt[:-3] if isArgPackExpansion else argTxt
if paramName != argName:
return True
return False
if correctPrimaryTemplateArgs:
if templateParams is not None and templateArgs is not None:
# If both are given, but it's not a specialization, then do lookup as if
# there is no argument list.
# For example: template<typename T> int A<T>::var;
if not isSpecialization():
if not _is_specialization(templateParams, templateArgs):
templateArgs = None
def matches(s: "Symbol") -> bool:
@@ -4812,7 +4860,7 @@ class Symbol:
if symbol.declaration is None:
if Symbol.debug_lookup:
Symbol.debug_print("empty candidate")
# if in the end we have non matching, but have an empty one,
# if in the end we have non-matching, but have an empty one,
# then just continue with that
ourChild = symbol
continue
@@ -4839,14 +4887,23 @@ class Symbol:
ourChild.declaration.directiveType, name)
logger.warning(msg, location=(otherChild.docname, otherChild.line))
else:
# Both have declarations, and in the same docname.
# This can apparently happen, it should be safe to
# just ignore it, right?
# Hmm, only on duplicate declarations, right?
msg = "Internal C++ domain error during symbol merging.\n"
msg += "ourChild:\n" + ourChild.to_string(1)
msg += "\notherChild:\n" + otherChild.to_string(1)
logger.warning(msg, location=otherChild.docname)
if (otherChild.declaration.objectType ==
ourChild.declaration.objectType and
otherChild.declaration.objectType in
('templateParam', 'functionParam') and
ourChild.parent.declaration == otherChild.parent.declaration):
# `ourChild` was just created during merging by the call
# to `_fill_empty` on the parent and can be ignored.
pass
else:
# Both have declarations, and in the same docname.
# This can apparently happen, it should be safe to
# just ignore it, right?
# Hmm, only on duplicate declarations, right?
msg = "Internal C++ domain error during symbol merging.\n"
msg += "ourChild:\n" + ourChild.to_string(1)
msg += "\notherChild:\n" + otherChild.to_string(1)
logger.warning(msg, location=otherChild.docname)
ourChild.merge_with(otherChild, docnames, env)
if Symbol.debug_lookup:
Symbol.debug_indent -= 2
@@ -5106,6 +5163,7 @@ class Symbol:
res.append(": ")
if self.isRedeclaration:
res.append('!!duplicate!! ')
res.append("{" + self.declaration.objectType + "} ")
res.append(str(self.declaration))
if self.docname:
res.append('\t(')
@@ -6727,7 +6785,7 @@ class DefinitionParser(BaseParser):
def _parse_template_parameter(self) -> ASTTemplateParam:
self.skip_ws()
if self.skip_word('template'):
# declare a tenplate template parameter
# declare a template template parameter
nestedParams = self._parse_template_parameter_list()
else:
nestedParams = None
@@ -6774,7 +6832,9 @@ class DefinitionParser(BaseParser):
# non-type parameter or constrained type parameter
self.pos = pos
param = self._parse_type_with_init('maybe', 'templateParam')
return ASTTemplateParamNonType(param)
self.skip_ws()
parameterPack = self.skip_string('...')
return ASTTemplateParamNonType(param, parameterPack)
except DefinitionError as eNonType:
self.pos = pos
header = "Error when parsing template parameter."
@@ -8089,7 +8149,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
return {
'version': 'builtin',
'env_version': 7,
'env_version': 8,
'parallel_read_safe': True,
'parallel_write_safe': True,
}

View File

@@ -378,7 +378,7 @@ class PyXrefMixin:
innernode: Type[TextlikeNode] = nodes.emphasis,
contnode: Node = None, env: BuildEnvironment = None,
inliner: Inliner = None, location: Node = None) -> List[Node]:
delims = r'(\s*[\[\]\(\),](?:\s*or\s)?\s*|\s+or\s+|\s*\|\s*|\.\.\.)'
delims = r'(\s*[\[\]\(\),](?:\s*o[rf]\s)?\s*|\s+o[rf]\s+|\s*\|\s*|\.\.\.)'
delims_re = re.compile(delims)
sub_targets = re.split(delims, target)

View File

@@ -246,8 +246,10 @@ class GoogleDocstring:
def _consume_indented_block(self, indent: int = 1) -> List[str]:
lines = []
line = self._lines.get(0)
while(not self._is_section_break() and
(not line or self._is_indented(line, indent))):
while (
not self._is_section_break() and
(not line or self._is_indented(line, indent))
):
lines.append(self._lines.next())
line = self._lines.get(0)
return lines

View File

@@ -181,7 +181,7 @@ def read_doc(app: "Sphinx", env: BuildEnvironment, filename: str) -> nodes.docum
writer=SphinxDummyWriter(),
source_class=SphinxFileInput,
destination=NullOutput())
pub.process_programmatic_settings(None, env.settings, None)
pub.process_programmatic_settings(None, env.settings, None) # type: ignore[arg-type]
pub.set_source(source_path=filename)
pub.publish()
return pub.document

View File

@@ -3,7 +3,7 @@
import pathlib
from os import path
from pprint import pformat
from typing import TYPE_CHECKING, Any, Callable, Dict, Iterator, List, Tuple, Union
from typing import TYPE_CHECKING, Any, Callable, Dict, Iterator, List, Optional, Tuple, Union
from jinja2 import BaseLoader, FileSystemLoader, TemplateNotFound
from jinja2.environment import Environment
@@ -142,7 +142,12 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
# TemplateBridge interface
def init(self, builder: "Builder", theme: Theme = None, dirs: List[str] = None) -> None:
def init(
self,
builder: "Builder",
theme: Optional[Theme] = None,
dirs: Optional[List[str]] = None
) -> None:
# create a chain of paths to search
if theme:
# the theme's own dir and its bases' dirs

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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