Question: Message.locations duplicate unnecessary When running there are times the list of locations is duplicated unnecessarily, example: or as shown in this screen viewing of the 'pot' file result: <img width="1552" alt="Screenshot 2022-01-15 at 20 41 41" src="https://user-"After debugging a little, the problem appeared to be in the file: in the 'init' method. My simple solution is this: Note, this solution will probably needed to be in the and in the as well. Follow instructions on this page which comprises of sections for installing dependencies, download sources. then load the file: into an editor and search for and you will see repeated locations appear there. The message id is: There should only be ONE instance of and there are NO duplications of other locations. No response MacOS Catalina 10.15.7 9 1 No response No response No response

def __iter__(self) -> Generator[Message, None, None]:         for message in self.messages:            positions = [(source, line) for source, line, uuid in self.metadata[message]]            positions = sorted(set((source, line) for source, line, uuid                                   in self.metadata[message]))             uuids = [uuid for source, line, uuid in self.metadata[message]]             yield Message(message, positions, uuids)


Question: If a project defines "language = None" in , treat it like "en" Hello, I started working on integrating Sphinx 5 to Fedora to ensure distribution packages work smoothly when the final is out. I ran across is a side effect of the change inspired by . If a project has already "language = None" defined in their (which, it seems, used to be an issue before commit), the new behavior will cause the documentation build to error out. The projects created after the mentioned commit seem not to be affected. In a sample of ~40 packages, 2 have run across this issue. A naive check using shows that for a half a million indexed GitHub projects there is around 6k which have the string in their (I removed the commented strings from the equation). For older projects using Sphinx, this change will be disruptive and will require the same commit in the same place for each and every one of them. The exact error: Describe the solution you'd like When Sphinx encounters NoneType for language, it could set the language to English and log the fact for the user (possibly asking them to make adjustments to ) instead of erroring. It's not that different than the current behavior in 5.0.0b1. When if I run and set no language, the variable is not present at all in , although in the background my project is processed as English. Describe alternatives you've considered Aforementioned manual change for each affected project, which I'm afraid of.

raise ConfigError(__("config directory doesn't contain a conf.py file (%s)") %                               confdir)         namespace = eval_config_file(filename, tags)<ins>        # Note: Old sphinx projects have been configured as "langugae = None" because        #       sphinx-quickstart previously generated this by default.        #       To keep compatibility, they should be fallback to 'en' for a while        #       (This conversion should not be removed before 2025-01-01).        if namespace.get("language", ...) is None:            logger.warning(__("Invalid configuration value found: 'language = None'. "                              "Update your configuration to a valid langauge code. "                              "Falling back to 'en' (English)."))            namespace["language"] = "en"</ins>         return cls(namespace, overrides or {})      def convert_overrides(self, name: str, value: Any) -> Any:


Question: Typo in new language warning See the following snippet: Both and are used incorrectly. Noticed in Read the Docs: Mention "language" without typos.

confdir)         namespace = eval_config_file(filename, tags)         # Note: Old sphinx projects have been configured as "langugae = None" because        # Note: Old sphinx projects have been configured as "language = None" because         #       sphinx-quickstart previously generated this by default.         #       To keep compatibility, they should be fallback to 'en' for a while         #       (This conversion should not be removed before 2025-01-01).         if namespace.get("language", ...) is None:             logger.warning(__("Invalid configuration value found: 'language = None'. "                              "Update your configuration to a valid langauge code. "                              "Update your configuration to a valid language code. "                               "Falling back to 'en' (English)."))             namespace["language"] = "en"


Question: IndexError: list index out of range make[1]: [Documentation/Makefile:96: htmldocs] Error 2 make: [Makefile:1678: htmldocs] Error 2 ==ERROR: A failure occurred in build(). Aborting... archlinux Linux RYZEN 5.18.0-arch1-1 x8664 , , , , , , No response

def run(self, **kwargs: Any) -> None:         matcher = NodeMatcher(nodes.literal, classes=["kbd"])        for node in self.document.findall(matcher):  # type: nodes.literal        # this list must be pre-created as during iteration new nodes        # are added which match the condition in the NodeMatcher.        for node in list(self.document.findall(matcher)):  # type: nodes.literal             parts = self.pattern.split(node[-1].astext())             if len(parts) == 1 or self.is_multiwords_key(parts):                 continue


Question: Spurious space in default parameter values that are negative numbers in HTML output. For several projects, I've noticed a problem in the HTML output of functions that have a parameter with a default value that is a negative number. In the rendered HTML, there is a spurious space between the minus sign and the first digit. A typical example is being rendered as . This issue was originally raised with . Here are links to examples in several projects: SciPy: see . see . NumPy: Pandas: Matplotlib: I wasn't able to find an existing issue for this. I don't know which versions of Sphinx were used in all those projects, so I don't know if the problem still exists in the latest version of Sphinx. Also, it looks like those projects all use the , so it is possible that the problem is the theme and not Sphinx itself. See the links. No response See the links No response See the above comments. Probably varied; see the links. Maybe several; see the links. No response No response No response_

return "%s.%s" % (self.visit(node.value), node.attr)      def visit_BinOp(self, node: ast.BinOp) -> str:<ins>        # Special case ``**`` to not have surrounding spaces.        if isinstance(node.op, ast.Pow):            return "".join(map(self.visit, (node.left, node.op, node.right)))</ins>         return " ".join(self.visit(e) for e in [node.left, node.op, node.right])      def visit_BoolOp(self, node: ast.BoolOp) -> str:


Question: Spurious space in default parameter values that are negative numbers in HTML output. For several projects, I've noticed a problem in the HTML output of functions that have a parameter with a default value that is a negative number. In the rendered HTML, there is a spurious space between the minus sign and the first digit. A typical example is being rendered as . This issue was originally raised with . Here are links to examples in several projects: SciPy: see . see . NumPy: Pandas: Matplotlib: I wasn't able to find an existing issue for this. I don't know which versions of Sphinx were used in all those projects, so I don't know if the problem still exists in the latest version of Sphinx. Also, it looks like those projects all use the , so it is possible that the problem is the theme and not Sphinx itself. See the links. No response See the links No response See the above comments. Probably varied; see the links. Maybe several; see the links. No response No response No response_

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))        # UnaryOp is one of {UAdd, USub, Invert, Not}, which refer to ``+x``,        # ``-x``, ``~x``, and ``not x``. Only Not needs a space.        if isinstance(node.op, ast.Not):            return "%s %s" % (self.visit(node.op), self.visit(node.operand))        return "%s%s" % (self.visit(node.op), self.visit(node.operand))      def visit_Tuple(self, node: ast.Tuple) -> str:         if len(node.elts) == 0:


Question: inheritance-diagram 404 links with SVG I have created some SVG inheritance diagrams using the plugin. If the inheritance diagram is created in a file that is not in the root directory, the links lead to a 404 page. This issue does not happen in the default (png?) mode. This issue is similar to and however this is reproduced with only first party extensions. Here is a small demo that can be used to reproduce the issue. 1) Extract the folder from the zip 2) run 3) run (I believe this is the command pycharm is running) 4) Open the website to view (I am doing this through pycharm on firefox) 5) Navigate to see that the links work. 6) Navigate to see that the links do not work. My understanding of this bug is that the links in the SVG file are relative to the SVG file (because it is embedded using the object tag) however the rest of the link is written as if it was relative to the file the SVG is embedded on. Here are the correct links to the files Below are some examples of the links generated in the SVG file. They are formatted with the link the file was embedded on followed by the actual link text in the SVG file and then the path that firefox expands that to (the link when clicked on) I would expect that the links would go to the correct page when clicked on and not to a 404 page. No response Windows 1 2 , , No response No response_

pending_xrefs = cast(Iterable[addnodes.pending_xref], node)     for child in pending_xrefs:         if child.get('refuri') is not None:            if graphviz_output_format == 'SVG':                urls[child['reftitle']] = "../" + child.get('refuri')            # Construct the name from the URI if the reference is external via intersphinx            if not child.get('internal', True):                refname = child['refuri'].rsplit('#', 1)[-1]             else:                urls[child['reftitle']] = child.get('refuri')                refname = child['reftitle']            urls[refname] = child.get('refuri')         elif child.get('refid') is not None:             if graphviz_output_format == 'SVG':                urls[child['reftitle']] = '../' + current_filename + '#' + child.get('refid')                urls[child['reftitle']] = current_filename + '#' + child.get('refid')             else:                 urls[child['reftitle']] = '#' + child.get('refid')


Question: toctree contains reference to nonexisting document 'genindex', 'modindex', 'search' Is your feature request related to a problem? Please describe. A lot of users try to add the following links to the toctree: like this: See: And probably more. However when doing this we get: Describe the solution you'd like The following directive should be possible and do not rise errors: .. toctree:: :maxdepth: 1 :caption: Indices and tables genindex modindex search ``

return ret      def parse_content(self, toctree: addnodes.toctree) -> List[Node]:        generated_docnames = frozenset(self.env.domains['std'].initial_data['labels'].keys())         suffixes = self.config.source_suffix          # glob target documents        all_docnames = self.env.found_docs.copy()        all_docnames = self.env.found_docs.copy() | generated_docnames         all_docnames.remove(self.env.docname)  # remove current document          ret: List[Node] = []


Question: toctree contains reference to nonexisting document 'genindex', 'modindex', 'search' Is your feature request related to a problem? Please describe. A lot of users try to add the following links to the toctree: like this: See: And probably more. However when doing this we get: Describe the solution you'd like The following directive should be possible and do not rise errors: .. toctree:: :maxdepth: 1 :caption: Indices and tables genindex modindex search ``

patname = docname_join(self.env.docname, entry)                 docnames = sorted(patfilter(all_docnames, patname))                 for docname in docnames:<ins>                    if docname in generated_docnames:                        # don't include generated documents in globs                        continue</ins>                     all_docnames.remove(docname)  # don't include it again                     toctree['entries'].append((None, docname))                     toctree['includefiles'].append(docname)


Question: toctree contains reference to nonexisting document 'genindex', 'modindex', 'search' Is your feature request related to a problem? Please describe. A lot of users try to add the following links to the toctree: like this: See: And probably more. However when doing this we get: Describe the solution you'd like The following directive should be possible and do not rise errors: .. toctree:: :maxdepth: 1 :caption: Indices and tables genindex modindex search ``

docname = docname_join(self.env.docname, docname)                 if url_re.match(ref) or ref == 'self':                     toctree['entries'].append((title, ref))                elif docname not in self.env.found_docs:                elif docname not in self.env.found_docs | generated_docnames:                     if excluded(self.env.doc2path(docname, False)):                         message = __('toctree contains reference to excluded document %r')                         subtype = 'excluded'diff --git a/sphinx/environment/adapters/toctree.py b/sphinx/environment/adapters/toctree.py-- a/sphinx/environment/adapters/toctree.py++ b/sphinx/environment/adapters/toctree.py


Question: toctree contains reference to nonexisting document 'genindex', 'modindex', 'search' Is your feature request related to a problem? Please describe. A lot of users try to add the following links to the toctree: like this: See: And probably more. However when doing this we get: Describe the solution you'd like The following directive should be possible and do not rise errors: .. toctree:: :maxdepth: 1 :caption: Indices and tables genindex modindex search ``

"""Toctree adapter for sphinx.environment.""" from typing import TYPE_CHECKING, Any, Iterable, List, Optional, castfrom typing import TYPE_CHECKING, Any, Dict, Iterable, List, Optional, Tuple, cast  from docutils import nodes from docutils.nodes import Element, Node


Question: toctree contains reference to nonexisting document 'genindex', 'modindex', 'search' Is your feature request related to a problem? Please describe. A lot of users try to add the following links to the toctree: like this: See: And probably more. However when doing this we get: Describe the solution you'd like The following directive should be possible and do not rise errors: .. toctree:: :maxdepth: 1 :caption: Indices and tables genindex modindex search ``

"""         if toctree.get('hidden', False) and not includehidden:             return None<ins>        generated_docnames: Dict[str, Tuple[str, str, str]] = self.env.domains['std'].initial_data['labels'].copy()  # NoQA: E501</ins>          # For reading the following two helper function, it is useful to keep         # in mind the node structure of a toctree (using HTML-like node names


Question: toctree contains reference to nonexisting document 'genindex', 'modindex', 'search' Is your feature request related to a problem? Please describe. A lot of users try to add the following links to the toctree: like this: See: And probably more. However when doing this we get: Describe the solution you'd like The following directive should be possible and do not rise errors: .. toctree:: :maxdepth: 1 :caption: Indices and tables genindex modindex search ``

item = nodes.list_item('', para)                         # don't show subitems                         toc = nodes.bullet_list('', item)                    elif ref in generated_docnames:                        docname, _, sectionname = generated_docnames[ref]                        if not title:                            title = sectionname                        reference = nodes.reference('', title, internal=True,                                                    refuri=docname, anchorname='')                        para = addnodes.compact_paragraph('', '', reference)                        item = nodes.list_item('', para)                        # don't show subitems                        toc = nodes.bullet_list('', item)                     else:                         if ref in parents:                             logger.warning(__('circular toctree references 'diff --git a/sphinx/environment/collectors/toctree.py b/sphinx/environment/collectors/toctree.py-- a/sphinx/environment/collectors/toctree.py++ b/sphinx/environment/collectors/toctree.py


Question: toctree contains reference to nonexisting document 'genindex', 'modindex', 'search' Is your feature request related to a problem? Please describe. A lot of users try to add the following links to the toctree: like this: See: And probably more. However when doing this we get: Describe the solution you'd like The following directive should be possible and do not rise errors: .. toctree:: :maxdepth: 1 :caption: Indices and tables genindex modindex search ``

def assign_figure_numbers(self, env: BuildEnvironment) -> List[str]:         """Assign a figure number to each figure under a numbered toctree."""<ins>        generated_docnames = frozenset(env.domains['std'].initial_data['labels'].keys())</ins>          rewrite_needed = []


Question: toctree contains reference to nonexisting document 'genindex', 'modindex', 'search' Is your feature request related to a problem? Please describe. A lot of users try to add the following links to the toctree: like this: See: And probably more. However when doing this we get: Describe the solution you'd like The following directive should be possible and do not rise errors: .. toctree:: :maxdepth: 1 :caption: Indices and tables genindex modindex search ``

fignumbers[figure_id] = get_next_fignumber(figtype, secnum)          def _walk_doctree(docname: str, doctree: Element, secnum: Tuple[int, ...]) -> None:<ins>            nonlocal generated_docnames</ins>             for subnode in doctree.children:                 if isinstance(subnode, nodes.section):                     next_secnum = get_section_number(docname, subnode)


Question: toctree contains reference to nonexisting document 'genindex', 'modindex', 'search' Is your feature request related to a problem? Please describe. A lot of users try to add the following links to the toctree: like this: See: And probably more. However when doing this we get: Describe the solution you'd like The following directive should be possible and do not rise errors: .. toctree:: :maxdepth: 1 :caption: Indices and tables genindex modindex search ``

if url_re.match(subdocname) or subdocname == 'self':                             # don't mess with those                             continue<ins>                        if subdocname in generated_docnames:                            # or these                            continue</ins>                          _walk_doc(subdocname, secnum)                 elif isinstance(subnode, nodes.Element):


Question: linkcheck should check URLs of raw directives Is your feature request related to a problem? Please describe. When using a with the option, the builder does not check this URL. Describe the solution you'd like I would expect the URLs of directives to be checked by .

builder = cast(CheckExternalLinksBuilder, self.app.builder)         hyperlinks = builder.hyperlinks         # reference nodes        for refnode in self.document.findall(nodes.reference):            if 'refuri' not in refnode:                continue            uri = refnode['refuri']        def add_uri(uri: str, node: nodes.Element) -> None:             newuri = self.app.emit_firstresult('linkcheck-process-uri', uri)             if newuri:                 uri = newuri             lineno = get_node_line(refnode)            lineno = get_node_line(node)             uri_info = Hyperlink(uri, self.env.docname, lineno)             if uri not in hyperlinks:                 hyperlinks[uri] = uri_info         # reference nodes        for refnode in self.document.findall(nodes.reference):            if 'refuri' not in refnode:                continue            uri = refnode['refuri']            add_uri(uri, refnode)         # image nodes         for imgnode in self.document.findall(nodes.image):             uri = imgnode['candidates'].get('?')             if uri and '://' in uri:                newuri = self.app.emit_firstresult('linkcheck-process-uri', uri)                if newuri:                    uri = newuri                lineno = get_node_line(imgnode)                uri_info = Hyperlink(uri, self.env.docname, lineno)                if uri not in hyperlinks:                    hyperlinks[uri] = uri_info                add_uri(uri, imgnode)        # raw nodes        for rawnode in self.document.findall(nodes.raw):            uri = rawnode.get('source')            if uri and '://' in uri:                add_uri(uri, rawnode)   def rewrite_github_anchor(app: Sphinx, uri: str) -> Optional[str]:


Question: Use the index directive as a source for search Is your feature request related to a problem? Please describe. My problem is the search engine is not good at finding terms that are indexed, for example: should find should find should find and a few others should find should find ... Describe the solution you'd like I think using the global index as a source for the search engine is a good way to enhance this and allow people to manually boost a search result by using the bang of the index directive. (). I can try to implement it, but I'm still not sure this is a good idea. Generated Index can point to anchors, I'm not sure the current searchindex can hold them in its current state.

from sphinx import addnodes, package_dir from sphinx.deprecation import RemovedInSphinx70Warning from sphinx.environment import BuildEnvironment<ins>from sphinx.util import split_into</ins>   class SearchLanguage:


Question: Use the index directive as a source for search Is your feature request related to a problem? Please describe. My problem is the search engine is not good at finding terms that are indexed, for example: should find should find should find and a few others should find should find ... Describe the solution you'd like I think using the global index as a source for the search engine is a good way to enhance this and allow people to manually boost a search result by using the bang of the index directive. (). I can try to implement it, but I'm still not sure this is a good idea. Generated Index can point to anchors, I'm not sure the current searchindex can hold them in its current state.

# stemmed words in titles -> set(docname)         self._title_mapping: Dict[str, Set[str]] = {}         self._all_titles: Dict[str, List[Tuple[str, str]]] = {}  # docname -> all titles<ins>        self._index_entries: Dict[str, List[Tuple[str, str, str]]] = {}  # docname -> index entry</ins>         self._stem_cache: Dict[str, str] = {}       # word -> stemmed word         self._objtypes: Dict[Tuple[str, str], int] = {}     # objtype -> index         # objtype index -> (domain, type, objname (localized))


Question: Use the index directive as a source for search Is your feature request related to a problem? Please describe. My problem is the search engine is not good at finding terms that are indexed, for example: should find should find should find and a few others should find should find ... Describe the solution you'd like I think using the global index as a source for the search engine is a good way to enhance this and allow people to manually boost a search result by using the bang of the index directive. (). I can try to implement it, but I'm still not sure this is a good idea. Generated Index can point to anchors, I'm not sure the current searchindex can hold them in its current state.

for title, titleid in titlelist:                 alltitles.setdefault(title, []).append((fn2index[docname],  titleid))         index_entries: Dict[str, List[Tuple[int, str]]] = {}        for docname, entries in self._index_entries.items():            for entry, entry_id, main_entry in entries:                index_entries.setdefault(entry.lower(), []).append((fn2index[docname],  entry_id))         return dict(docnames=docnames, filenames=filenames, titles=titles, terms=terms,                     objects=objects, objtypes=objtypes, objnames=objnames,                     titleterms=title_terms, envversion=self.env.version,                    alltitles=alltitles)                    alltitles=alltitles, indexentries=index_entries)      def label(self) -> str:         return "%s (code: %s)" % (self.lang.language_name, self.lang.lang)


Question: Use the index directive as a source for search Is your feature request related to a problem? Please describe. My problem is the search engine is not good at finding terms that are indexed, for example: should find should find should find and a few others should find should find ... Describe the solution you'd like I think using the global index as a source for the search engine is a good way to enhance this and allow people to manually boost a search result by using the bang of the index directive. (). I can try to implement it, but I'm still not sure this is a good idea. Generated Index can point to anchors, I'm not sure the current searchindex can hold them in its current state.

if _filter(stemmed_word) and not already_indexed:                 self._mapping.setdefault(stemmed_word, set()).add(docname) <ins>        # find explicit entries within index directives        _index_entries: Set[Tuple[str, str, str]] = set()        for node in doctree.findall(addnodes.index):            for entry_type, value, tid, main, *index_key in node['entries']:                tid = tid or ''                try:                    if entry_type == 'single':                        try:                            entry, subentry = split_into(2, 'single', value)                        except ValueError:                            entry, = split_into(1, 'single', value)                            subentry = ''                        _index_entries.add((entry, tid, main))                        if subentry:                            _index_entries.add((subentry, tid, main))                    elif entry_type == 'pair':                        first, second = split_into(2, 'pair', value)                        _index_entries.add((first, tid, main))                        _index_entries.add((second, tid, main))                    elif entry_type == 'triple':                        first, second, third = split_into(3, 'triple', value)                        _index_entries.add((first, tid, main))                        _index_entries.add((second, tid, main))                        _index_entries.add((third, tid, main))                    elif entry_type in {'see', 'seealso'}:                        first, second = split_into(2, 'see', value)                        _index_entries.add((first, tid, main))                except ValueError:                    pass        self._index_entries[docname] = sorted(_index_entries)</ins>     def context_for_searchtool(self) -> Dict[str, Any]:         if self.lang.js_splitter_code:             js_splitter_code = self.lang.js_splitter_code


Question: should improve formatting of Union, Optional, Literal, constants This is a sub-issue of split off here. When displayed normally, , , and add a lot of noise to the type signature and obscure the important information. Instead, it is much cleaner to display them using the PEP 604 () syntax: --Additionally, for it is cleaner to strip the text "Literal" and just display the literal value with normal Python syntax highlighting: -This is implemented in the tensorstore documentation via an ast transformation: This should be supported in Sphinx via a config option. The other improvement, of using syntax highlighting for constants, should also be integrated.

def _parse_annotation(annotation: str, env: BuildEnvironment | None) -> list[Node]:     """Parse type annotation."""<ins>    short_literals = env.config.python_display_short_literal_types</ins>     def unparse(node: ast.AST) -> list[Node]:         if isinstance(node, ast.Attribute):             return [nodes.Text(f"{unparse(node.value)[0]}.{node.attr}")]


Question: should improve formatting of Union, Optional, Literal, constants This is a sub-issue of split off here. When displayed normally, , , and add a lot of noise to the type signature and obscure the important information. Instead, it is much cleaner to display them using the PEP 604 () syntax: --Additionally, for it is cleaner to strip the text "Literal" and just display the literal value with normal Python syntax highlighting: -This is implemented in the tensorstore documentation via an ast transformation: This should be supported in Sphinx via a config option. The other improvement, of using syntax highlighting for constants, should also be integrated.

if isinstance(node, ast.Subscript):             if getattr(node.value, 'id', '') in {'Optional', 'Union'}:                 return _unparse_pep_604_annotation(node)<ins>            if short_literals and getattr(node.value, 'id', '') == 'Literal':                return _unparse_pep_604_annotation(node)</ins>             result = unparse(node.value)             result.append(addnodes.desc_sig_punctuation('', '['))             result.extend(unparse(node.slice))


Question: should improve formatting of Union, Optional, Literal, constants This is a sub-issue of split off here. When displayed normally, , , and add a lot of noise to the type signature and obscure the important information. Instead, it is much cleaner to display them using the PEP 604 () syntax: --Additionally, for it is cleaner to strip the text "Literal" and just display the literal value with normal Python syntax highlighting: -This is implemented in the tensorstore documentation via an ast transformation: This should be supported in Sphinx via a config option. The other improvement, of using syntax highlighting for constants, should also be integrated.

app.add_domain(PythonDomain)     app.add_config_value('python_use_unqualified_type_names', False, 'env')<ins>    app.add_config_value('python_display_short_literal_types', False, 'env')</ins>     app.connect('object-description-transform', filter_meta_fields)     app.connect('missing-reference', builtin_resolver, priority=900)


Question: Smaller/wrong search index with sphinx-build -j auto Using the latest version and building with then the searchindex is considerably larger and searches work as expected. Some quick testing showed that Sphinx 6.0.0 did not have this problem while Sphinx 6.1.0 onwards does. This fails: sphinx-build -j auto -n -b html -d build/doctrees -q -E . build/html This works: sphinx-build -n -b html -d build/doctrees -q -E . build/html No response Sphinx (almost empty!) and other files are at

}      def write_doc(self, docname: str, doctree: nodes.document) -> None:<del>        title_node = self.env.longtitles.get(docname)        title = self.render_partial(title_node)['title'] if title_node else ''        self.index_page(docname, doctree, title)</del>         destination = StringOutput(encoding='utf-8')         doctree.settings = self.docsettings


Question: Smaller/wrong search index with sphinx-build -j auto Using the latest version and building with then the searchindex is considerably larger and searches work as expected. Some quick testing showed that Sphinx 6.0.0 did not have this problem while Sphinx 6.1.0 onwards does. This fails: sphinx-build -j auto -n -b html -d build/doctrees -q -E . build/html This works: sphinx-build -n -b html -d build/doctrees -q -E . build/html No response Sphinx (almost empty!) and other files are at

def write_doc_serialized(self, docname: str, doctree: nodes.document) -> None:         self.imgpath = relative_uri(self.get_target_uri(docname), self.imagedir)         self.post_process_images(doctree)<ins>        title_node = self.env.longtitles.get(docname)        title = self.render_partial(title_node)['title'] if title_node else ''        self.index_page(docname, doctree, title)</ins>      def finish(self) -> None:         self.finish_tasks.add_task(self.gen_indices)


Question: LaTeX: missing space before colon after "Voir aussi" for seealso directive in French Here is a screenshot ! No response This was caused by which fixed . See Sorry, my bad. LaTeX: missing space before colon after "Voir aussi" for seealso directive in French Here is a screenshot ! No response This was caused by which fixed . See Sorry, my bad.

def visit_seealso(self, node: Element) -> None:         self.body.append(BLANKLINE)        self.body.append(r'\begin{sphinxseealso}{%s}' % admonitionlabels['seealso'] + CR)        self.body.append(r'\begin{sphinxseealso}{%s:}' % admonitionlabels['seealso'] + CR)      def depart_seealso(self, node: Element) -> None:         self.body.append(BLANKLINE)


Question: [FEATURE] Avoid losing information in . In light to , the current implementation of does the following assuming that the builder's current translator class is not a subclass of : If one or more node classes specified by (and derived from ) are not handled by the translator class, all are transformed into nodes instead (with the same attributes). If in addition the node is not handled by the visitor class, it is transformed into an node instead as well. This implementation choice suffers from the following disadvantages: Whenever a node inherits from , the class must be to the list. A custom translator not inheriting from should not be penalized if it only implements and handle it internally. Currently, they can emulate that behaviour by implementing and checking whether the XML attributes are those that we would find on nodes. As such, I suggest the following features: Use the hook together with a meta-keyword (defaults to ) to automatically add a class derived from to the list. That way, users may still use as a regular base class without affecting the nodes expected by Sphinx itself. A custom translator class orthogonal to must satisfy one of the following exclusive conditions: explicitly supports all nodes described in by providing methods. If a node inherits from but is not in , then must explicitly specify the corresponding visitor method. That way, nodes expected from Sphinx (i.e., those in ) are correctly dispatched and the remaining nodes are simply kept as is and handled as any other nodes. specifies a generic fallback method and possibly zero or more visitor methods for handling specific nodes. The nodes are then dispatched to their most precise type. does not have an interface for nodes and should therefore use a fallback. However, if there are other post-transforms coming after the fallback transform, it would be good to keep some information on the type the node originally had before converting them into nodes. For instance, we could add as an extra XML attribute of the transformed inline node. For , since the latter does not inherit from , I suggest that the fallback implementation simply add as an XML attribute in order to have a similar behaviour.

# Leaf nodes for markup of text fragments ######################################### #: A set of classes inheriting :class:`desc_sig_element`. Each node class#: is expected to be handled by the builder's translator class if the latter#: does not inherit from SphinxTranslator.#:#: This set can be extended manually by third-party extensions or#: by subclassing :class:`desc_sig_element` and using the class#: keyword argument `_sig_element=True`.SIG_ELEMENTS: set[type[desc_sig_element]] = set() # Signature text elements, generally translated to node.inline # in SigElementFallbackTransform.# When adding a new one, add it to SIG_ELEMENTS.# When adding a new one, add it to SIG_ELEMENTS via the class# keyword argument `_sig_element=True` (e.g., see `desc_sig_space`).  class desc_sig_element(nodes.inline, _desc_classes_injector):     """Common parent class of nodes for inline text of a signature."""


Question: [FEATURE] Avoid losing information in . In light to , the current implementation of does the following assuming that the builder's current translator class is not a subclass of : If one or more node classes specified by (and derived from ) are not handled by the translator class, all are transformed into nodes instead (with the same attributes). If in addition the node is not handled by the visitor class, it is transformed into an node instead as well. This implementation choice suffers from the following disadvantages: Whenever a node inherits from , the class must be to the list. A custom translator not inheriting from should not be penalized if it only implements and handle it internally. Currently, they can emulate that behaviour by implementing and checking whether the XML attributes are those that we would find on nodes. As such, I suggest the following features: Use the hook together with a meta-keyword (defaults to ) to automatically add a class derived from to the list. That way, users may still use as a regular base class without affecting the nodes expected by Sphinx itself. A custom translator class orthogonal to must satisfy one of the following exclusive conditions: explicitly supports all nodes described in by providing methods. If a node inherits from but is not in , then must explicitly specify the corresponding visitor method. That way, nodes expected from Sphinx (i.e., those in ) are correctly dispatched and the remaining nodes are simply kept as is and handled as any other nodes. specifies a generic fallback method and possibly zero or more visitor methods for handling specific nodes. The nodes are then dispatched to their most precise type. does not have an interface for nodes and should therefore use a fallback. However, if there are other post-transforms coming after the fallback transform, it would be good to keep some information on the type the node originally had before converting them into nodes. For instance, we could add as an extra XML attribute of the transformed inline node. For , since the latter does not inherit from , I suggest that the fallback implementation simply add as an XML attribute in order to have a similar behaviour.

super().__init__(rawsource, text, *children, **attributes)         self['classes'].extend(self.classes)     def __init_subclass__(cls, *, _sig_element=False, **kwargs):        super().__init_subclass__(**kwargs)        if _sig_element:            # add the class to the SIG_ELEMENTS set if asked            SIG_ELEMENTS.add(cls)  # to not reinvent the wheel, the classes in the following desc_sig classes # are based on those used in Pygments class desc_sig_space(desc_sig_element):class desc_sig_space(desc_sig_element, _sig_element=True):     """Node for a space in a signature."""     classes = ["w"]


Question: [FEATURE] Avoid losing information in . In light to , the current implementation of does the following assuming that the builder's current translator class is not a subclass of : If one or more node classes specified by (and derived from ) are not handled by the translator class, all are transformed into nodes instead (with the same attributes). If in addition the node is not handled by the visitor class, it is transformed into an node instead as well. This implementation choice suffers from the following disadvantages: Whenever a node inherits from , the class must be to the list. A custom translator not inheriting from should not be penalized if it only implements and handle it internally. Currently, they can emulate that behaviour by implementing and checking whether the XML attributes are those that we would find on nodes. As such, I suggest the following features: Use the hook together with a meta-keyword (defaults to ) to automatically add a class derived from to the list. That way, users may still use as a regular base class without affecting the nodes expected by Sphinx itself. A custom translator class orthogonal to must satisfy one of the following exclusive conditions: explicitly supports all nodes described in by providing methods. If a node inherits from but is not in , then must explicitly specify the corresponding visitor method. That way, nodes expected from Sphinx (i.e., those in ) are correctly dispatched and the remaining nodes are simply kept as is and handled as any other nodes. specifies a generic fallback method and possibly zero or more visitor methods for handling specific nodes. The nodes are then dispatched to their most precise type. does not have an interface for nodes and should therefore use a fallback. However, if there are other post-transforms coming after the fallback transform, it would be good to keep some information on the type the node originally had before converting them into nodes. For instance, we could add as an extra XML attribute of the transformed inline node. For , since the latter does not inherit from , I suggest that the fallback implementation simply add as an XML attribute in order to have a similar behaviour.

super().__init__(rawsource, text, *children, **attributes)  class desc_sig_name(desc_sig_element):class desc_sig_name(desc_sig_element, _sig_element=True):     """Node for an identifier in a signature."""     classes = ["n"]  class desc_sig_operator(desc_sig_element):class desc_sig_operator(desc_sig_element, _sig_element=True):     """Node for an operator in a signature."""     classes = ["o"]  class desc_sig_punctuation(desc_sig_element):class desc_sig_punctuation(desc_sig_element, _sig_element=True):     """Node for punctuation in a signature."""     classes = ["p"]  class desc_sig_keyword(desc_sig_element):class desc_sig_keyword(desc_sig_element, _sig_element=True):     """Node for a general keyword in a signature."""     classes = ["k"]  class desc_sig_keyword_type(desc_sig_element):class desc_sig_keyword_type(desc_sig_element, _sig_element=True):     """Node for a keyword which is a built-in type in a signature."""     classes = ["kt"]  class desc_sig_literal_number(desc_sig_element):class desc_sig_literal_number(desc_sig_element, _sig_element=True):     """Node for a numeric literal in a signature."""     classes = ["m"]  class desc_sig_literal_string(desc_sig_element):class desc_sig_literal_string(desc_sig_element, _sig_element=True):     """Node for a string literal in a signature."""     classes = ["s"]  class desc_sig_literal_char(desc_sig_element):class desc_sig_literal_char(desc_sig_element, _sig_element=True):     """Node for a character literal in a signature."""     classes = ["sc"]  SIG_ELEMENTS = [desc_sig_space,                desc_sig_name,                desc_sig_operator,                desc_sig_punctuation,                desc_sig_keyword, desc_sig_keyword_type,                desc_sig_literal_number, desc_sig_literal_string, desc_sig_literal_char] ############################################################### # new admonition-like constructs 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


Question: [FEATURE] Avoid losing information in . In light to , the current implementation of does the following assuming that the builder's current translator class is not a subclass of : If one or more node classes specified by (and derived from ) are not handled by the translator class, all are transformed into nodes instead (with the same attributes). If in addition the node is not handled by the visitor class, it is transformed into an node instead as well. This implementation choice suffers from the following disadvantages: Whenever a node inherits from , the class must be to the list. A custom translator not inheriting from should not be penalized if it only implements and handle it internally. Currently, they can emulate that behaviour by implementing and checking whether the XML attributes are those that we would find on nodes. As such, I suggest the following features: Use the hook together with a meta-keyword (defaults to ) to automatically add a class derived from to the list. That way, users may still use as a regular base class without affecting the nodes expected by Sphinx itself. A custom translator class orthogonal to must satisfy one of the following exclusive conditions: explicitly supports all nodes described in by providing methods. If a node inherits from but is not in , then must explicitly specify the corresponding visitor method. That way, nodes expected from Sphinx (i.e., those in ) are correctly dispatched and the remaining nodes are simply kept as is and handled as any other nodes. specifies a generic fallback method and possibly zero or more visitor methods for handling specific nodes. The nodes are then dispatched to their most precise type. does not have an interface for nodes and should therefore use a fallback. However, if there are other post-transforms coming after the fallback transform, it would be good to keep some information on the type the node originally had before converting them into nodes. For instance, we could add as an extra XML attribute of the transformed inline node. For , since the latter does not inherit from , I suggest that the fallback implementation simply add as an XML attribute in order to have a similar behaviour.

# subclass of SphinxTranslator supports desc_sig_element nodes automatically.             return         # for the leaf elements (desc_sig_element), the translator should support _all_        if not all(has_visitor(translator, node) for node in addnodes.SIG_ELEMENTS):        # for the leaf elements (desc_sig_element), the translator should support _all_,        # unless there exists a generic visit_desc_sig_element default visitor        if (not all(has_visitor(translator, node) for node in addnodes.SIG_ELEMENTS)                and not has_visitor(translator, addnodes.desc_sig_element)):             self.fallback(addnodes.desc_sig_element)          if not has_visitor(translator, addnodes.desc_inline):             self.fallback(addnodes.desc_inline)     def fallback(self, nodeType: Any) -> None:        for node in self.document.findall(nodeType):    def fallback(self, node_type: Any) -> None:        """Translate nodes of type *node_type* to docutils inline nodes.        The original node type name is stored as a string in a private        ``_sig_node_type`` attribute if the latter did not exist.        """        for node in self.document.findall(node_type):             newnode = nodes.inline()             newnode.update_all_atts(node)             newnode.extend(node)            # Only set _sig_node_type if not defined by the user            newnode.setdefault('_sig_node_type', node.tagname)             node.replace_self(newnode)


Question: util.inspect.objectdescription: does not emit reliable ordering for a set nested within another collection Differences appear in some v5.3.0 generated object descriptions for v1.8.1, as demonstrated by . Arguably it could make sense for code authors to intentionally write elements in their code files in a way that does not correspond to their computed sort order -- as a means to communicate with human readers about abstract ideas that aren't relevant to computers at runtime, for example. However, the current behaviour does result in non-reproducible documentation output. In particular, the ordering of a class attribute with a value that contains a set-within-a-tuple seems unreliable across differing builds: ... is emitted variously as ... ... or ... cc who has been . It is not yet clear to me exactly what circumstances cause the ordering of elements to vary - and it's OK not to proceed until that's figured out (maybe not a blocker, but it would be nice to have confidence about the cause). From searching around on previous issues while writing up this bugreport: I wonder if this could be an edge-case for / follow-up to . Although these build log links are somewhat ephemeral, the system environment details for two builds that produce differing output are visible at: https://tests.reproducible- https://tests.reproducible- No response_

raise AttributeError(name) from exc  def object_description(object: Any) -> str:    """A repr() implementation that returns text safe to use in reST context."""    if isinstance(object, dict):def object_description(obj: Any, *, _seen: frozenset = frozenset()) -> str:    """A repr() implementation that returns text safe to use in reST context.    Maintains a set of 'seen' object IDs to detect and avoid infinite recursion.    """    seen = _seen    if isinstance(obj, dict):        if id(obj) in seen:            return 'dict(...)'        seen |= {id(obj)}         try:            sorted_keys = sorted(object)        except Exception:            pass  # Cannot sort dict keys, fall back to generic repr        else:            items = ("%s: %s" %                     (object_description(key), object_description(object[key]))                     for key in sorted_keys)            return "{%s}" % ", ".join(items)    elif isinstance(object, set):            sorted_keys = sorted(obj)        except TypeError:            # Cannot sort dict keys, fall back to using descriptions as a sort key            sorted_keys = sorted(obj, key=lambda k: object_description(k, _seen=seen))        items = ((object_description(key, _seen=seen),                  object_description(obj[key], _seen=seen)) for key in sorted_keys)        return '{%s}' % ', '.join(f'{key}: {value}' for (key, value) in items)    elif isinstance(obj, set):        if id(obj) in seen:            return 'set(...)'        seen |= {id(obj)}         try:            sorted_values = sorted(object)            sorted_values = sorted(obj)         except TypeError:            pass  # Cannot sort set values, fall back to generic repr        else:            return "{%s}" % ", ".join(object_description(x) for x in sorted_values)    elif isinstance(object, frozenset):            # Cannot sort set values, fall back to using descriptions as a sort key            sorted_values = sorted(obj, key=lambda x: object_description(x, _seen=seen))        return '{%s}' % ', '.join(object_description(x, _seen=seen) for x in sorted_values)    elif isinstance(obj, frozenset):        if id(obj) in seen:            return 'frozenset(...)'        seen |= {id(obj)}         try:            sorted_values = sorted(object)            sorted_values = sorted(obj)         except TypeError:            pass  # Cannot sort frozenset values, fall back to generic repr        else:            return "frozenset({%s})" % ", ".join(object_description(x)                                                 for x in sorted_values)    elif isinstance(object, enum.Enum):        return f"{object.__class__.__name__}.{object.name}"            # Cannot sort frozenset values, fall back to using descriptions as a sort key            sorted_values = sorted(obj, key=lambda x: object_description(x, _seen=seen))        return 'frozenset({%s})' % ', '.join(object_description(x, _seen=seen)                                             for x in sorted_values)    elif isinstance(obj, enum.Enum):        return f'{obj.__class__.__name__}.{obj.name}'    elif isinstance(obj, tuple):        if id(obj) in seen:            return 'tuple(...)'        seen |= frozenset([id(obj)])        return '(%s%s)' % (            ', '.join(object_description(x, _seen=seen) for x in obj),            ',' * (len(obj) == 1),        )    elif isinstance(obj, list):        if id(obj) in seen:            return 'list(...)'        seen |= {id(obj)}        return '[%s]' % ', '.join(object_description(x, _seen=seen) for x in obj)      try:        s = repr(object)        s = repr(obj)     except Exception as exc:         raise ValueError from exc     # Strip non-deterministic memory addresses such as


Question: Napoleon causes warning about missing end-string when encountering a reference on the first line of a docstring in a dataclass When using , a docstring of a dataclass attribute will cause an warning for a reference that's placed on the first line of this docstring. The reference itself is processed correctly. This causes the warning This one works just fine. Notice the linebreak in the docstring No response

_single_colon_regex = re.compile(r'(?<!:):(?!:)') _xref_or_code_regex = re.compile(     r'((?::(?:[a-zA-Z0-9]+[\-_+:.])*[a-zA-Z0-9]+:`.+?`)|'    r'(?:``.+?``))')    r'(?:``.+?``)|'    r'(?::meta .+:.*)|'    r'(?:`.+?\s*(?<!\x00)<.*?>`))') _xref_regex = re.compile(     r'(?:(?::(?:[a-zA-Z0-9]+[\-_+:.])*[a-zA-Z0-9]+:)?`.+?`)', )


Question: Using rstprolog removes top level headings containing a domain directive If is set, then any documents that contain a domain directive as the first heading (eg ) do not render the heading correctly or include the heading in the toctree. In the example below, if the heading of were instead of then the heading displays correctly. Similarly, if you do not set then the heading will display correctly. This appears to have been broken for some time because I can reproduce it in v4.0.0 of Sphinx : : No response_

from docutils.parsers.rst import roles from docutils.parsers.rst.languages import en as englishfrom docutils.parsers.rst.states import Body from docutils.statemachine import StringList from docutils.utils import Reporterfrom jinja2 import Environmentfrom jinja2 import Environment, pass_environment  from sphinx.locale import __ from sphinx.util import docutils, logging try:    from jinja2.utils import pass_environmentexcept ImportError:    from jinja2 import environmentfilter as pass_environment logger = logging.getLogger(__name__) docinfo_re = re.compile(':\\w+:.*?')FIELD_NAME_RE = re.compile(Body.patterns['field_marker']) symbols_re = re.compile(r'([!-\-/:-@\[-`{-~])')  # symbols without dot(0x2e) SECTIONING_CHARS = ['=', '-', '~']


Question: Using rstprolog removes top level headings containing a domain directive If is set, then any documents that contain a domain directive as the first heading (eg ) do not render the heading correctly or include the heading in the toctree. In the example below, if the heading of were instead of then the heading displays correctly. Similarly, if you do not set then the heading will display correctly. This appears to have been broken for some time because I can reproduce it in v4.0.0 of Sphinx : : No response_

if prolog:         pos = 0         for line in content:            if docinfo_re.match(line):            if FIELD_NAME_RE.match(line):                 pos += 1             else:                 break


Question: Using rstprolog removes top level headings containing a domain directive If is set, then any documents that contain a domain directive as the first heading (eg ) do not render the heading correctly or include the heading in the toctree. In the example below, if the heading of were instead of then the heading displays correctly. Similarly, if you do not set then the heading will display correctly. This appears to have been broken for some time because I can reproduce it in v4.0.0 of Sphinx : : No response_

pos += 1          # insert prolog (after docinfo if exists)<ins>        lineno = 0</ins>         for lineno, line in enumerate(prolog.splitlines()):             content.insert(pos + lineno, line, '<rst_prolog>', lineno)


Question: Allow disabling linkcheck anchor checks for specific URLs Is your feature request related to a problem? Please describe. It appears GitHub has made the Markdown renderer/file viewer require JavaScript which breaks linkcheck anchor checks. Describe the solution you'd like A config which disables the linkcheck anchors check based on a regex of the entire URL would allow for cases like these to be handled while still validating whether the page itself exists and keep anchor checks enabled for others. Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered. Additional context This is what looks like without JavaScript enabled: <img width="1007" alt="Capture d’écran 2023-07-07 à 17 00 57" src=""- Related issue:

self.anchors_ignore: list[re.Pattern[str]] = list(             map(re.compile, config.linkcheck_anchors_ignore))<ins>        self.anchors_ignore_for_url: list[re.Pattern[str]] = list(            map(re.compile, config.linkcheck_anchors_ignore_for_url))</ins>         self.documents_exclude: list[re.Pattern[str]] = list(             map(re.compile, config.linkcheck_exclude_documents))         self.auth = [(re.compile(pattern), auth_info) for pattern, auth_info


Question: Allow disabling linkcheck anchor checks for specific URLs Is your feature request related to a problem? Please describe. It appears GitHub has made the Markdown renderer/file viewer require JavaScript which breaks linkcheck anchor checks. Describe the solution you'd like A config which disables the linkcheck anchors check based on a regex of the entire URL would allow for cases like these to be handled while still validating whether the page itself exists and keep anchor checks enabled for others. Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered. Additional context This is what looks like without JavaScript enabled: <img width="1007" alt="Capture d’écran 2023-07-07 à 17 00 57" src=""- Related issue:

def _check_uri(self, uri: str, hyperlink: Hyperlink) -> tuple[str, str, int]:         req_url, delimiter, anchor = uri.partition('#')        for rex in self.anchors_ignore if delimiter and anchor else []:            if rex.match(anchor):                anchor = ''                break        if delimiter and anchor:            for rex in self.anchors_ignore:                if rex.match(anchor):                    anchor = ''                    break            else:                for rex in self.anchors_ignore_for_url:                    if rex.match(req_url):                        anchor = ''                        break          # handle non-ASCII URIs         try:


Question: Allow disabling linkcheck anchor checks for specific URLs Is your feature request related to a problem? Please describe. It appears GitHub has made the Markdown renderer/file viewer require JavaScript which breaks linkcheck anchor checks. Describe the solution you'd like A config which disables the linkcheck anchors check based on a regex of the entire URL would allow for cases like these to be handled while still validating whether the page itself exists and keep anchor checks enabled for others. Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered. Additional context This is what looks like without JavaScript enabled: <img width="1007" alt="Capture d’écran 2023-07-07 à 17 00 57" src=""- Related issue:

# Anchors starting with ! are ignored since they are     # commonly used for dynamic pages     app.add_config_value('linkcheck_anchors_ignore', ['^!'], False)<ins>    app.add_config_value('linkcheck_anchors_ignore_for_url', (), False, (tuple, list))</ins>     app.add_config_value('linkcheck_rate_limit_timeout', 300.0, False)      app.add_event('linkcheck-process-uri')


Question: Keep 'translated' node attribute Is your feature request related to a problem? Please describe. In my internationalized documentation, I am adding markers to untranslated or partially translated pages, to warn the user that they can see English content and nudge them to help translating (e.g., like this: !). To do this, I'm essentially duplicating part of the transform. This feels clumsy because the transform already knows which nodes are translated and which aren't. In fact, it sets an attribute on the translated ones. However, this attribute is considered internal, so it deletes it at the end: Describe the solution you'd like I'd like to know if it would be acceptable to just delete the two lines of code above in order to let extensions know whether a node has been translated. Describe alternatives you've considered Adding the functionality for "untranslated" markers to Sphinx itself.

node['raw_entries'] = entries                 node['entries'] = new_entries <del>        # remove translated attribute that is used for avoiding double translation.        matcher = NodeMatcher(translated=Any)        for translated in self.document.findall(matcher):  # type: nodes.Element            translated.delattr('translated')</del>  class RemoveTranslatableInline(SphinxTransform):     """


Question: linkcheck builder: begin using requests.Session functionality during linkchecking Is your feature request related to a problem? Please describe. At the moment, the builder performs individual (or similar HTTP request method) operations during linkchecking, without any explicit connection or session pooling. This may be inefficient, because it seems likely that for many use cases, linkchecking will make multiple requests to the same host (because documentation references are likely to have host-locality). Describe the solution you'd like Confirmation that connection pooling is not currently in use would be a good starting point; in other words: we should confirm that linkchecking of multiple URLs on a single host results in multiple TCP connections. Ideally this should be written as a test case. If we can confirm that the problem exists, then we may be able to use some of the from the library that's already in use here to enable connection pooling. Describe alternatives you've considered None so far, although open to suggestions (and improvements on the definition of this feature request). Additional context See note / suggestion about use of context managers:

self.tls_verify = config.tls_verify         self.tls_cacerts = config.tls_cacerts         self._session = requests._Session()         super().__init__(daemon=True)      def run(self) -> None:         while True:             next_check, hyperlink = self.wqueue.get()             if hyperlink is None:                # An empty hyperlink is a signal to shutdown the worker; cleanup resources here                self._session.close()                 break              uri, docname, _docpath, lineno = hyperlink


Question: linkcheck builder: begin using requests.Session functionality during linkchecking Is your feature request related to a problem? Please describe. At the moment, the builder performs individual (or similar HTTP request method) operations during linkchecking, without any explicit connection or session pooling. This may be inefficient, because it seems likely that for many use cases, linkchecking will make multiple requests to the same host (because documentation references are likely to have host-locality). Describe the solution you'd like Confirmation that connection pooling is not currently in use would be a good starting point; in other words: we should confirm that linkchecking of multiple URLs on a single host results in multiple TCP connections. Ideally this should be written as a test case. If we can confirm that the problem exists, then we may be able to use some of the from the library that's already in use here to enable connection pooling. Describe alternatives you've considered None so far, although open to suggestions (and improvements on the definition of this feature request). Additional context See note / suggestion about use of context managers:

return status, info, code <ins>    def _retrieval_methods(self,                           check_anchors: bool,                           anchor: str) -> Iterator[tuple[Callable, dict]]:        if not check_anchors or not anchor:            yield self._session.head, {'allow_redirects': True}        yield self._session.get, {'stream': True}</ins>     def _check_uri(self, uri: str, hyperlink: Hyperlink) -> tuple[str, str, int]:         req_url, delimiter, anchor = uri.partition('#')         for rex in self.anchors_ignore if delimiter and anchor else []:


Question: linkcheck builder: begin using requests.Session functionality during linkchecking Is your feature request related to a problem? Please describe. At the moment, the builder performs individual (or similar HTTP request method) operations during linkchecking, without any explicit connection or session pooling. This may be inefficient, because it seems likely that for many use cases, linkchecking will make multiple requests to the same host (because documentation references are likely to have host-locality). Describe the solution you'd like Confirmation that connection pooling is not currently in use would be a good starting point; in other words: we should confirm that linkchecking of multiple URLs on a single host results in multiple TCP connections. Ideally this should be written as a test case. If we can confirm that the problem exists, then we may be able to use some of the from the library that's already in use here to enable connection pooling. Describe alternatives you've considered None so far, although open to suggestions (and improvements on the definition of this feature request). Additional context See note / suggestion about use of context managers:

error_message = None         status_code = -1         response_url = retry_after = ''        for retrieval_method, kwargs in _retrieval_methods(self.check_anchors, anchor):        for retrieval_method, kwargs in self._retrieval_methods(self.check_anchors, anchor):             try:                 with retrieval_method(                     url=req_url, auth=auth_info,


Question: linkcheck builder: begin using requests.Session functionality during linkchecking Is your feature request related to a problem? Please describe. At the moment, the builder performs individual (or similar HTTP request method) operations during linkchecking, without any explicit connection or session pooling. This may be inefficient, because it seems likely that for many use cases, linkchecking will make multiple requests to the same host (because documentation references are likely to have host-locality). Describe the solution you'd like Confirmation that connection pooling is not currently in use would be a good starting point; in other words: we should confirm that linkchecking of multiple URLs on a single host results in multiple TCP connections. Ideally this should be written as a test case. If we can confirm that the problem exists, then we may be able to use some of the from the library that's already in use here to enable connection pooling. Describe alternatives you've considered None so far, although open to suggestions (and improvements on the definition of this feature request). Additional context See note / suggestion about use of context managers:

return {}  def _retrieval_methods(check_anchors: bool, anchor: str) -> Iterator[tuple[Callable, dict]]:    if not check_anchors or not anchor:        yield requests.head, {'allow_redirects': True}    yield requests.get, {'stream': True} def contains_anchor(response: Response, anchor: str) -> bool:     """Determine if an anchor is contained within an HTTP response.""" diff --git a/sphinx/util/requests.py b/sphinx/util/requests.py-- a/sphinx/util/requests.py++ b/sphinx/util/requests.py


Question: linkcheck builder: begin using requests.Session functionality during linkchecking Is your feature request related to a problem? Please describe. At the moment, the builder performs individual (or similar HTTP request method) operations during linkchecking, without any explicit connection or session pooling. This may be inefficient, because it seems likely that for many use cases, linkchecking will make multiple requests to the same host (because documentation references are likely to have host-locality). Describe the solution you'd like Confirmation that connection pooling is not currently in use would be a good starting point; in other words: we should confirm that linkchecking of multiple URLs on a single host results in multiple TCP connections. Ideally this should be written as a test case. If we can confirm that the problem exists, then we may be able to use some of the from the library that's already in use here to enable connection pooling. Describe alternatives you've considered None so far, although open to suggestions (and improvements on the definition of this feature request). Additional context See note / suggestion about use of context managers:

from __future__ import annotations  import warningsfrom contextlib import contextmanagerfrom typing import Any, Iteratorfrom typing import Any from urllib.parse import urlsplit  import requests


Question: linkcheck builder: begin using requests.Session functionality during linkchecking Is your feature request related to a problem? Please describe. At the moment, the builder performs individual (or similar HTTP request method) operations during linkchecking, without any explicit connection or session pooling. This may be inefficient, because it seems likely that for many use cases, linkchecking will make multiple requests to the same host (because documentation references are likely to have host-locality). Describe the solution you'd like Confirmation that connection pooling is not currently in use would be a good starting point; in other words: we should confirm that linkchecking of multiple URLs on a single host results in multiple TCP connections. Ideally this should be written as a test case. If we can confirm that the problem exists, then we may be able to use some of the from the library that's already in use here to enable connection pooling. Describe alternatives you've considered None so far, although open to suggestions (and improvements on the definition of this feature request). Additional context See note / suggestion about use of context managers:

f'Sphinx/{sphinx.__version__}')  <del>@contextmanagerdef ignore_insecure_warning(verify: bool) -> Iterator[None]:    with warnings.catch_warnings():        if not verify:            # ignore InsecureRequestWarning if verify=False            warnings.filterwarnings("ignore", category=InsecureRequestWarning)        yield</del> def _get_tls_cacert(url: str, certs: str | dict[str, str] | None) -> str | bool:     """Get additional CA cert for a specific URL."""     if not certs:


Question: linkcheck builder: begin using requests.Session functionality during linkchecking Is your feature request related to a problem? Please describe. At the moment, the builder performs individual (or similar HTTP request method) operations during linkchecking, without any explicit connection or session pooling. This may be inefficient, because it seems likely that for many use cases, linkchecking will make multiple requests to the same host (because documentation references are likely to have host-locality). Describe the solution you'd like Confirmation that connection pooling is not currently in use would be a good starting point; in other words: we should confirm that linkchecking of multiple URLs on a single host results in multiple TCP connections. Ideally this should be written as a test case. If we can confirm that the problem exists, then we may be able to use some of the from the library that's already in use here to enable connection pooling. Describe alternatives you've considered None so far, although open to suggestions (and improvements on the definition of this feature request). Additional context See note / suggestion about use of context managers:

return certs.get(hostname, True)  def get(url: str,        _user_agent: str = '',        _tls_info: tuple[bool, str | dict[str, str] | None] = (),  # type: ignore[assignment]        **kwargs: Any) -> requests.Response:    """Sends a HEAD request like requests.head().def get(url: str, **kwargs: Any) -> requests.Response:    """Sends a GET request like requests.get().      This sets up User-Agent header and TLS verification automatically."""    headers = kwargs.setdefault('headers', {})    headers.setdefault('User-Agent', _user_agent or _USER_AGENT)    if _tls_info:        tls_verify, tls_cacerts = _tls_info        verify = bool(kwargs.get('verify', tls_verify))        kwargs.setdefault('verify', verify and _get_tls_cacert(url, tls_cacerts))    else:        verify = kwargs.get('verify', True)    with _Session() as session:        return session.get(url, **kwargs)     with ignore_insecure_warning(verify):        return requests.get(url, **kwargs) def head(url: str,         _user_agent: str = '',         _tls_info: tuple[bool, str | dict[str, str] | None] = (),  # type: ignore[assignment]         **kwargs: Any) -> requests.Response:def head(url: str, **kwargs: Any) -> requests.Response:     """Sends a HEAD request like requests.head().      This sets up User-Agent header and TLS verification automatically."""    headers = kwargs.setdefault('headers', {})    headers.setdefault('User-Agent', _user_agent or _USER_AGENT)    if _tls_info:        tls_verify, tls_cacerts = _tls_info        verify = bool(kwargs.get('verify', tls_verify))        kwargs.setdefault('verify', verify and _get_tls_cacert(url, tls_cacerts))    else:        verify = kwargs.get('verify', True)    with _Session() as session:        return session.head(url, **kwargs)     with ignore_insecure_warning(verify):        return requests.head(url, **kwargs)class _Session(requests.Session):    def request(  # type: ignore[override]        self, method: str, url: str,        _user_agent: str = '',        _tls_info: tuple[bool, str | dict[str, str] | None] = (),  # type: ignore[assignment]        **kwargs: Any,    ) -> requests.Response:        """Sends a request with an HTTP verb and url.        This sets up User-Agent header and TLS verification automatically."""        headers = kwargs.setdefault('headers', {})        headers.setdefault('User-Agent', _user_agent or _USER_AGENT)        if _tls_info:            tls_verify, tls_cacerts = _tls_info            verify = bool(kwargs.get('verify', tls_verify))            kwargs.setdefault('verify', verify and _get_tls_cacert(url, tls_cacerts))        else:            verify = kwargs.get('verify', True)        if verify:            return super().request(method, url, **kwargs)        with warnings.catch_warnings():            # ignore InsecureRequestWarning if verify=False            warnings.filterwarnings("ignore", category=InsecureRequestWarning)            return super().request(method, url, **kwargs)


Question: source-read event does not modify include'd files source In , we use a custom extension to do some search and replace in literal blocks, see We discovered ( and ) that this does not work on all files and some are left out of this mechanism. Such is the case for include'd files. I could reproduce on Sphinx 5.0.2. something-to- my- will contain: Note that the dumping docname and source[0] shows that the function actually gets called for something-to- file and its content is correctly replaced in source[0], it just does not make it to the final HTML file for some reason. should contain: No response Linux 10 2 Custom extension using source-read event No response No response source-read event does not modify include'd files source In , we use a custom extension to do some search and replace in literal blocks, see We discovered ( and ) that this does not work on all files and some are left out of this mechanism. Such is the case for include'd files. I could reproduce on Sphinx 5.0.2. something-to- my- will contain: Note that the dumping docname and source[0] shows that the function actually gets called for something-to- file and its content is correctly replaced in source[0], it just does not make it to the final HTML file for some reason. should contain: No response Linux 10 2 Custom extension using source-read event No response No response

from docutils.parsers.rst.directives.admonitions import BaseAdmonition from docutils.parsers.rst.directives.misc import Class from docutils.parsers.rst.directives.misc import Include as BaseInclude<ins>from docutils.statemachine import StateMachine</ins>  from sphinx import addnodes from sphinx.domains.changeset import VersionChange  # noqa: F401  # for compatibility


Question: source-read event does not modify include'd files source In , we use a custom extension to do some search and replace in literal blocks, see We discovered ( and ) that this does not work on all files and some are left out of this mechanism. Such is the case for include'd files. I could reproduce on Sphinx 5.0.2. something-to- my- will contain: Note that the dumping docname and source[0] shows that the function actually gets called for something-to- file and its content is correctly replaced in source[0], it just does not make it to the final HTML file for some reason. should contain: No response Linux 10 2 Custom extension using source-read event No response No response source-read event does not modify include'd files source In , we use a custom extension to do some search and replace in literal blocks, see We discovered ( and ) that this does not work on all files and some are left out of this mechanism. Such is the case for include'd files. I could reproduce on Sphinx 5.0.2. something-to- my- will contain: Note that the dumping docname and source[0] shows that the function actually gets called for something-to- file and its content is correctly replaced in source[0], it just does not make it to the final HTML file for some reason. should contain: No response Linux 10 2 Custom extension using source-read event No response No response

from sphinx.util.docutils import SphinxDirective from sphinx.util.matching import Matcher, patfilter from sphinx.util.nodes import explicit_title_re<ins>from sphinx.util.osutil import os_path</ins>  if TYPE_CHECKING:     from docutils.nodes import Element, Node


Question: source-read event does not modify include'd files source In , we use a custom extension to do some search and replace in literal blocks, see We discovered ( and ) that this does not work on all files and some are left out of this mechanism. Such is the case for include'd files. I could reproduce on Sphinx 5.0.2. something-to- my- will contain: Note that the dumping docname and source[0] shows that the function actually gets called for something-to- file and its content is correctly replaced in source[0], it just does not make it to the final HTML file for some reason. should contain: No response Linux 10 2 Custom extension using source-read event No response No response source-read event does not modify include'd files source In , we use a custom extension to do some search and replace in literal blocks, see We discovered ( and ) that this does not work on all files and some are left out of this mechanism. Such is the case for include'd files. I could reproduce on Sphinx 5.0.2. something-to- my- will contain: Note that the dumping docname and source[0] shows that the function actually gets called for something-to- file and its content is correctly replaced in source[0], it just does not make it to the final HTML file for some reason. should contain: No response Linux 10 2 Custom extension using source-read event No response No response

"""      def run(self) -> list[Node]:<ins>        # To properly emit "source-read" events from included RST text,        # we must patch the ``StateMachine.insert_input()`` method.        # In the future, docutils will hopefully offer a way for Sphinx        # to provide the RST parser to use        # when parsing RST text that comes in via Include directive.        def _insert_input(include_lines, path):            # First, we need to combine the lines back into text so that            # we can send it with the source-read event.            # In docutils 0.18 and later, there are two lines at the end            # that act as markers.            # We must preserve them and leave them out of the source-read event:            text = "\n".join(include_lines[:-2])            # The docname to pass into the source-read event            docname = self.env.path2doc(os_path(path))            # Emit the "source-read" event            arg = [text]            self.env.app.events.emit("source-read", docname, arg)            text = arg[0]            # Split back into lines and reattach the two marker lines            include_lines = text.splitlines() + include_lines[-2:]            # Call the parent implementation.            # Note that this snake does not eat its tail because we patch            # the *Instance* method and this call is to the *Class* method.            return StateMachine.insert_input(self.state_machine, include_lines, path)        # Only enable this patch if there are listeners for 'source-read'.        if self.env.app.events.listeners.get('source-read'):            # See https://github.com/python/mypy/issues/2427 for details on the mypy issue            self.state_machine.insert_input = _insert_input  # type: ignore[method-assign]</ins>         if self.arguments[0].startswith('<') and \            self.arguments[0].endswith('>'):             # docutils "standard" includes, do not do path processing


Question: linkcheck failing after Sphinx 7.1.0 release Starting with , my package(s) started reporting failures due to "Anchor not found", e.g., Reverting to Sphinx 7.0.1 fixes the issue. reveals the issue started with , this PR: $ git clone $ cd photutils $ tox -e linkcheck No response No response

_user_agent=self.user_agent,                     _tls_info=(self.tls_verify, self.tls_cacerts),                 ) as response:                    if response.ok and anchor and not contains_anchor(response, anchor):                    if (self.check_anchors and response.ok and anchor                            and not contains_anchor(response, anchor)):                         raise Exception(__(f'Anchor {anchor!r} not found'))                  # Copy data we need from the (closed) response


Question: autodoc preserve defaults leads to exception on multiline lambda In , I've stumbled into an issue where the docs builds are failing (). After some , I learned that the issue seems to be related to the use of with and the use of where the lambda is on a different line from the . Weirdly, removing the carriage return after suppresses the error. Also, converting to a traditional decorator or replacing the lambda with a simple function also suppresses the error:

import ast import inspectfrom typing import TYPE_CHECKING, Anyimport typesimport warningsfrom typing import TYPE_CHECKING  import sphinxfrom sphinx.deprecation import RemovedInSphinx90Warning from sphinx.locale import __ from sphinx.pycode.ast import unparse as ast_unparse from sphinx.util import logging  if TYPE_CHECKING:    from typing import Any     from sphinx.application import Sphinx  logger = logging.getLogger(__name__)_LAMBDA_NAME = (lambda: None).__name__   class DefaultValue:


Question: autodoc preserve defaults leads to exception on multiline lambda In , I've stumbled into an issue where the docs builds are failing (). After some , I learned that the issue seems to be related to the use of with and the use of where the lambda is on a different line from the . Weirdly, removing the carriage return after suppresses the error. Also, converting to a traditional decorator or replacing the lambda with a simple function also suppresses the error:

def get_function_def(obj: Any) -> ast.FunctionDef | None:     """Get FunctionDef object from living object.     This tries to parse original code for living object and returns     AST node for given *obj*.     """    warnings.warn('sphinx.ext.autodoc.preserve_defaults.get_function_def is'                  ' deprecated and scheduled for removal in Sphinx 9.'                  ' Use sphinx.ext.autodoc.preserve_defaults._get_arguments() to'                  ' extract AST arguments objects from a lambda or regular'                  ' function.', RemovedInSphinx90Warning, stacklevel=2)     try:         source = inspect.getsource(obj)        if source.startswith((' ', r'\t')):        if source.startswith((' ', '\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)


Question: autodoc preserve defaults leads to exception on multiline lambda In , I've stumbled into an issue where the docs builds are failing (). After some , I learned that the issue seems to be related to the use of with and the use of where the lambda is on a different line from the . Weirdly, removing the carriage return after suppresses the error. Also, converting to a traditional decorator or replacing the lambda with a simple function also suppresses the error:

return None  <ins>def _get_arguments(obj: Any, /) -> ast.arguments | None:    """Parse 'ast.arguments' from an object.    This tries to parse the original code for an object and returns    an 'ast.arguments' node.    """    try:        source = inspect.getsource(obj)        if source.startswith((' ', '\t')):            # 'obj' is in some indented block.            module = ast.parse('if True:\n' + source)            subject = module.body[0].body[0]  # type: ignore[attr-defined]        else:            module = ast.parse(source)            subject = module.body[0]    except (OSError, TypeError):        # bail; failed to load source for 'obj'.        return None    except SyntaxError:        if _is_lambda(obj):            # Most likely a multi-line arising from detecting a lambda, e.g.:            #            # class Egg:            #     x = property(            #         lambda self: 1, doc="...")            return None        # Other syntax errors that are not due to the fact that we are        # documenting a lambda function are propagated        # (in particular if a lambda is renamed by the user).        raise    return _get_arguments_inner(subject)def _is_lambda(x, /):    return isinstance(x, types.LambdaType) and x.__name__ == _LAMBDA_NAMEdef _get_arguments_inner(x: Any, /) -> ast.arguments | None:    if isinstance(x, (ast.AsyncFunctionDef, ast.FunctionDef, ast.Lambda)):        return x.args    if isinstance(x, (ast.Assign, ast.AnnAssign)):        return _get_arguments_inner(x.value)    return None</ins> def get_default_value(lines: list[str], position: ast.AST) -> str | None:     try:         if position.lineno == position.end_lineno:


Question: autodoc preserve defaults leads to exception on multiline lambda In , I've stumbled into an issue where the docs builds are failing (). After some , I learned that the issue seems to be related to the use of with and the use of where the lambda is on a different line from the . Weirdly, removing the carriage return after suppresses the error. Also, converting to a traditional decorator or replacing the lambda with a simple function also suppresses the error:

try:         lines = inspect.getsource(obj).splitlines()        if lines[0].startswith((' ', r'\t')):            lines.insert(0, '')  # insert a dummy line to follow what get_function_def() does.        if lines[0].startswith((' ', '\t')):            # insert a dummy line to follow what _get_arguments() does.            lines.insert(0, '')     except (OSError, TypeError):         lines = []      try:        function = get_function_def(obj)        assert function is not None  # for mypy        if function.args.defaults or function.args.kw_defaults:        args = _get_arguments(obj)        if args is None:            # If the object is a built-in, we won't be always able to recover            # the function definition and its arguments. This happens if *obj*            # is the `__init__` method generated automatically for dataclasses.            return        if args.defaults or args.kw_defaults:             sig = inspect.signature(obj)            defaults = list(function.args.defaults)            kw_defaults = list(function.args.kw_defaults)            defaults = list(args.defaults)            kw_defaults = list(args.kw_defaults)             parameters = list(sig.parameters.values())             for i, param in enumerate(parameters):                 if param.default is param.empty:


Question: Support for functions It would be nice if there was some mechanism to automagically pick up the overloads to a function and list them together... e.g.

import re import warnings from types import ModuleTypefrom typing import Any, Callable, Dict, Iterator, List, Sequence, Set, Tuple, Unionfrom typing import Any, Callable, Dict, Iterator, List, Sequence, Set, Tuple, Type, Unionfrom unittest.mock import patch  from docutils.statemachine import StringList


Question: Support for functions It would be nice if there was some mechanism to automagically pick up the overloads to a function and list them together... e.g.

self.add_line('   :async:', sourcename)  <ins>class SingledispatchFunctionDocumenter(FunctionDocumenter):    """    Specialized Documenter subclass for singledispatch'ed functions.    """    objtype = 'singledispatch_function'    directivetype = 'function'    member_order = 30    # before FunctionDocumenter    priority = FunctionDocumenter.priority + 1    @classmethod    def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any                            ) -> bool:        return (super().can_document_member(member, membername, isattr, parent) and                inspect.is_singledispatch_function(member))    def add_directive_header(self, sig: str) -> None:        sourcename = self.get_sourcename()        # intercept generated directive headers        # TODO: It is very hacky to use mock to intercept header generation        with patch.object(self, 'add_line') as add_line:            super().add_directive_header(sig)        # output first line of header        self.add_line(*add_line.call_args_list[0][0])        # inserts signature of singledispatch'ed functions        for typ, func in self.object.registry.items():            if typ is object:                pass  # default implementation. skipped.            else:                self.annotate_to_first_argument(func, typ)                documenter = FunctionDocumenter(self.directive, '')                documenter.object = func                self.add_line('   %s%s' % (self.format_name(),                                           documenter.format_signature()),                              sourcename)        # output remains of directive header        for call in add_line.call_args_list[1:]:            self.add_line(*call[0])    def annotate_to_first_argument(self, func: Callable, typ: Type) -> None:        """Annotate type hint to the first argument of function if needed."""        sig = inspect.signature(func)        if len(sig.parameters) == 0:            return        name = list(sig.parameters)[0]        if name not in func.__annotations__:            func.__annotations__[name] = typ</ins> class DecoratorDocumenter(FunctionDocumenter):     """     Specialized Documenter subclass for decorator functions.


Question: Support for functions It would be nice if there was some mechanism to automagically pick up the overloads to a function and list them together... e.g.

pass  <ins>class SingledispatchMethodDocumenter(MethodDocumenter):    """    Specialized Documenter subclass for singledispatch'ed methods.    """    objtype = 'singledispatch_method'    directivetype = 'method'    member_order = 50    # before MethodDocumenter    priority = MethodDocumenter.priority + 1    @classmethod    def can_document_member(cls, member: Any, membername: str, isattr: bool, parent: Any                            ) -> bool:        if super().can_document_member(member, membername, isattr, parent) and parent.object:            meth = parent.object.__dict__.get(membername)            return inspect.is_singledispatch_method(meth)        else:            return False    def add_directive_header(self, sig: str) -> None:        sourcename = self.get_sourcename()        # intercept generated directive headers        # TODO: It is very hacky to use mock to intercept header generation        with patch.object(self, 'add_line') as add_line:            super().add_directive_header(sig)        # output first line of header        self.add_line(*add_line.call_args_list[0][0])        # inserts signature of singledispatch'ed functions        meth = self.parent.__dict__.get(self.objpath[-1])        for typ, func in meth.dispatcher.registry.items():            if typ is object:                pass  # default implementation. skipped.            else:                self.annotate_to_first_argument(func, typ)                documenter = MethodDocumenter(self.directive, '')                documenter.object = func                self.add_line('   %s%s' % (self.format_name(),                                           documenter.format_signature()),                              sourcename)        # output remains of directive header        for call in add_line.call_args_list[1:]:            self.add_line(*call[0])    def annotate_to_first_argument(self, func: Callable, typ: Type) -> None:        """Annotate type hint to the first argument of function if needed."""        sig = inspect.signature(func, bound_method=True)        if len(sig.parameters) == 0:            return        name = list(sig.parameters)[0]        if name not in func.__annotations__:            func.__annotations__[name] = typ</ins> class AttributeDocumenter(DocstringStripSignatureMixin, ClassLevelDocumenter):  # type: ignore     """     Specialized Documenter subclass for attributes.


Question: Support for functions It would be nice if there was some mechanism to automagically pick up the overloads to a function and list them together... e.g.

app.add_autodocumenter(DataDocumenter)     app.add_autodocumenter(DataDeclarationDocumenter)     app.add_autodocumenter(FunctionDocumenter)    app.add_autodocumenter(SingledispatchFunctionDocumenter)     app.add_autodocumenter(DecoratorDocumenter)     app.add_autodocumenter(MethodDocumenter)    app.add_autodocumenter(SingledispatchMethodDocumenter)     app.add_autodocumenter(AttributeDocumenter)     app.add_autodocumenter(PropertyDocumenter)     app.add_autodocumenter(InstanceAttributeDocumenter)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


Question: Support for functions It would be nice if there was some mechanism to automagically pick up the overloads to a function and list them together... e.g.

FunctionDocumenter, MethodDocumenter, AttributeDocumenter,         InstanceAttributeDocumenter, DecoratorDocumenter, PropertyDocumenter,         SlotsAttributeDocumenter, DataDeclarationDocumenter,        SingledispatchFunctionDocumenter,     )     documenters = [         ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter,         FunctionDocumenter, MethodDocumenter, AttributeDocumenter,         InstanceAttributeDocumenter, DecoratorDocumenter, PropertyDocumenter,         SlotsAttributeDocumenter, DataDeclarationDocumenter,        SingledispatchFunctionDocumenter,     ]  # type: List[Type[Documenter]]     for documenter in documenters:         app.registry.add_documenter(documenter.objtype, documenter)diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py-- a/sphinx/util/inspect.py++ b/sphinx/util/inspect.py


Question: Support for functions It would be nice if there was some mechanism to automagically pick up the overloads to a function and list them together... e.g.

return False  <ins>def is_singledispatch_function(obj: Any) -> bool:    """Check if the object is singledispatch function."""    if (inspect.isfunction(obj) and            hasattr(obj, 'dispatch') and            hasattr(obj, 'register') and            obj.dispatch.__module__ == 'functools'):        return True    else:        return Falsedef is_singledispatch_method(obj: Any) -> bool:    """Check if the object is singledispatch method."""    try:        from functools import singledispatchmethod  # type: ignore        return isinstance(obj, singledispatchmethod)    except ImportError:  # py35-37        return False</ins> def isfunction(obj: Any) -> bool:     """Check if the object is function."""     return inspect.isfunction(unwrap(obj))


Question: autodoc: Load automatically After typehints enough matured, it should be loaded automatically from autodoc extension. refs:

(inspect.isroutine(member) and isinstance(parent, ModuleDocumenter)))      def format_args(self, **kwargs: Any) -> str:        if self.env.config.autodoc_typehints == 'none':        if self.env.config.autodoc_typehints in ('none', 'description'):             kwargs.setdefault('show_annotation', False)          if inspect.isbuiltin(self.object) or inspect.ismethoddescriptor(self.object):


Question: autodoc: Load automatically After typehints enough matured, it should be loaded automatically from autodoc extension. refs:

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)    app.add_config_value('autodoc_typehints', "signature", True, ENUM("signature", "none"))    app.add_config_value('autodoc_typehints', "signature", True,                         ENUM("signature", "description", "none"))     app.add_config_value('autodoc_warningiserror', True, True)     app.add_config_value('autodoc_inherit_docstrings', True, True)     app.add_event('autodoc-before-process-signature')


Question: autodoc: Load automatically After typehints enough matured, it should be loaded automatically from autodoc extension. refs:

app.add_event('autodoc-skip-member')      app.setup_extension('sphinx.ext.autodoc.type_comment')    app.setup_extension('sphinx.ext.autodoc.typehints')      return {'version': sphinx.__display_version__, 'parallel_read_safe': 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


Question: autodoc: Load automatically After typehints enough matured, it should be loaded automatically from autodoc extension. refs:

from sphinx import addnodes from sphinx.application import Sphinxfrom sphinx.config import Config, ENUM from sphinx.util import inspect, typing  def config_inited(app: Sphinx, config: Config) -> None:    if config.autodoc_typehints == 'description':        # HACK: override this to make autodoc suppressing typehints in signatures        config.autodoc_typehints = 'none'  # type: ignore        # preserve user settings        app._autodoc_typehints_description = True  # type: ignore    else:        app._autodoc_typehints_description = False  # type: ignore def record_typehints(app: Sphinx, objtype: str, name: str, obj: Any,                      options: Dict, args: str, retann: str) -> None:     """Record type hints to env object."""