'doctree-read': 'the doctree before being pickled',     'env-merge-info': 'env, read docnames, other env instance',     'missing-reference': 'env, node, contnode',    'warn-missing-reference': 'domain, node',     'doctree-resolved': 'doctree, docname',     'env-updated': 'env',     'html-collect-pages': 'builder',diff --git a/sphinx/transforms/post_transforms/__init__.py b/sphinx/transforms/post_transforms/__init__.py-- a/sphinx/transforms/post_transforms/__init__.py++ b/sphinx/transforms/post_transforms/__init__.py


warn = False         if not warn:             return        if domain and typ in domain.dangling_warnings:        if self.app.emit_firstresult('warn-missing-reference', domain, node):            return        elif domain and typ in domain.dangling_warnings:             msg = domain.dangling_warnings[typ]         elif node.get('refdomain', 'std') not in ('', 'std'):             msg = (__('%s:%s reference target not found: %%(target)s') %


napoleon_use_param = True         napoleon_use_rtype = True         napoleon_use_keyword = True<ins>        napoleon_preprocess_types = False</ins>         napoleon_type_aliases = None         napoleon_custom_sections = None


: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.


'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')     }diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py-- a/sphinx/ext/napoleon/docstring.py++ b/sphinx/ext/napoleon/docstring.py


_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


from collections import deque from io import StringIO from os import pathfrom typing import Any, Callable, Dict, IO, List, Tuple, Unionfrom typing import Any, Callable, Dict, IO, List, Optional, Tuple, Union  from docutils import nodes from docutils.nodes import Element, TextElement


if catalog.domain == 'sphinx' and catalog.is_outdated():                     catalog.write_mo(self.config.language)             locale_dirs = [None, path.join(package_dir, 'locale')] + list(repo.locale_dirs)            locale_dirs = [None]  # type: List[Optional[str]]            locale_dirs += list(repo.locale_dirs)            locale_dirs += [path.join(package_dir, 'locale')]             self.translator, has_translation = locale.init(locale_dirs, self.config.language)             if has_translation or self.config.language == 'en':                 # "en" never needs to be translateddiff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py-- a/sphinx/locale/__init__.py++ b/sphinx/locale/__init__.py


translators = defaultdict(NullTranslations)  # type: Dict[Tuple[str, str], NullTranslations]  def init(locale_dirs: List[str], language: str,def init(locale_dirs: List[Optional[str]], language: str,          catalog: str = 'sphinx', namespace: str = 'general') -> Tuple[NullTranslations, bool]:     """Look for message catalogs in `locale_dirs` and *ensure* that there is at     least a NullTranslations catalog set in `translators`. If called multiple


return None  <ins>class ObjectMember(tuple):    """A member of object.    This is used for the result of `Documenter.get_object_members()` to    represent each member of the object.    .. Note::       An instance of this class behaves as a tuple of (name, object)       for compatibility to old Sphinx.  The behavior will be dropped       in the future.  Therefore extensions should not use the tuple       interface.    """    def __new__(cls, name: str, obj: Any, **kwargs: Any) -> Any:        return super().__new__(cls, (name, obj))  # type: ignore    def __init__(self, name: str, obj: Any, skipped: bool = False) -> None:        self.__name__ = name        self.object = obj        self.skipped = skippedObjectMembers = Union[List[ObjectMember], List[Tuple[str, Any]]]</ins> class Documenter:     """     A Documenter knows how to autodocument a single object type.  When


for line, src in zip(more_content.data, more_content.items):                 self.add_line(line, src[0], src[1])     def get_object_members(self, want_all: bool) -> Tuple[bool, List[Tuple[str, Any]]]:    def get_object_members(self, want_all: bool) -> Tuple[bool, ObjectMembers]:         """Return `(members_check_module, members)` where `members` is a         list of `(membername, member)` pairs of the members of *self.object*.


members = get_object_members(self.object, self.objpath, self.get_attr, self.analyzer)         if not want_all:             if not self.options.members:                return False, []                return False, []  # type: ignore             # specific members given             selected = []            for name in self.options.members:            for name in self.options.members:  # type: str                 if name in members:                     selected.append((name, members[name].value))                 else:


return False, [(m.name, m.value) for m in members.values()                            if m.directly_defined]     def filter_members(self, members: List[Tuple[str, Any]], want_all: bool    def filter_members(self, members: ObjectMembers, want_all: bool                        ) -> List[Tuple[str, Any, bool]]:         """Filter the given member list.


attr_docs = {}          # process members and determine which to skip        for (membername, member) in members:        for obj in members:            membername, member = obj             # if isattr is True, the member is documented as an attribute             if member is INSTANCEATTR:                 isattr = True


# ignore undocumented members if :undoc-members: is not given                     keep = has_doc or self.options.undoc_members <ins>            if isinstance(obj, ObjectMember) and obj.skipped:                # forcedly skipped member (ex. a module attribute not defined in __all__)                keep = False</ins>             # give the user a chance to decide whether this member             # should be skipped             if self.env.app:


if self.options.deprecated:             self.add_line('   :deprecated:', sourcename)     def get_object_members(self, want_all: bool) -> Tuple[bool, List[Tuple[str, Any]]]:    def get_object_members(self, want_all: bool) -> Tuple[bool, ObjectMembers]:         if want_all:            if self.__all__:                memberlist = self.__all__            else:            members = get_module_members(self.object)            if not self.__all__:                 # for implicit module members, check __module__ to avoid                 # documenting imported objects                return True, get_module_members(self.object)                return True, members            else:                ret = []                for name, value in members:                    if name in self.__all__:                        ret.append(ObjectMember(name, value))                    else:                        ret.append(ObjectMember(name, value, skipped=True))                return False, ret         else:             memberlist = self.options.members or []        ret = []        for mname in memberlist:            try:                ret.append((mname, safe_getattr(self.object, mname)))            except AttributeError:                logger.warning(                    __('missing attribute mentioned in :members: or __all__: '                       'module %s, attribute %s') %                    (safe_getattr(self.object, '__name__', '???'), mname),                    type='autodoc'                )        return False, ret            ret = []            for name in memberlist:                try:                    value = safe_getattr(self.object, name)                    ret.append(ObjectMember(name, value))                except AttributeError:                    logger.warning(__('missing attribute mentioned in :members: option: '                                      'module %s, attribute %s') %                                   (safe_getattr(self.object, '__name__', '???'), name),                                   type='autodoc')            return False, ret      def sort_members(self, documenters: List[Tuple["Documenter", bool]],                      order: str) -> List[Tuple["Documenter", bool]]:


self.env.app.emit('autodoc-process-docstring',                                   self.objtype, self.fullname, self.object,                                   self.options, docstringlines)<ins>                if docstringlines and docstringlines[-1] != '':                    # append a blank line to the end of the docstring                    docstringlines.append('')</ins>             yield from docstringlines      def get_sourcename(self) -> str:


return repr(annotation)      if getattr(annotation, '__args__', None):        if qualname == 'Union':        if not isinstance(annotation.__args__, (list, tuple)):            # broken __args__ found            pass        elif qualname == 'Union':             if len(annotation.__args__) > 1 and annotation.__args__[-1] is NoneType:                 if len(annotation.__args__) > 2:                     args = ', '.join(stringify(a) for a in annotation.__args__[:-1])


return "{" + ", ".join(self.visit(e) for e in node.elts) + "}"      def visit_Subscript(self, node: ast.Subscript) -> str:        return "%s[%s]" % (self.visit(node.value), self.visit(node.slice))        def is_simple_tuple(value: ast.AST) -> bool:            return (                isinstance(value, ast.Tuple) and                bool(value.elts) and                not any(isinstance(elt, ast.Starred) for elt in value.elts)            )        if is_simple_tuple(node.slice):            elts = ", ".join(self.visit(e) for e in node.slice.elts)  # type: ignore            return "%s[%s]" % (self.visit(node.value), elts)        elif isinstance(node.slice, ast.Index) and is_simple_tuple(node.slice.value):            elts = ", ".join(self.visit(e) for e in node.slice.value.elts)  # type: ignore            return "%s[%s]" % (self.visit(node.value), elts)        else:            return "%s[%s]" % (self.visit(node.value), self.visit(node.slice))      def visit_UnaryOp(self, node: ast.UnaryOp) -> str:         return "%s %s" % (self.visit(node.op), self.visit(node.operand))      def visit_Tuple(self, node: ast.Tuple) -> str:         if node.elts:            return ", ".join(self.visit(e) for e in node.elts)            return "(" + ", ".join(self.visit(e) for e in node.elts) + ")"         else:             return "()"


# Read the whole document and see if #anchor exists                     response = requests.get(req_url, stream=True, config=self.app.config,                                             auth=auth_info, **kwargs)<ins>                    response.raise_for_status()</ins>                     found = check_anchor(response, unquote(anchor))                      if not found:


from sphinx.util import progress_message from sphinx.util.console import darkgreen  # type: ignore from sphinx.util.nodes import inline_all_toctreesfrom sphinx.util.osutil import make_filename_from_projectfrom sphinx.util.osutil import ensuredir, make_filename_from_project from sphinx.writers.manpage import ManualPageWriter, ManualPageTranslator


docsettings.authors = authors             docsettings.section = section             targetname = '%s.%s' % (name, section)            if self.config.man_make_section_directory:                ensuredir(path.join(self.outdir, str(section)))                targetname = '%s/%s.%s' % (section, name, section)            else:                targetname = '%s.%s' % (name, section)             logger.info(darkgreen(targetname) + ' { ', nonl=True)             destination = FileOutput(                 destination_path=path.join(self.outdir, targetname),


app.add_config_value('man_pages', default_man_pages, None)     app.add_config_value('man_show_urls', False, None)<ins>    app.add_config_value('man_make_section_directory', False, None)</ins>      return {         'version': 'builtin',


return ast.parse(code, mode=mode)  def unparse(node: Optional[ast.AST]) -> Optional[str]:def unparse(node: Optional[ast.AST], code: str = '') -> Optional[str]:     """Unparse an AST to string."""     if node is None:         return None     elif isinstance(node, str):         return node    return _UnparseVisitor().visit(node)    return _UnparseVisitor(code).visit(node)   # a greatly cut-down version of `ast._Unparser` class _UnparseVisitor(ast.NodeVisitor):    def __init__(self, code: str = '') -> None:        self.code = code      def _visit_op(self, node: ast.AST) -> str:         return OPERATORS[node.__class__]


def visit_Constant(self, node: ast.Constant) -> str:             if node.value is Ellipsis:                 return "..."            elif isinstance(node.value, (int, float, complex)):                if self.code and sys.version_info > (3, 8):                    return ast.get_source_segment(self.code, node)                else:                    return repr(node.value)             else:                 return repr(node.value) diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py-- a/sphinx/util/inspect.py++ b/sphinx/util/inspect.py


def signature_from_str(signature: str) -> inspect.Signature:     """Create a Signature object from string."""    module = ast.parse('def func' + signature + ': pass')    code = 'def func' + signature + ': pass'    module = ast.parse(code)     function = cast(ast.FunctionDef, module.body[0])  # type: ignore     return signature_from_ast(function)    return signature_from_ast(function, code)  def signature_from_ast(node: ast.FunctionDef) -> inspect.Signature:def signature_from_ast(node: ast.FunctionDef, code: str = '') -> inspect.Signature:     """Create a Signature object from AST *node*."""     args = node.args     defaults = list(args.defaults)


if defaults[i] is Parameter.empty:                 default = Parameter.empty             else:                default = ast_unparse(defaults[i])                default = ast_unparse(defaults[i], code)             annotation = ast_unparse(arg.annotation) or Parameter.empty            annotation = ast_unparse(arg.annotation, code) or Parameter.empty             params.append(Parameter(arg.arg, Parameter.POSITIONAL_ONLY,                                     default=default, annotation=annotation))


if defaults[i + posonlyargs] is Parameter.empty:             default = Parameter.empty         else:            default = ast_unparse(defaults[i + posonlyargs])            default = ast_unparse(defaults[i + posonlyargs], code)         annotation = ast_unparse(arg.annotation) or Parameter.empty        annotation = ast_unparse(arg.annotation, code) or Parameter.empty         params.append(Parameter(arg.arg, Parameter.POSITIONAL_OR_KEYWORD,                                 default=default, annotation=annotation))      if args.vararg:        annotation = ast_unparse(args.vararg.annotation) or Parameter.empty        annotation = ast_unparse(args.vararg.annotation, code) or Parameter.empty         params.append(Parameter(args.vararg.arg, Parameter.VAR_POSITIONAL,                                 annotation=annotation))      for i, arg in enumerate(args.kwonlyargs):        default = ast_unparse(args.kw_defaults[i]) or Parameter.empty        annotation = ast_unparse(arg.annotation) or Parameter.empty        default = ast_unparse(args.kw_defaults[i], code) or Parameter.empty        annotation = ast_unparse(arg.annotation, code) or Parameter.empty         params.append(Parameter(arg.arg, Parameter.KEYWORD_ONLY, default=default,                                 annotation=annotation))      if args.kwarg:        annotation = ast_unparse(args.kwarg.annotation) or Parameter.empty        annotation = ast_unparse(args.kwarg.annotation, code) or Parameter.empty         params.append(Parameter(args.kwarg.arg, Parameter.VAR_KEYWORD,                                 annotation=annotation))     return_annotation = ast_unparse(node.returns) or Parameter.empty    return_annotation = ast_unparse(node.returns, code) or Parameter.empty      return inspect.Signature(params, return_annotation=return_annotation)


def format_signature(self, **kwargs: Any) -> str:         sigs = []        if self.analyzer and '.'.join(self.objpath) in self.analyzer.overloads:        if (self.analyzer and                '.'.join(self.objpath) in self.analyzer.overloads and                self.env.config.autodoc_typehints == 'signature'):             # Use signatures for overloaded functions instead of the implementation function.             overloaded = True         else:


sigs = []          overloads = self.get_overloaded_signatures()        if overloads:        if overloads and self.env.config.autodoc_typehints == 'signature':             # Use signatures for overloaded methods instead of the implementation method.             method = safe_getattr(self._signature_class, self._signature_method_name, None)             __globals__ = safe_getattr(method, '__globals__', {})


def format_signature(self, **kwargs: Any) -> str:         sigs = []        if self.analyzer and '.'.join(self.objpath) in self.analyzer.overloads:        if (self.analyzer and                '.'.join(self.objpath) in self.analyzer.overloads and                self.env.config.autodoc_typehints == 'signature'):             # Use signatures for overloaded methods instead of the implementation method.             overloaded = True         else:


app.add_config_value('man_pages', default_man_pages, None)     app.add_config_value('man_show_urls', False, None)    app.add_config_value('man_make_section_directory', False, None)    app.add_config_value('man_make_section_directory', True, None)      return {         'version': 'builtin',


def _private_without_docstring(self):         passclass ExamplePEP526Class:    """The summary line for a class docstring should fit on one line.    If the class has public attributes, they may be documented here    in an ``Attributes`` section and follow the same formatting as a    function's ``Args`` section. If ``napoleon_attr_annotations``    is True, types can be specified in the class body using ``PEP 526``    annotations.    Attributes:        attr1: Description of `attr1`.        attr2: Description of `attr2`.    """    attr1: str    attr2: int\ No newline at end of filediff --git a/sphinx/ext/napoleon/__init__.py b/sphinx/ext/napoleon/__init__.py-- a/sphinx/ext/napoleon/__init__.py++ b/sphinx/ext/napoleon/__init__.py


napoleon_preprocess_types = False         napoleon_type_aliases = None         napoleon_custom_sections = None<ins>        napoleon_attr_annotations = True</ins>      .. _Google style:        https://google.github.io/styleguide/pyguide.html


section. If the entry is a tuple/list/indexed container, the first entry         is the name of the section, the second is the section key to emulate. <ins>    napoleon_attr_annotations : :obj:`bool` (Defaults to True)        Use the type annotations of class attributes that are documented in the docstring        but do not have a type in the docstring.</ins>      """     _config_values = {


'napoleon_use_keyword': (True, 'env'),         'napoleon_preprocess_types': (False, 'env'),         'napoleon_type_aliases': (None, 'env'),        'napoleon_custom_sections': (None, 'env')        'napoleon_custom_sections': (None, 'env'),        'napoleon_attr_annotations': (True, 'env'),     }      def __init__(self, **settings: Any) -> None:diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py-- a/sphinx/ext/napoleon/docstring.py++ b/sphinx/ext/napoleon/docstring.py


from sphinx.ext.napoleon.iterators import modify_iter from sphinx.locale import _, __ from sphinx.util import logging<ins>from sphinx.util.inspect import stringify_annotationfrom sphinx.util.typing import get_type_hints</ins>  if False:     # For type annotation


def _parse_attributes_section(self, section: str) -> List[str]:         lines = []         for _name, _type, _desc in self._consume_fields():<ins>            if not _type:                _type = self._lookup_annotation(_name)</ins>             if self._config.napoleon_use_ivar:                 _name = self._qualify_name(_name, self._obj)                 field = ':ivar %s: ' % _name


lines = lines[start:end + 1]         return lines <ins>    def _lookup_annotation(self, _name: str) -> str:        if self._config.napoleon_attr_annotations:            if self._what in ("module", "class", "exception") and self._obj:                # cache the class annotations                if not hasattr(self, "_annotations"):                    localns = getattr(self._config, "autodoc_type_aliases", {})                    localns.update(getattr(                                   self._config, "napoleon_type_aliases", {}                                   ) or {})                    self._annotations = get_type_hints(self._obj, None, localns)                if _name in self._annotations:                    return stringify_annotation(self._annotations[_name])        # No annotation found        return ""</ins>  def _recombine_set_tokens(tokens: List[str]) -> List[str]:     token_queue = collections.deque(tokens)


_name, _type = _name.strip(), _type.strip()         _name = self._escape_args_and_kwargs(_name)         if parse_type and not _type:            _type = self._lookup_annotation(_name)         if prefer_type and not _type:             _type, _name = _name, _type diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py-- a/sphinx/util/typing.py++ b/sphinx/util/typing.py


from sphinx.util.inspect import safe_getattr  # lazy loading      try:        return typing.get_type_hints(obj, None, localns)        return typing.get_type_hints(obj, globalns, localns)     except NameError:         # Failed to evaluate ForwardRef (maybe TYPE_CHECKING)         return safe_getattr(obj, '__annotations__', {})


try:             self.env.app.emit('autodoc-before-process-signature', self.object, False)            sig = inspect.signature(self.object, follow_wrapped=True,            sig = inspect.signature(self.object,                                     type_aliases=self.env.config.autodoc_type_aliases)             args = stringify_signature(sig, **kwargs)         except TypeError as exc:


else:                     self.env.app.emit('autodoc-before-process-signature', self.object, True)                     sig = inspect.signature(self.object, bound_method=True,                                            follow_wrapped=True,                                             type_aliases=self.env.config.autodoc_type_aliases)                 args = stringify_signature(sig, **kwargs)         except TypeError as exc:diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py-- a/sphinx/util/inspect.py++ b/sphinx/util/inspect.py


return False  def signature(subject: Callable, bound_method: bool = False, follow_wrapped: bool = False,def signature(subject: Callable, bound_method: bool = False, follow_wrapped: bool = None,               type_aliases: Dict = {}) -> inspect.Signature:     """Return a Signature object for the given *subject*.      :param bound_method: Specify *subject* is a bound method or not     :param follow_wrapped: Same as ``inspect.signature()``.                           Defaults to ``False`` (get a signature of *subject*).     """    if follow_wrapped is None:        follow_wrapped = True    else:        warnings.warn('The follow_wrapped argument of sphinx.util.inspect.signature() is '                      'deprecated', RemovedInSphinx50Warning, stacklevel=2)     try:         try:             if _should_unwrap(subject):


if not self.options.annotation:             # obtain annotation for this data             try:                annotations = get_type_hints(self.parent)                annotations = get_type_hints(self.parent, None,                                             self.config.autodoc_type_aliases)             except NameError:                 # Failed to evaluate ForwardRef (maybe TYPE_CHECKING)                 annotations = safe_getattr(self.parent, '__annotations__', {})


if not self.options.annotation:             # obtain type annotation for this attribute             try:                annotations = get_type_hints(self.parent)                annotations = get_type_hints(self.parent, None,                                             self.config.autodoc_type_aliases)             except NameError:                 # Failed to evaluate ForwardRef (maybe TYPE_CHECKING)                 annotations = safe_getattr(self.parent, '__annotations__', {})


if callable(obj):             annotations = app.env.temp_data.setdefault('annotations', {})             annotation = annotations.setdefault(name, OrderedDict())            sig = inspect.signature(obj)            sig = inspect.signature(obj, type_aliases=app.config.autodoc_type_aliases)             for param in sig.parameters.values():                 if param.annotation is not param.empty:                     annotation[param.name] = typing.stringify(param.annotation)


if fignumber is None:                 return contnode         except ValueError:            logger.warning(__("no number is assigned for %s: %s"), figtype, labelid,                           location=node)            logger.warning(__("Failed to create a cross reference. Any number is not "                              "assigned: %s"),                           labelid, location=node)             return contnode          try:


from docutils import nodes from docutils.nodes import Nodefrom requests.exceptions import HTTPErrorfrom requests.exceptions import HTTPError, TooManyRedirects  from sphinx.application import Sphinx from sphinx.builders import Builder


config=self.app.config, auth=auth_info,                                                  **kwargs)                         response.raise_for_status()                    except HTTPError:                    except (HTTPError, TooManyRedirects):                         # retry with GET request if that fails, some servers                         # don't like HEAD requests.                         response = requests.get(req_url, stream=True, config=self.app.config,


class DataDocumenterMixinBase:     # define types of instance variables    parent = None  # type: Any     object = None  # type: Any    objpath = None  # type: List[str]      def should_suppress_directive_header(self) -> bool:         """Check directive header should be suppressed."""


super().__init__(*args, **kwargs)  class AttributeDocumenter(NewTypeMixin, TypeVarMixin,  # type: ignoreclass SlotsMixin(DataDocumenterMixinBase):    """    Mixin for AttributeDocumenter to provide the feature for supporting __slots__.    """    def isslotsattribute(self) -> bool:        """Check the subject is an attribute in __slots__."""        try:            __slots__ = inspect.getslots(self.parent)            if __slots__ and self.objpath[-1] in __slots__:                return True            else:                return False        except (AttributeError, ValueError):            return False    def import_object(self, raiseerror: bool = False) -> bool:        ret = super().import_object(raiseerror)  # type: ignore        if self.isslotsattribute():            self.object = SLOTSATTR        return ret    def should_suppress_directive_header(self) -> bool:        if self.object is SLOTSATTR:            self._datadescriptor = True            return True        else:            return super().should_suppress_directive_header()    def get_doc(self, encoding: str = None, ignore: int = None) -> List[List[str]]:        if self.object is SLOTSATTR:            try:                __slots__ = inspect.getslots(self.parent)                if __slots__ and __slots__.get(self.objpath[-1]):                    docstring = prepare_docstring(__slots__[self.objpath[-1]])                    return [docstring]                else:                    return []            except (AttributeError, ValueError) as exc:                logger.warning(__('Invalid __slots__ found on %s. Ignored.'),                               (self.parent.__qualname__, exc), type='autodoc')                return []        else:            return super().get_doc(encoding, ignore)  # type: ignoreclass AttributeDocumenter(NewTypeMixin, SlotsMixin, TypeVarMixin,  # type: ignore                           DocstringStripSignatureMixin, ClassLevelDocumenter):     """     Specialized Documenter subclass for attributes.


# must be higher than AttributeDocumenter     priority = 11     @classmethod    def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any                            ) -> bool:        """This documents only SLOTSATTR members."""        return member is SLOTSATTR    def import_object(self, raiseerror: bool = False) -> bool:        """Never import anything."""        # disguise as an attribute        self.objtype = 'attribute'        self._datadescriptor = True        with mock(self.config.autodoc_mock_imports):            try:                ret = import_object(self.modname, self.objpath[:-1], 'class',                                    attrgetter=self.get_attr,                                    warningiserror=self.config.autodoc_warningiserror)                self.module, _, _, self.parent = ret                return True            except ImportError as exc:                if raiseerror:                    raise                else:                    logger.warning(exc.args[0], type='autodoc', subtype='import_object')                    self.env.note_reread()                    return False    def get_doc(self, encoding: str = None, ignore: int = None) -> List[List[str]]:        """Decode and return lines of the docstring(s) for the object."""        if ignore is not None:            warnings.warn("The 'ignore' argument to autodoc.%s.get_doc() is deprecated."                          % self.__class__.__name__,                          RemovedInSphinx50Warning, stacklevel=2)        name = self.objpath[-1]        try:            __slots__ = inspect.getslots(self.parent)            if __slots__ and isinstance(__slots__.get(name, None), str):                docstring = prepare_docstring(__slots__[name])                return [docstring]            else:                return []        except (AttributeError, ValueError) as exc:            logger.warning(__('Invalid __slots__ found on %s. Ignored.'),                           (self.parent.__qualname__, exc), type='autodoc')            return []    def __init__(self, *args: Any, **kwargs: Any) -> None:        warnings.warn("%s is deprecated." % self.__class__.__name__,                      RemovedInSphinx50Warning, stacklevel=2)        super().__init__(*args, **kwargs)   class NewTypeAttributeDocumenter(AttributeDocumenter):


app.add_autodocumenter(AttributeDocumenter)     app.add_autodocumenter(PropertyDocumenter)     app.add_autodocumenter(InstanceAttributeDocumenter)    app.add_autodocumenter(SlotsAttributeDocumenter)     app.add_autodocumenter(NewTypeAttributeDocumenter)      app.add_config_value('autoclass_content', 'class', True, ENUM('both', 'class', 'init'))diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py-- a/sphinx/ext/autosummary/generate.py++ b/sphinx/ext/autosummary/generate.py


InstanceAttributeDocumenter, MethodDocumenter,                                     ModuleDocumenter, NewTypeAttributeDocumenter,                                     NewTypeDataDocumenter, PropertyDocumenter,                                    SingledispatchFunctionDocumenter, SlotsAttributeDocumenter)                                    SingledispatchFunctionDocumenter)     documenters = [         ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter,         FunctionDocumenter, MethodDocumenter, NewTypeAttributeDocumenter,         NewTypeDataDocumenter, AttributeDocumenter, InstanceAttributeDocumenter,        DecoratorDocumenter, PropertyDocumenter, SlotsAttributeDocumenter,        GenericAliasDocumenter, SingledispatchFunctionDocumenter,        DecoratorDocumenter, PropertyDocumenter, GenericAliasDocumenter,        SingledispatchFunctionDocumenter,     ]  # type: List[Type[Documenter]]     for documenter in documenters:         app.registry.add_documenter(documenter.objtype, documenter)


# RE for option descriptionsoption_desc_re = re.compile(r'((?:/|--|-|\+)?[^\s=[]+)(=?\s*.*)')option_desc_re = re.compile(r'((?:/|--|-|\+)?[^\s=]+)(=?\s*.*)') # RE for grammar tokens token_re = re.compile(r'`(\w+)`', re.U)


location=signode)                 continue             optname, args = m.groups()<ins>            if optname.endswith('[') and args.endswith(']'):                # optional value surrounded by brackets (ex. foo[=bar])                optname = optname[:-1]                args = '[' + args</ins>             if count:                 signode += addnodes.desc_addname(', ', ', ')             signode += addnodes.desc_name(optname, optname)


def default_latex_engine(config: Config) -> str:     """ Better default latex_engine settings for specific languages. """     if config.language == 'ja':        return 'platex'        return 'uplatex'     elif (config.language or '').startswith('zh'):         return 'xelatex'     elif config.language == 'el':


app.add_config_value('autodoc_mock_imports', [], True)     app.add_config_value('autodoc_typehints', "signature", True,                          ENUM("signature", "description", "none"))    app.add_config_value('autodoc_typehints_description_target', 'all', True,                         ENUM('all', 'documented'))     app.add_config_value('autodoc_type_aliases', {}, True)     app.add_config_value('autodoc_warningiserror', True, True)     app.add_config_value('autodoc_inherit_docstrings', True, True)diff --git a/sphinx/ext/autodoc/typehints.py b/sphinx/ext/autodoc/typehints.py-- a/sphinx/ext/autodoc/typehints.py++ b/sphinx/ext/autodoc/typehints.py


import re from collections import OrderedDictfrom typing import Any, Dict, Iterable, castfrom typing import Any, Dict, Iterable, Set, cast  from docutils import nodes from docutils.nodes import Element


return     if app.config.autodoc_typehints != 'description':         return<del>    if objtype == 'class' and app.config.autoclass_content not in ('init', 'both'):        return</del>      try:         signature = cast(addnodes.desc_signature, contentnode.parent[0])


field_lists.append(field_list)          for field_list in field_lists:            modify_field_list(field_list, annotations[fullname])            if app.config.autodoc_typehints_description_target == "all":                modify_field_list(field_list, annotations[fullname])            else:                augment_descriptions_with_types(field_list, annotations[fullname])   def insert_field_list(node: Element) -> nodes.field_list:


node += field  <ins>def augment_descriptions_with_types(    node: nodes.field_list,    annotations: Dict[str, str],) -> None:    fields = cast(Iterable[nodes.field], node)    has_description = set()  # type: Set[str]    has_type = set()  # type: Set[str]    for field in fields:        field_name = field[0].astext()        parts = re.split(' +', field_name)        if parts[0] == 'param':            if len(parts) == 2:                # :param xxx:                has_description.add(parts[1])            elif len(parts) > 2:                # :param xxx yyy:                name = ' '.join(parts[2:])                has_description.add(name)                has_type.add(name)        elif parts[0] == 'type':            name = ' '.join(parts[1:])            has_type.add(name)        elif parts[0] == 'return':            has_description.add('return')        elif parts[0] == 'rtype':            has_type.add('return')    # Add 'type' for parameters with a description but no declared type.    for name in annotations:        if name == 'return':            continue        if name in has_description and name not in has_type:            field = nodes.field()            field += nodes.field_name('', 'type ' + name)            field += nodes.field_body('', nodes.paragraph('', annotations[name]))            node += field    # Add 'rtype' if 'return' is present and 'rtype' isn't.    if 'return' in annotations:        if 'return' in has_description and 'return' not in has_type:            field = nodes.field()            field += nodes.field_name('', 'rtype')            field += nodes.field_body('', nodes.paragraph('', annotations['return']))            node += field</ins> def setup(app: Sphinx) -> Dict[str, Any]:     app.connect('autodoc-process-signature', record_typehints)     app.connect('object-description-transform', merge_typehints)


self.add_line('   ' + _('Bases: %s') % ', '.join(bases), sourcename)      def get_object_members(self, want_all: bool) -> Tuple[bool, ObjectMembers]:        members = get_class_members(self.object, self.objpath, self.get_attr, self.analyzer)        members = get_class_members(self.object, self.objpath, self.get_attr)         if not want_all:             if not self.options.members:                 return False, []  # type: ignorediff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py-- a/sphinx/ext/autodoc/importer.py++ b/sphinx/ext/autodoc/importer.py


from typing import Any, Callable, Dict, List, Mapping, NamedTuple, Optional, Tuple  from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_aliasfrom sphinx.pycode import ModuleAnalyzerfrom sphinx.pycode import ModuleAnalyzer, PycodeError from sphinx.util import logging from sphinx.util.inspect import (getannotations, getmro, getslots, isclass, isenumclass,                                  safe_getattr)


self.docstring = docstring  def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable,                      analyzer: ModuleAnalyzer = None) -> Dict[str, ClassAttribute]:def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable                      ) -> Dict[str, ClassAttribute]:     """Get members and attributes of target class."""     from sphinx.ext.autodoc import INSTANCEATTR


except AttributeError:             continue     # annotation only member (ex. attr: int)    for cls in getmro(subject):        try:            for name in getannotations(cls):                name = unmangle(cls, name)                if name and name not in members:                    members[name] = ClassAttribute(cls, name, INSTANCEATTR)        except AttributeError:            pass    if analyzer:        # append instance attributes (cf. self.attr1) if analyzer knows        namespace = '.'.join(objpath)        for (ns, name), docstring in analyzer.attr_docs.items():            if namespace == ns and name not in members:                members[name] = ClassAttribute(subject, name, INSTANCEATTR,                                               '\n'.join(docstring))    try:        for cls in getmro(subject):            # annotation only member (ex. attr: int)            try:                for name in getannotations(cls):                    name = unmangle(cls, name)                    if name and name not in members:                        members[name] = ClassAttribute(cls, name, INSTANCEATTR)            except AttributeError:                pass            # append instance attributes (cf. self.attr1) if analyzer knows            try:                modname = safe_getattr(cls, '__module__')                qualname = safe_getattr(cls, '__qualname__')                analyzer = ModuleAnalyzer.for_module(modname)                analyzer.analyze()                for (ns, name), docstring in analyzer.attr_docs.items():                    if ns == qualname and name not in members:                        members[name] = ClassAttribute(cls, name, INSTANCEATTR,                                                       '\n'.join(docstring))            except (AttributeError, PycodeError):                pass    except AttributeError:        pass      return members


result = super().make_xref(rolename, domain, target,  # type: ignore                                    innernode, contnode, env)         result['refspecific'] = True        result['py:module'] = env.ref_context.get('py:module')        result['py:class'] = env.ref_context.get('py:class')         if target.startswith(('.', '~')):             prefix, result['reftarget'] = target[0], target[1:]             if prefix == '.':diff --git a/sphinx/util/docfields.py b/sphinx/util/docfields.py-- a/sphinx/util/docfields.py++ b/sphinx/util/docfields.py


self.directive.domain,                         target,                         contnode=content[0],<ins>                        env=self.directive.state.document.settings.env</ins>                     )                     if _is_single_paragraph(field_body):                         paragraph = cast(nodes.paragraph, field_body[0])


'notes': self._parse_notes_section,                 'other parameters': self._parse_other_parameters_section,                 'parameters': self._parse_parameters_section,<ins>                'receive': self._parse_receives_section,                'receives': self._parse_receives_section,</ins>                 'return': self._parse_returns_section,                 'returns': self._parse_returns_section,                 'raise': self._parse_raises_section,


lines.append('')         return lines <ins>    def _parse_receives_section(self, section: str) -> List[str]:        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(_('Receives'), fields)</ins>     def _parse_references_section(self, section: str) -> List[str]:         use_admonition = self._config.napoleon_use_admonition_for_references         return self._parse_generic_section(_('References'), use_admonition)


from urllib.parse import unquote, urlparse  from docutils import nodesfrom docutils.nodes import Nodefrom docutils.nodes import Element, Node from requests import Response from requests.exceptions import HTTPError, TooManyRedirects


DEFAULT_DELAY = 60.0  <ins>def node_line_or_0(node: Element) -> int:    """    PriorityQueue items must be comparable. The line number is part of the    tuple used by the PriorityQueue, keep an homogeneous type for comparison.    """    return get_node_line(node) or 0</ins> class AnchorCheckParser(HTMLParser):     """Specialized HTML parser that looks for a specific anchor."""


if 'refuri' not in refnode:                 continue             uri = refnode['refuri']            lineno = get_node_line(refnode)            lineno = node_line_or_0(refnode)             uri_info = (CHECK_IMMEDIATELY, uri, docname, lineno)             self.wqueue.put(uri_info, False)             n += 1


for imgnode in doctree.traverse(nodes.image):             uri = imgnode['candidates'].get('?')             if uri and '://' in uri:                lineno = get_node_line(imgnode)                lineno = node_line_or_0(imgnode)                 uri_info = (CHECK_IMMEDIATELY, uri, docname, lineno)                 self.wqueue.put(uri_info, False)                 n += 1


from sphinx.deprecation import (RemovedInSphinx40Warning, RemovedInSphinx50Warning,                                 RemovedInSphinx60Warning) from sphinx.environment import BuildEnvironmentfrom sphinx.ext.autodoc.importer import (ClassAttribute, get_class_members, get_module_members,                                         get_object_members, import_module, import_object)from sphinx.ext.autodoc.importer import (ClassAttribute, get_class_members, get_object_members,                                         import_module, import_object) from sphinx.ext.autodoc.mock import mock from sphinx.locale import _, __ from sphinx.pycode import ModuleAnalyzer, PycodeError


if self.options.deprecated:             self.add_line('   :deprecated:', sourcename)     def get_module_members(self) -> Dict[str, ObjectMember]:        """Get members of target module."""        if self.analyzer:            attr_docs = self.analyzer.attr_docs        else:            attr_docs = {}        members = {}  # type: Dict[str, ObjectMember]        for name in dir(self.object):            try:                value = safe_getattr(self.object, name, None)                docstring = attr_docs.get(('', name), [])                members[name] = ObjectMember(name, value, docstring="\n".join(docstring))            except AttributeError:                continue        # annotation only member (ex. attr: int)        try:            for name in inspect.getannotations(self.object):                if name not in members:                    docstring = attr_docs.get(('', name), [])                    members[name] = ObjectMember(name, INSTANCEATTR,                                                 docstring="\n".join(docstring))        except AttributeError:            pass        return members     def get_object_members(self, want_all: bool) -> Tuple[bool, ObjectMembers]:        members = self.get_module_members()         if want_all:            members = get_module_members(self.object)             if not self.__all__:                 # for implicit module members, check __module__ to avoid                 # documenting imported objects                return True, members                return True, list(members.values())             else:                ret = []                for name, value in members:                    if name in self.__all__:                        ret.append(ObjectMember(name, value))                    else:                        ret.append(ObjectMember(name, value, skipped=True))                for member in members.values():                    if member.__name__ not in self.__all__:                        member.skipped = True                 return False, ret                return False, list(members.values())         else:             memberlist = self.options.members or []             ret = []             for name in memberlist:                try:                    value = safe_getattr(self.object, name)                    ret.append(ObjectMember(name, value))                except AttributeError:                if name in members:                    ret.append(members[name])                else:                     logger.warning(__('missing attribute mentioned in :members: option: '                                       'module %s, attribute %s') %                                    (safe_getattr(self.object, '__name__', '???'), name),diff --git a/sphinx/ext/autodoc/importer.py b/sphinx/ext/autodoc/importer.py-- a/sphinx/ext/autodoc/importer.py++ b/sphinx/ext/autodoc/importer.py


import warnings from typing import Any, Callable, Dict, List, Mapping, NamedTuple, Optional, Tuple from sphinx.deprecation import RemovedInSphinx40Warning, deprecated_aliasfrom sphinx.deprecation import (RemovedInSphinx40Warning, RemovedInSphinx50Warning,                                deprecated_alias) from sphinx.pycode import ModuleAnalyzer, PycodeError from sphinx.util import logging from sphinx.util.inspect import (getannotations, getmro, getslots, isclass, isenumclass,


"""Get members of target module."""     from sphinx.ext.autodoc import INSTANCEATTR <ins>    warnings.warn('sphinx.ext.autodoc.importer.get_module_members() is deprecated.',                  RemovedInSphinx50Warning)</ins>     members = {}  # type: Dict[str, Tuple[str, Any]]     for name in dir(module):         try:


def get_object_members(self, want_all: bool) -> Tuple[bool, ObjectMembers]:         members = self.get_module_members()         if want_all:            if not self.__all__:            if self.__all__ is None:                 # for implicit module members, check __module__ to avoid                 # documenting imported objects                 return True, list(members.values())


and :value: header will be suppressed unexpectedly.     """     def import_object(self, raiseerror: bool = False) -> bool:        ret = super().import_object(raiseerror)  # type: ignore        if ret and not inspect.isattributedescriptor(self.object):            self.non_data_descriptor = True        else:            self.non_data_descriptor = False        return ret     def should_suppress_value_header(self) -> bool:        return (inspect.isattributedescriptor(self.object) or        return (not getattr(self, 'non_data_descriptor', False) or                 super().should_suppress_directive_header())      def get_doc(self, encoding: str = None, ignore: int = None) -> List[List[str]]:        if not inspect.isattributedescriptor(self.object):        if getattr(self, 'non_data_descriptor', False):             # the docstring of non datadescriptor is very probably the wrong thing             # to display             return []         else:             return super().get_doc(encoding, ignore)  # type: ignore     def add_content(self, more_content: Optional[StringList], no_docstring: bool = False                    ) -> None:        if getattr(self, 'non_data_descriptor', False):            # the docstring of non datadescriptor is very probably the wrong thing            # to display            no_docstring = True        super().add_content(more_content, no_docstring=no_docstring)  # type: ignore  class SlotsMixin(DataDocumenterMixinBase):     """


After::         <literal class="kbd">        <literal class="kbd compound">             <literal class="kbd">                 Control             -


if len(parts) == 1:                 continue <ins>            node['classes'].append('compound')</ins>             node.pop()             while parts:                 key = parts.pop(0)


"""     default_priority = 400     builders = ('html',)    pattern = re.compile(r'(-|\+|\^|\s+)')    pattern = re.compile(r'(?<=.)(-|\+|\^|\s+)(?=.)')      def run(self, **kwargs: Any) -> None:         matcher = NodeMatcher(nodes.literal, classes=["kbd"])


import sys import typing<ins>from struct import Struct</ins> from typing import Any, Callable, Dict, Generator, List, Optional, Tuple, TypeVar, Union  from docutils import nodes


return ':obj:`None`'     elif cls is Ellipsis:         return '...'<ins>    elif cls is Struct:        # Before Python 3.9, struct.Struct class has incorrect __module__.        return ':class:`struct.Struct`'</ins>     elif inspect.isNewType(cls):         return ':class:`%s`' % cls.__name__     elif cls.__module__ in ('__builtin__', 'builtins'):


return annotation.__qualname__     elif annotation is Ellipsis:         return '...'<ins>    elif annotation is Struct:        # Before Python 3.9, struct.Struct class has incorrect __module__.        return 'struct.Struct'</ins>      if sys.version_info >= (3, 7):  # py37+         return _stringify_py37(annotation)


valid_names.extend(cls.__name__ for cls in self.object.__mro__)          docstrings = self.get_doc()<ins>        if docstrings is None:            return None, None</ins>         self._new_docstrings = docstrings[:]         self._signatures = []         result = None


def add_content(self, more_content: Optional[StringList], no_docstring: bool = False                     ) -> None:         if self.doc_as_attr:            more_content = StringList([_('alias of %s') % restify(self.object)], source='')            try:                more_content = StringList([_('alias of %s') % restify(self.object)], source='')            except AttributeError:                pass  # Invalid class object is passed.          super().add_content(more_content)


and :value: header will be suppressed unexpectedly.     """     def import_object(self, raiseerror: bool = False) -> bool:        ret = super().import_object(raiseerror)  # type: ignore        if ret and not inspect.isattributedescriptor(self.object):            self.non_data_descriptor = True        else:            self.non_data_descriptor = False        return ret     def should_suppress_value_header(self) -> bool:        return (inspect.isattributedescriptor(self.object) or        return (not getattr(self, 'non_data_descriptor', False) or                 super().should_suppress_directive_header())      def get_doc(self, encoding: str = None, ignore: int = None) -> Optional[List[List[str]]]:        if not inspect.isattributedescriptor(self.object):        if getattr(self, 'non_data_descriptor', False):             # the docstring of non datadescriptor is very probably the wrong thing             # to display            return []            return None         else:             return super().get_doc(encoding, ignore)  # type: ignore


return (self.object is UNINITIALIZED_ATTR or                 super().should_suppress_value_header()) <ins>    def get_doc(self, encoding: str = None, ignore: int = None) -> Optional[List[List[str]]]:        if self.object is UNINITIALIZED_ATTR:            return None        else:            return super().get_doc(encoding, ignore)  # type: ignore</ins>  class AttributeDocumenter(GenericAliasMixin, NewTypeMixin, SlotsMixin,  # type: ignore                           TypeVarMixin, RuntimeInstanceAttributeMixin,


return True         else:             doc = self.get_doc()            metadata = extract_metadata('\n'.join(sum(doc, [])))            if 'hide-value' in metadata:                return True            if doc:                metadata = extract_metadata('\n'.join(sum(doc, [])))                if 'hide-value' in metadata:                    return True          return False


'keyword', 'kwarg', 'kwparam'),                      typerolename='class', typenames=('paramtype', 'type'),                      can_collapse=True),        PyTypedField('variable', label=_('Variables'), rolename='obj',        PyTypedField('variable', label=_('Variables'),                      names=('var', 'ivar', 'cvar'),                      typerolename='class', typenames=('vartype',),                      can_collapse=True),


* To create a custom "generic" section, just pass a string.           * To create an alias for an existing section, pass a tuple containing the             alias name and the original, in that order.          * To create a custom section that displays like the parameters or returns            section, pass a tuple containing the custom section name and a string            value, "params_style" or "returns_style".          If an entry is just a string, it is interpreted as a header for a generic         section. If the entry is a tuple/list/indexed container, the first entry        is the name of the section, the second is the section key to emulate.        is the name of the section, the second is the section key to emulate. If the        second entry value is "params_style" or "returns_style", the custom section        will be displayed like the parameters section or returns section.      napoleon_attr_annotations : :obj:`bool` (Defaults to True)         Use the type annotations of class attributes that are documented in the docstringdiff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py-- a/sphinx/ext/napoleon/docstring.py++ b/sphinx/ext/napoleon/docstring.py


self._sections[entry.lower()] = self._parse_custom_generic_section                 else:                     # otherwise, assume entry is container;                    # [0] is new section, [1] is the section to alias.                    # in the case of key mismatch, just handle as generic section.                    self._sections[entry[0].lower()] = \                        self._sections.get(entry[1].lower(),                                           self._parse_custom_generic_section)                    if entry[1] == "params_style":                        self._sections[entry[0].lower()] = \                            self._parse_custom_params_style_section                    elif entry[1] == "returns_style":                        self._sections[entry[0].lower()] = \                            self._parse_custom_returns_style_section                    else:                        # [0] is new section, [1] is the section to alias.                        # in the case of key mismatch, just handle as generic section.                        self._sections[entry[0].lower()] = \                            self._sections.get(entry[1].lower(),                                               self._parse_custom_generic_section)      def _parse(self) -> None:         self._parsed_lines = self._consume_empty()


# for now, no admonition for simple custom sections         return self._parse_generic_section(section, False) <ins>    def _parse_custom_params_style_section(self, section: str) -> List[str]:        return self._format_fields(section, self._consume_fields())    def _parse_custom_returns_style_section(self, section: str) -> List[str]:        fields = self._consume_returns_section()        return self._format_fields(section, fields)</ins>     def _parse_usage_section(self, section: str) -> List[str]:         header = ['.. rubric:: Usage:', '']         block = ['.. code-block:: python', '']


"But `%r' is given." % source_suffix))  <ins>def convert_highlight_options(app: "Sphinx", config: Config) -> None:    """Convert old styled highlight_options to new styled one.    * old style: options    * new style: dict that maps language names to options    """    options = config.highlight_options    if options and not all(isinstance(v, dict) for v in options.values()):        # old styled option detected because all values are not dictionary.        config.highlight_options = {config.highlight_language: options}  # type: ignore</ins> def init_numfig_format(app: "Sphinx", config: Config) -> None:     """Initialize :confval:`numfig_format`."""     numfig_format = {'section': _('Section %s'),


def setup(app: "Sphinx") -> Dict[str, Any]:     app.connect('config-inited', convert_source_suffix, priority=800)    app.connect('config-inited', convert_highlight_options, priority=800)     app.connect('config-inited', init_numfig_format, priority=800)     app.connect('config-inited', correct_copyright_year, priority=800)     app.connect('config-inited', check_confval_types, priority=800)diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py-- a/sphinx/writers/html.py++ b/sphinx/writers/html.py


linenos = node.get('linenos', False)         highlight_args = node.get('highlight_args', {})         highlight_args['force'] = node.get('force', False)        if lang == self.config.highlight_language:            # only pass highlighter options for original language            opts = self.config.highlight_options        else:            opts = {}        opts = self.config.highlight_options.get(lang, {})          if linenos and self.config.html_codeblock_linenos_style:             linenos = self.config.html_codeblock_linenos_stylediff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py-- a/sphinx/writers/html5.py++ b/sphinx/writers/html5.py


linenos = node.get('linenos', False)         highlight_args = node.get('highlight_args', {})         highlight_args['force'] = node.get('force', False)        if lang == self.config.highlight_language:            # only pass highlighter options for original language            opts = self.config.highlight_options        else:            opts = {}        opts = self.config.highlight_options.get(lang, {})          if linenos and self.config.html_codeblock_linenos_style:             linenos = self.config.html_codeblock_linenos_stylediff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py-- a/sphinx/writers/latex.py++ b/sphinx/writers/latex.py


linenos = node.get('linenos', False)             highlight_args = node.get('highlight_args', {})             highlight_args['force'] = node.get('force', False)            if lang == self.config.highlight_language:                # only pass highlighter options for original language                opts = self.config.highlight_options            else:                opts = {}            opts = self.config.highlight_options.get(lang, {})              hlcode = self.highlighter.highlight_block(                 node.rawsource, lang, opts=opts, linenos=linenos,


name, env.doc2path(self.labels[name][0]),                                location=node)             self.anonlabels[name] = docname, labelid            if node.tagname in ('section', 'rubric'):            if node.tagname == 'section':                 title = cast(nodes.title, node[0])                 sectname = clean_astext(title)            elif node.tagname == 'rubric':                sectname = clean_astext(node)             elif self.is_enumerable_node(node):                 sectname = self.get_numfig_title(node)                 if not sectname:


"""  import sys<ins>import textwrap</ins> import warnings from difflib import unified_diff from typing import Any, Dict, List, Tuple


from sphinx import addnodes from sphinx.config import Config from sphinx.deprecation import RemovedInSphinx40Warning<ins>from sphinx.directives import optional_int</ins> from sphinx.locale import __ from sphinx.util import logging, parselinenos from sphinx.util.docutils import SphinxDirective


def dedent_lines(lines: List[str], dedent: int, location: Tuple[str, int] = None) -> List[str]:     if not dedent:        return lines        return textwrap.dedent(''.join(lines)).splitlines(True)      if any(s[:dedent].strip() for s in lines):         logger.warning(__('non-whitespace stripped by dedent'), location=location)


option_spec = {         'force': directives.flag,         'linenos': directives.flag,        'dedent': int,        'dedent': optional_int,         'lineno-start': int,         'emphasize-lines': directives.unchanged_required,         'caption': directives.unchanged_required,


optional_arguments = 0     final_argument_whitespace = True     option_spec = {        'dedent': int,        'dedent': optional_int,         'linenos': directives.flag,         'lineno-start': int,         'lineno-match': directives.flag,


import os import pickle<ins>import posixpath</ins> import warnings from collections import defaultdict from copy import copy


docdir = path.dirname(self.doc2path(docname or self.docname,                                                 base=None))             rel_fn = path.join(docdir, filename)        # the path.abspath() might seem redundant, but otherwise artifacts        # such as ".." will remain in the path        return rel_fn, path.abspath(path.join(self.srcdir, rel_fn))        return (posixpath.normpath(rel_fn),                path.normpath(path.join(self.srcdir, rel_fn)))      @property     def found_docs(self) -> Set[str]:


import posixpath import traceback<ins>import warnings</ins> from os import path from typing import Any, Dict, Generator, Iterable, Optional, Set, Tuple, cast


import sphinx from sphinx import addnodes from sphinx.application import Sphinxfrom sphinx.builders import Builder from sphinx.builders.html import StandaloneHTMLBuilderfrom sphinx.deprecation import RemovedInSphinx50Warning from sphinx.environment import BuildEnvironment from sphinx.locale import _, __ from sphinx.pycode import ModuleAnalyzerfrom sphinx.transforms.post_transforms import SphinxPostTransform from sphinx.util import get_full_modname, logging, status_iterator from sphinx.util.nodes import make_refnode


OUTPUT_DIRNAME = '_modules'  <ins>class viewcode_anchor(Element):    """Node for viewcode anchors.    This node will be processed in the resolving phase.    For viewcode supported builders, they will be all converted to the anchors.    For not supported builders, they will be removed.    """</ins> def _get_full_modname(app: Sphinx, modname: str, attribute: str) -> Optional[str]:     try:         return get_full_modname(modname, attribute)


return None  def is_supported_builder(builder: Builder) -> bool:    if builder.format != 'html':        return False    elif builder.name == 'singlehtml':        return False    elif builder.name.startswith('epub') and not builder.config.viewcode_enable_epub:        return False    else:        return True def doctree_read(app: Sphinx, doctree: Node) -> None:     env = app.builder.env     if not hasattr(env, '_viewcode_modules'):         env._viewcode_modules = {}  # type: ignore    if app.builder.name == "singlehtml":        return    if app.builder.name.startswith("epub") and not env.config.viewcode_enable_epub:        return      def has_tag(modname: str, fullname: str, docname: str, refname: str) -> bool:         entry = env._viewcode_modules.get(modname, None)  # type: ignore


continue             names.add(fullname)             pagename = posixpath.join(OUTPUT_DIRNAME, modname.replace('.', '/'))            inline = nodes.inline('', _('[source]'), classes=['viewcode-link'])            onlynode = addnodes.only(expr='html')            onlynode += addnodes.pending_xref('', inline, reftype='viewcode', refdomain='std',                                              refexplicit=False, reftarget=pagename,                                              refid=fullname, refdoc=env.docname)            signode += onlynode            signode += viewcode_anchor(reftarget=pagename, refid=fullname, refdoc=env.docname)   def env_merge_info(app: Sphinx, env: BuildEnvironment, docnames: Iterable[str],


env._viewcode_modules.update(other._viewcode_modules)  # type: ignore  class ViewcodeAnchorTransform(SphinxPostTransform):    """Convert or remove viewcode_anchor nodes depends on builder."""    default_priority = 100    def run(self, **kwargs: Any) -> None:        if is_supported_builder(self.app.builder):            self.convert_viewcode_anchors()        else:            self.remove_viewcode_anchors()    def convert_viewcode_anchors(self) -> None:        for node in self.document.traverse(viewcode_anchor):            anchor = nodes.inline('', _('[source]'), classes=['viewcode-link'])            refnode = make_refnode(self.app.builder, node['refdoc'], node['reftarget'],                                   node['refid'], anchor)            node.replace_self(refnode)    def remove_viewcode_anchors(self) -> None:        for node in self.document.traverse(viewcode_anchor):            node.parent.remove(node) def missing_reference(app: Sphinx, env: BuildEnvironment, node: Element, contnode: Node                       ) -> Optional[Node]:     # resolve our "viewcode" reference nodes -- they need special treatment     if node['reftype'] == 'viewcode':        warnings.warn('viewcode extension is no longer use pending_xref node. '                      'Please update your extension.', RemovedInSphinx50Warning)         return make_refnode(app.builder, node['refdoc'], node['reftarget'],                             node['refid'], contnode)


env = app.builder.env     if not hasattr(env, '_viewcode_modules'):         return    if app.builder.name == "singlehtml":        return    if app.builder.name.startswith("epub") and not env.config.viewcode_enable_epub:    if not is_supported_builder(app.builder):         return     highlighter = app.builder.highlighter  # type: ignore     urito = app.builder.get_relative_uri


# app.add_config_value('viewcode_exclude_modules', [], 'env')     app.add_event('viewcode-find-source')     app.add_event('viewcode-follow-imported')<ins>    app.add_post_transform(ViewcodeAnchorTransform)</ins>     return {         'version': sphinx.__display_version__,         'env_version': 1,


return self._parse_generic_section(_('Notes'), use_admonition)      def _parse_other_parameters_section(self, section: str) -> List[str]:        return self._format_fields(_('Other Parameters'), 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(_('Other Parameters'), fields)      def _parse_parameters_section(self, section: str) -> List[str]:         if self._config.napoleon_use_param:


"""  import refrom typing import Any, Dictfrom typing import Any, Dict, List  from docutils import nodes


default_priority = 400     builders = ('html',)     pattern = re.compile(r'(?<=.)(-|\+|\^|\s+)(?=.)')    multiwords_keys = (('caps', 'lock'),                       ('page' 'down'),                       ('page', 'up'),                       ('scroll' 'lock'),                       ('num', 'lock'),                       ('sys' 'rq'),                       ('back' 'space'))      def run(self, **kwargs: Any) -> None:         matcher = NodeMatcher(nodes.literal, classes=["kbd"])         for node in self.document.traverse(matcher):  # type: nodes.literal             parts = self.pattern.split(node[-1].astext())            if len(parts) == 1:            if len(parts) == 1 or self.is_multiwords_key(parts):                 continue              node['classes'].append('compound')             node.pop()             while parts:                key = parts.pop(0)                if self.is_multiwords_key(parts):                    key = ''.join(parts[:3])                    parts[:3] = []                else:                    key = parts.pop(0)                 node += nodes.literal('', key, classes=["kbd"])                  try:


except IndexError:                     pass <ins>    def is_multiwords_key(self, parts: List[str]) -> bool:        if len(parts) >= 3 and parts[1].strip() == '':            name = parts[0].lower(), parts[2].lower()            if name in self.multiwords_keys:                return True            else:                return False        else:            return False</ins>  def setup(app: Sphinx) -> Dict[str, Any]:     app.add_post_transform(KeyboardTransform)


env = app.builder.env     if not hasattr(env, '_viewcode_modules'):         return<ins>    if app.builder.name == "singlehtml":        return    if app.builder.name.startswith("epub") and not env.config.viewcode_enable_epub:        return</ins>     highlighter = app.builder.highlighter  # type: ignore     urito = app.builder.get_relative_uri


from fnmatch import fnmatch from importlib.machinery import EXTENSION_SUFFIXES from os import pathfrom typing import Any, List, Tuplefrom typing import Any, Generator, List, Tuple  import sphinx.locale from sphinx import __display_version__, package_dir


return False  def walk(rootpath: str, excludes: List[str], opts: Any         ) -> Generator[Tuple[str, List[str], List[str]], None, None]:    """Walk through the directory and list files and subdirectories up."""    followlinks = getattr(opts, 'followlinks', False)    includeprivate = getattr(opts, 'includeprivate', False)    for root, subs, files in os.walk(rootpath, followlinks=followlinks):        # document only Python module files (that aren't excluded)        files = sorted(f for f in files                       if f.endswith(PY_SUFFIXES) and                       not is_excluded(path.join(root, f), excludes))        # remove hidden ('.') and private ('_') directories, as well as        # excluded dirs        if includeprivate:            exclude_prefixes = ('.',)  # type: Tuple[str, ...]        else:            exclude_prefixes = ('.', '_')        subs[:] = sorted(sub for sub in subs if not sub.startswith(exclude_prefixes) and                         not is_excluded(path.join(root, sub), excludes))        yield root, subs, filesdef has_child_module(rootpath: str, excludes: List[str], opts: Any) -> bool:    """Check the given directory contains child modules at least one."""    for root, subs, files in walk(rootpath, excludes, opts):        if files:            return True    return False def recurse_tree(rootpath: str, excludes: List[str], opts: Any,                  user_template_dir: str = None) -> List[str]:     """     Look for every file in the directory tree and create the corresponding     ReST files.     """    followlinks = getattr(opts, 'followlinks', False)    includeprivate = getattr(opts, 'includeprivate', False)     implicit_namespaces = getattr(opts, 'implicit_namespaces', False)      # check if the base directory is a package and get its name


root_package = None      toplevels = []    for root, subs, files in os.walk(rootpath, followlinks=followlinks):        # document only Python module files (that aren't excluded)        py_files = sorted(f for f in files                          if f.endswith(PY_SUFFIXES) and                          not is_excluded(path.join(root, f), excludes))        is_pkg = is_packagedir(None, py_files)    for root, subs, files in walk(rootpath, excludes, opts):        is_pkg = is_packagedir(None, files)         is_namespace = not is_pkg and implicit_namespaces         if is_pkg:            for f in py_files[:]:            for f in files[:]:                 if is_initpy(f):                    py_files.remove(f)                    py_files.insert(0, f)                    files.remove(f)                    files.insert(0, f)         elif root != rootpath:             # only accept non-package at toplevel unless using implicit namespaces             if not implicit_namespaces:                 del subs[:]                 continue        # remove hidden ('.') and private ('_') directories, as well as        # excluded dirs        if includeprivate:            exclude_prefixes = ('.',)  # type: Tuple[str, ...]        else:            exclude_prefixes = ('.', '_')        subs[:] = sorted(sub for sub in subs if not sub.startswith(exclude_prefixes) and                         not is_excluded(path.join(root, sub), excludes))          if is_pkg or is_namespace:             # we are in a package with something to document            if subs or len(py_files) > 1 or not is_skipped_package(root, opts):            if subs or len(files) > 1 or not is_skipped_package(root, opts):                 subpackage = root[len(rootpath):].lstrip(path.sep).\                     replace(path.sep, '.')                 # if this is not a namespace or                 # a namespace and there is something there to document                if not is_namespace or len(py_files) > 0:                if not is_namespace or has_child_module(root, excludes, opts):                     create_package_file(root, root_package, subpackage,                                        py_files, opts, subs, is_namespace, excludes,                                        files, opts, subs, is_namespace, excludes,                                         user_template_dir)                     toplevels.append(module_join(root_package, subpackage))         else:             # if we are at the root level, we don't require it to be a package             assert root == rootpath and root_package is None            for py_file in py_files:            for py_file in files:                 if not is_skipped_module(path.join(rootpath, py_file), opts, excludes):                     module = py_file.split('.')[0]                     create_module_file(root_package, module, opts, user_template_dir)


_SINGLETONS = ("None", "True", "False", "Ellipsis")  <ins>def _convert_type_spec(_type: str, translations: Dict[str, str] = {}) -> str:    """Convert type specification to reference in reST."""    if _type in translations:        return translations[_type]    else:        if _type == 'None':            return ':obj:`None`'        else:            return ':class:`%s`' % _type    return _type</ins> class GoogleDocstring:     """Convert Google style docstrings to reStructuredText.


if prefer_type and not _type:             _type, _name = _name, _type<ins>        if _type and self._config.napoleon_preprocess_types:            _type = _convert_type_spec(_type, self._config.napoleon_type_aliases or {})</ins>         indent = self._get_indent(line) + 1         _descs = [_desc] + self._dedent(self._consume_indented_block(indent))         _descs = self.__class__(_descs, self._config).lines()


_descs = self.__class__(_descs, self._config).lines()         return _type, _descs     def _consume_returns_section(self) -> List[Tuple[str, str, List[str]]]:    def _consume_returns_section(self, preprocess_types: bool = False                                 ) -> List[Tuple[str, str, List[str]]]:         lines = self._dedent(self._consume_to_next_section())         if lines:             before, colon, after = self._partition_field_on_colon(lines[0])


_type = before <ins>            if (_type and preprocess_types and                    self._config.napoleon_preprocess_types):                _type = _convert_type_spec(_type, self._config.napoleon_type_aliases or {})</ins>             _desc = self.__class__(_desc, self._config).lines()             return [(_name, _type, _desc,)]         else:


return self._format_fields(section, self._consume_fields())      def _parse_custom_returns_style_section(self, section: str) -> List[str]:        fields = self._consume_returns_section()        fields = self._consume_returns_section(preprocess_types=True)         return self._format_fields(section, fields)      def _parse_usage_section(self, section: str) -> List[str]:


return self._format_fields(_('Warns'), self._consume_fields())      def _parse_yields_section(self, section: str) -> List[str]:        fields = self._consume_returns_section()        fields = self._consume_returns_section(preprocess_types=True)         return self._format_fields(_('Yields'), fields)      def _partition_field_on_colon(self, line: str) -> Tuple[str, str, str]:


_desc = self.__class__(_desc, self._config).lines()         return _name, _type, _desc     def _consume_returns_section(self) -> List[Tuple[str, str, List[str]]]:    def _consume_returns_section(self, preprocess_types: bool = False                                 ) -> List[Tuple[str, str, List[str]]]:         return self._consume_fields(prefer_type=True)      def _consume_section_header(self) -> str:


app.connect('config-inited', migrate_autodoc_member_order, priority=800)     app.setup_extension('sphinx.ext.autodoc.preserve_defaults')     app.setup_extension('sphinx.ext.autodoc.type_comment')     app.setup_extension('sphinx.ext.autodoc.typehints') diff --git a/sphinx/ext/autodoc/preserve_defaults.py b/sphinx/ext/autodoc/preserve_defaults.pynew file mode 100644-- /dev/null++ b/sphinx/ext/autodoc/preserve_defaults.py


<ins>"""    sphinx.ext.autodoc.preserve_defaults    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    Preserve the default argument values of function signatures in source code    and keep them not evaluated for readability.    :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.    :license: BSD, see LICENSE for details."""import astimport inspectfrom typing import Any, Dictfrom sphinx.application import Sphinxfrom sphinx.locale import __from sphinx.pycode.ast import parse as ast_parsefrom sphinx.pycode.ast import unparse as ast_unparsefrom sphinx.util import logginglogger = logging.getLogger(__name__)class DefaultValue:    def __init__(self, name: str) -> None:        self.name = name    def __repr__(self) -> str:        return self.namedef get_function_def(obj: Any) -> ast.FunctionDef:    """Get FunctionDef object from living object.    This tries to parse original code for living object and returns    AST node for given *obj*.    """    try:        source = inspect.getsource(obj)        if source.startswith((' ', r'\t')):            # subject is placed inside class or block.  To read its docstring,            # this adds if-block before the declaration.            module = ast_parse('if True:\n' + source)            return module.body[0].body[0]  # type: ignore        else:            module = ast_parse(source)            return module.body[0]  # type: ignore    except (OSError, TypeError):  # failed to load source code        return Nonedef update_defvalue(app: Sphinx, obj: Any, bound_method: bool) -> None:    """Update defvalue info of *obj* using type_comments."""    if not app.config.autodoc_preserve_defaults:        return    try:        function = get_function_def(obj)        if function.args.defaults or function.args.kw_defaults:            sig = inspect.signature(obj)            defaults = list(function.args.defaults)            kw_defaults = list(function.args.kw_defaults)            parameters = list(sig.parameters.values())            for i, param in enumerate(parameters):                if param.default is not param.empty:                    if param.kind in (param.POSITIONAL_ONLY, param.POSITIONAL_OR_KEYWORD):                        value = DefaultValue(ast_unparse(defaults.pop(0)))  # type: ignore                        parameters[i] = param.replace(default=value)                    else:                        value = DefaultValue(ast_unparse(kw_defaults.pop(0)))  # type: ignore                        parameters[i] = param.replace(default=value)            sig = sig.replace(parameters=parameters)            obj.__signature__ = sig    except (AttributeError, TypeError):        # failed to update signature (ex. built-in or extension types)        pass    except NotImplementedError as exc:  # failed to ast.unparse()        logger.warning(__("Failed to parse a default argument value for %r: %s"), obj, exc)def setup(app: Sphinx) -> Dict[str, Any]:    app.add_config_value('autodoc_preserve_defaults', False, True)    app.connect('autodoc-before-process-signature', update_defvalue)    return {        'version': '1.0',        'parallel_read_safe': True    }</ins>


try:         for cls in getmro(subject):            try:                modname = safe_getattr(cls, '__module__')                qualname = safe_getattr(cls, '__qualname__')                analyzer = ModuleAnalyzer.for_module(modname)                analyzer.analyze()            except AttributeError:                qualname = None                analyzer = None            except PycodeError:                analyzer = None             # annotation only member (ex. attr: int)             for name in getannotations(cls):                 name = unmangle(cls, name)                 if name and name not in members:                    members[name] = ObjectMember(name, INSTANCEATTR, class_=cls)                    if analyzer and (qualname, name) in analyzer.attr_docs:                        docstring = '\n'.join(analyzer.attr_docs[qualname, name])                    else:                        docstring = None                    members[name] = ObjectMember(name, INSTANCEATTR, class_=cls,                                                 docstring=docstring)              # append instance attributes (cf. self.attr1) if analyzer knows            try:                modname = safe_getattr(cls, '__module__')                qualname = safe_getattr(cls, '__qualname__')                analyzer = ModuleAnalyzer.for_module(modname)                analyzer.analyze()            if analyzer:                 for (ns, name), docstring in analyzer.attr_docs.items():                     if ns == qualname and name not in members:                         members[name] = ObjectMember(name, INSTANCEATTR, class_=cls,                                                      docstring='\n'.join(docstring))            except (AttributeError, PycodeError):                pass     except AttributeError:         pass


def visit_footnote(self, node: Element) -> None:         self.in_footnote += 1         label = cast(nodes.label, node[0])        if 'auto' not in node:            self.body.append('\\sphinxstepexplicit ')         if self.in_parsed_literal:             self.body.append('\\begin{footnote}[%s]' % label.astext())         else:             self.body.append('%\n')             self.body.append('\\begin{footnote}[%s]' % label.astext())        if 'auto' not in node:            self.body.append('\\phantomsection'                             '\\label{\\thesphinxscope.%s}%%\n' % label.astext())         self.body.append('\\sphinxAtStartFootnote\n')      def depart_footnote(self, node: Element) -> None:


label = cast(nodes.label, node[0])         self.body.append('%\n')         self.body.append('\\begin{footnotetext}[%s]'                         '\\sphinxAtStartFootnote\n' % label.astext())                         '\\phantomsection\\label{\\thesphinxscope.%s}%%\n'                         % (label.astext(), label.astext()))        self.body.append('\\sphinxAtStartFootnote\n')      def depart_footnotetext(self, node: Element) -> None:         # the \ignorespaces in particular for after table header use


|   \+\+ | --     |   ->\*? | \,     |   (<<|>>)=? | && | \|\|<ins>    |   <=></ins>     |   [!<>=/*%+|&^~-]=?     |   (\b(and|and_eq|bitand|bitor|compl|not|not_eq|or|or_eq|xor|xor_eq)\b) ''')


'>': 'gt',     '<=': 'le',     '>=': 'ge',<ins>    '<=>': 'ss',</ins>     '!': 'nt', 'not': 'nt',     '&&': 'aa', 'and': 'aa',     '||': 'oo', 'or': 'oo',


['^', 'xor'],     ['&', 'bitand'],     ['==', '!=', 'not_eq'],    ['<=', '>=', '<', '>'],    ['<=>', '<=', '>=', '<', '>'],     ['<<', '>>'],     ['+', '-'],     ['*', '/', '%'],


# exclusive-or   = and              ^         # and            = equality         &         # equality       = relational       ==, !=        # relational     = shift            <, >, <=, >=        # relational     = shift            <, >, <=, >=, <=>         # shift          = additive         <<, >>         # additive       = multiplicative   +, -         # multiplicative = pm               *, /, %


:license: BSD, see LICENSE for details. """ import os import warningsfrom os import path from typing import TYPE_CHECKING, Any, Dict, List, Tuple, cast  from docutils import nodes


from sphinx.deprecation import RemovedInSphinx60Warning from sphinx.directives import optional_int from sphinx.domains.math import MathDomainfrom sphinx.locale import __from sphinx.util import logging from sphinx.util.docutils import SphinxDirective from sphinx.util.nodes import set_source_infofrom sphinx.util.osutil import SEP, os_path, relpath  if TYPE_CHECKING:     from sphinx.application import Sphinx  logger = logging.getLogger(__name__) class Figure(images.Figure):     """The figure directive which applies `:name:` option to the figure node     instead of the image node.


class CSVTable(tables.CSVTable):    """The csv-table directive which sets source and line information to its caption.    Only for docutils-0.13 or older version."""    """The csv-table directive which searches a CSV file from Sphinx project's source    directory when an absolute path is given via :file: option.    """      def run(self) -> List[Node]:        warnings.warn('CSVTable is deprecated.',                      RemovedInSphinx60Warning)        return super().run()        if 'file' in self.options and self.options['file'].startswith((SEP, os.sep)):            env = self.state.document.settings.env            filename = self.options['file']            if path.exists(filename):                logger.warning(__('":file:" option for csv-table directive now recognizes '                                  'an absolute path as a relative path from source directory. '                                  'Please update your document.'),                               location=(env.docname, self.lineno))            else:                abspath = path.join(env.srcdir, os_path(self.options['file'][1:]))                docdir = path.dirname(env.doc2path(env.docname))                self.options['file'] = relpath(abspath, docdir)     def make_title(self) -> Tuple[nodes.title, List[system_message]]:        title, message = super().make_title()        if title:            set_source_info(self, title)        return title, message        return super().run()   class ListTable(tables.ListTable):


def setup(app: "Sphinx") -> Dict[str, Any]:     directives.register_directive('figure', Figure)     directives.register_directive('meta', Meta)<ins>    directives.register_directive('csv-table', CSVTable)</ins>     directives.register_directive('code', Code)     directives.register_directive('math', MathDirective)


import sys import typing from struct import Struct<ins>from types import TracebackType</ins> from typing import Any, Callable, Dict, Generator, List, Optional, Tuple, TypeVar, Union  from docutils import nodes


from typing import Type  # NOQA # for python3.5.1  <ins># builtin classes that have incorrect __module__INVALID_BUILTIN_CLASSES = {    Struct: 'struct.Struct',  # Before Python 3.9    TracebackType: 'types.TracebackType',}</ins> # Text like nodes which are initialized with text and rawsource TextlikeNode = Union[nodes.Text, nodes.TextElement]


return ':obj:`None`'     elif cls is Ellipsis:         return '...'    elif cls is Struct:        # Before Python 3.9, struct.Struct class has incorrect __module__.        return ':class:`struct.Struct`'    elif cls in INVALID_BUILTIN_CLASSES:        return ':class:`%s`' % INVALID_BUILTIN_CLASSES[cls]     elif inspect.isNewType(cls):         return ':class:`%s`' % cls.__name__     elif types_Union and isinstance(cls, types_Union):


return repr(annotation)     elif annotation is NoneType:         return 'None'    elif annotation in INVALID_BUILTIN_CLASSES:        return INVALID_BUILTIN_CLASSES[annotation]     elif (getattr(annotation, '__module__', None) == 'builtins' and           hasattr(annotation, '__qualname__')):         return annotation.__qualname__     elif annotation is Ellipsis:         return '...'    elif annotation is Struct:        # Before Python 3.9, struct.Struct class has incorrect __module__.        return 'struct.Struct'      if sys.version_info >= (3, 7):  # py37+         return _stringify_py37(annotation)


def make_xrefs(self, rolename: str, domain: str, target: str,                    innernode: Type[TextlikeNode] = nodes.emphasis,                    contnode: Node = None, env: BuildEnvironment = None) -> List[Node]:        delims = r'(\s*[\[\]\(\),](?:\s*or\s)?\s*|\s+or\s+)'        delims = r'(\s*[\[\]\(\),](?:\s*or\s)?\s*|\s+or\s+|\.\.\.)'         delims_re = re.compile(delims)         sub_targets = re.split(delims, target)


docname: str     node_id: str     objtype: str    canonical: bool    aliased: bool   class ModuleEntry(NamedTuple):


canonical_name = self.options.get('canonical')         if canonical_name:            domain.note_object(canonical_name, self.objtype, node_id, canonical=True,            domain.note_object(canonical_name, self.objtype, node_id, aliased=True,                                location=signode)          if 'noindexentry' not in self.options:


return self.data.setdefault('objects', {})  # fullname -> ObjectEntry      def note_object(self, name: str, objtype: str, node_id: str,                    canonical: bool = False, location: Any = None) -> None:                    aliased: bool = False, location: Any = None) -> None:         """Note a python object for cross reference.          .. versionadded:: 2.1         """         if name in self.objects:             other = self.objects[name]            logger.warning(__('duplicate object description of %s, '                              'other instance in %s, use :noindex: for one of them'),                           name, other.docname, location=location)        self.objects[name] = ObjectEntry(self.env.docname, node_id, objtype, canonical)            if other.aliased and aliased is False:                # The original definition found. Override it!                pass            elif other.aliased is False and aliased:                # The original definition is already registered.                return            else:                # duplicated                logger.warning(__('duplicate object description of %s, '                                  'other instance in %s, use :noindex: for one of them'),                               name, other.docname, location=location)        self.objects[name] = ObjectEntry(self.env.docname, node_id, objtype, aliased)      @property     def modules(self) -> Dict[str, ModuleEntry]:


yield (modname, modname, 'module', mod.docname, mod.node_id, 0)         for refname, obj in self.objects.items():             if obj.objtype != 'module':  # modules are already handled                if obj.canonical:                    # canonical names are not full-text searchable.                if obj.aliased:                    # aliased names are not full-text searchable.                     yield (refname, refname, obj.objtype, obj.docname, obj.node_id, -1)                 else:                     yield (refname, refname, obj.objtype, obj.docname, obj.node_id, 1)


def __contains__(self, item: Any) -> bool:         return True <ins>    def append(self, item: Any) -> None:        pass  # nothing</ins>  class _Empty:     """A special value for :exclude-members: that never matches to any member."""


def __init__(self, *args: Any) -> None:         super().__init__(*args)<ins>        if self.config.autodoc_class_signature == 'separated':            # show __init__() method            if self.options.special_members is None:                self.options['special-members'] = {'__new__', '__init__'}            else:                self.options.special_members.append('__new__')                self.options.special_members.append('__init__')</ins>         merge_members_option(self.options)      @classmethod


def format_signature(self, **kwargs: Any) -> str:         if self.doc_as_attr:             return ''<ins>        if self.config.autodoc_class_signature == 'separated':            # do not show signatures            return ''</ins>          sig = super().format_signature()         sigs = []


else:             return None <ins>    def get_doc(self, ignore: int = None) -> Optional[List[List[str]]]:        if self.objpath[-1] == '__init__':            docstring = getdoc(self.object, self.get_attr,                               self.config.autodoc_inherit_docstrings,                               self.parent, self.object_name)            if (docstring is not None and                (docstring == object.__init__.__doc__ or  # for pypy                 docstring.strip() == object.__init__.__doc__)):  # for !pypy                docstring = None            if docstring:                tab_width = self.directive.state.document.settings.tab_width                return [prepare_docstring(docstring, tabsize=tab_width)]            else:                return []        elif self.objpath[-1] == '__new__':            __new__ = self.get_attr(self.object, '__new__', None)            if __new__:                docstring = getdoc(__new__, self.get_attr,                                   self.config.autodoc_inherit_docstrings,                                   self.parent, self.object_name)                if (docstring is not None and                    (docstring == object.__new__.__doc__ or  # for pypy                     docstring.strip() == object.__new__.__doc__)):  # for !pypy                    docstring = None            if docstring:                tab_width = self.directive.state.document.settings.tab_width                return [prepare_docstring(docstring, tabsize=tab_width)]            else:                return []        else:            return super().get_doc()</ins>  class NonDataDescriptorMixin(DataDocumenterMixinBase):     """


app.add_config_value('autoclass_content', 'class', True, ENUM('both', 'class', 'init'))     app.add_config_value('autodoc_member_order', 'alphabetical', True,                          ENUM('alphabetic', 'alphabetical', 'bysource', 'groupwise'))    app.add_config_value('autodoc_class_signature', 'mixed', True, ENUM('mixed', 'separated'))     app.add_config_value('autodoc_default_options', {}, True)     app.add_config_value('autodoc_docstring_signature', True, True)     app.add_config_value('autodoc_mock_imports', [], True)diff --git a/sphinx/ext/autosummary/__init__.py b/sphinx/ext/autosummary/__init__.py-- a/sphinx/ext/autosummary/__init__.py++ b/sphinx/ext/autosummary/__init__.py


document = Struct(settings=settings)         env = BuildEnvironment()         env.config = Config()<ins>        env.config.add('autodoc_class_signature', 'mixed', True, None)</ins>         state = Struct(document=document)         super().__init__(env, None, Options(), 0, state)


# if isattr is True, the member is documented as an attribute             if member is INSTANCEATTR:                 isattr = True<ins>            elif (namespace, membername) in attr_docs:                isattr = True</ins>             else:                 isattr = False


else:                     # keep documented attributes                     keep = True<del>                isattr = True</del>             elif want_all and isprivate:                 if has_doc or self.options.undoc_members:                     if self.options.private_members is None:


if not matches:             return None         elif len(matches) > 1:            logger.warning(__('more than one target found for cross-reference %r: %s'),                           target, ', '.join(match[0] for match in matches),                           type='ref', subtype='python', location=node)            canonicals = [m for m in matches if not m[1].aliased]            if len(canonicals) == 1:                matches = canonicals            else:                logger.warning(__('more than one target found for cross-reference %r: %s'),                               target, ', '.join(match[0] for match in matches),                               type='ref', subtype='python', location=node)         name, obj = matches[0]          if obj[2] == 'module':


def get_doc(self, ignore: int = None) -> Optional[List[List[str]]]:         if self.doc_as_attr:             # Don't show the docstring of the class when it is an alias.            return None            comment = self.get_variable_comment()            if comment:                return []            else:                return None          lines = getattr(self, '_new_docstrings', None)         if lines is not None: