From 3a240642615ec6c3634541b9b94982221efbbe2d Mon Sep 17 00:00:00 2001 From: onerandomusername Date: Mon, 15 Sep 2025 02:02:25 -0400 Subject: [PATCH 01/15] deps: bump doc dependencies --- .readthedocs.yml | 4 ++-- noxfile.py | 3 ++- pyproject.toml | 24 ++++++++++++++---------- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/.readthedocs.yml b/.readthedocs.yml index aec1ccff3d..be03096e5b 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -6,13 +6,13 @@ formats: build: os: ubuntu-24.04 tools: - python: "3.8" + python: "3.11" jobs: create_environment: - asdf plugin add uv - asdf install uv latest - asdf global uv latest - - UV_PROJECT_ENVIRONMENT=$READTHEDOCS_VIRTUALENV_PATH uv sync --no-default-groups --extra docs + - UV_PROJECT_ENVIRONMENT=$READTHEDOCS_VIRTUALENV_PATH uv sync --no-default-groups --group docs install: - "true" diff --git a/noxfile.py b/noxfile.py index 7dc54e12f7..19c3448787 100755 --- a/noxfile.py +++ b/noxfile.py @@ -88,8 +88,9 @@ def __post_init__(self) -> None: # docs and pyright ExecutionGroup( sessions=("docs", "pyright"), + python="3.11", pyright_paths=("docs",), - extras=("docs",), + groups=("docs",), ), # codemodding and pyright ExecutionGroup( diff --git a/pyproject.toml b/pyproject.toml index dcb3f7b29e..b9b76b888e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -56,16 +56,6 @@ voice = [ "PyNaCl>=1.5.0,<1.6", 'audioop-lts>=0.2.1; python_version >= "3.13"' ] -docs = [ - "sphinx==7.0.1", - "sphinxcontrib-trio~=1.1.2", - "sphinx-hoverxref==1.3.0", - "sphinx-autobuild~=2021.3", - "sphinxcontrib-towncrier==0.3.2a0", - "towncrier==23.6.0", - "sphinx-notfound-page==0.8.3", - "sphinxext-opengraph==0.9.1", -] [dependency-groups] dev = [ @@ -75,6 +65,7 @@ dev = [ { include-group = "typing" }, { include-group = "test" }, { include-group = "build" }, + { include-group = "docs" }, ] nox = [ # note: nox should be synced with nox.needs_version in noxfile.py @@ -93,6 +84,16 @@ tools = [ changelog = [ "towncrier==23.6.0", ] +docs = [ + "sphinx==8.2.3", + "sphinx-autobuild~=2025.8.25", + "sphinx-hoverxref==1.4.2", + "sphinx-notfound-page==1.1.0", + "sphinxcontrib-towncrier==0.5.0a0", + "sphinxcontrib-trio~=1.1.2", + "sphinxext-opengraph==0.9.1", + { include-group = "changelog" } +] codemod = [ # run codemods on the repository (mostly automated typing) "libcst~=1.1.0", @@ -124,6 +125,9 @@ include = ["disnake*"] [tool.uv] required-version = ">=0.8.4" +[tool.uv.dependency-groups] +docs = { requires-python = ">=3.11" } + [tool.ruff] line-length = 100 From 45b21921fc491813efdb356803c45d2a29768044 Mon Sep 17 00:00:00 2001 From: onerandomusername Date: Sat, 20 Sep 2025 17:35:57 -0400 Subject: [PATCH 02/15] fix type error --- docs/extensions/resourcelinks.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/extensions/resourcelinks.py b/docs/extensions/resourcelinks.py index d93f6f2715..994bdf4f55 100644 --- a/docs/extensions/resourcelinks.py +++ b/docs/extensions/resourcelinks.py @@ -4,7 +4,7 @@ # Licensed under BSD. from __future__ import annotations -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple +from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Tuple from docutils import nodes, utils from sphinx.util.nodes import split_explicit_title @@ -26,7 +26,7 @@ def role( lineno: int, inliner: Inliner, options: Optional[Dict[str, Any]] = None, - content: Optional[List[str]] = None, + content: Optional[Sequence[str]] = None, ) -> Tuple[List[Node], List[system_message]]: text = utils.unescape(text) has_explicit_title, title, key = split_explicit_title(text) From f897595b12c6892413169894701e84188bac0e75 Mon Sep 17 00:00:00 2001 From: onerandomusername Date: Sat, 20 Sep 2025 17:36:38 -0400 Subject: [PATCH 03/15] configure ruff for py311 docs --- docs/.ruff.toml | 6 ++++++ docs/conf.py | 4 ++-- docs/extensions/attributetable.py | 20 ++++++++++---------- docs/extensions/collapse.py | 4 ++-- docs/extensions/exception_hierarchy.py | 4 ++-- docs/extensions/fulltoc.py | 4 ++-- docs/extensions/redirects.py | 6 +++--- docs/extensions/resourcelinks.py | 11 ++++++----- 8 files changed, 33 insertions(+), 26 deletions(-) create mode 100644 docs/.ruff.toml diff --git a/docs/.ruff.toml b/docs/.ruff.toml new file mode 100644 index 0000000000..41bf35e5d3 --- /dev/null +++ b/docs/.ruff.toml @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: MIT + +extend = "../pyproject.toml" +src = ["../"] + +target-version = "py311" diff --git a/docs/conf.py b/docs/conf.py index 40b4b3dc7d..6f183fabf2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -18,7 +18,7 @@ import re import subprocess # noqa: TID251 import sys -from typing import Any, Dict, Optional +from typing import Any from sphinx.application import Sphinx @@ -207,7 +207,7 @@ def git(*args: str) -> str: _disnake_module_path = os.path.dirname(_spec.origin) -def linkcode_resolve(domain: str, info: Dict[str, Any]) -> Optional[str]: +def linkcode_resolve(domain: str, info: dict[str, Any]) -> str | None: if domain != "py": return None diff --git a/docs/extensions/attributetable.py b/docs/extensions/attributetable.py index 4589d73e6d..1986c017c6 100644 --- a/docs/extensions/attributetable.py +++ b/docs/extensions/attributetable.py @@ -5,7 +5,7 @@ import inspect import re from collections import defaultdict -from typing import TYPE_CHECKING, ClassVar, DefaultDict, Dict, List, NamedTuple, Optional, Tuple +from typing import TYPE_CHECKING, ClassVar, NamedTuple from docutils import nodes from sphinx import addnodes @@ -103,7 +103,7 @@ class PyAttributeTable(SphinxDirective): final_argument_whitespace = False option_spec: ClassVar[OptionSpec] = {} - def parse_name(self, content: str) -> Tuple[str, Optional[str]]: + def parse_name(self, content: str) -> tuple[str, str | None]: match = _name_parser_regex.match(content) path, name = match.groups() if match else (None, None) if path: @@ -117,7 +117,7 @@ def parse_name(self, content: str) -> Tuple[str, Optional[str]]: return modulename, name - def run(self) -> List[nodes.Node]: + def run(self) -> list[nodes.Node]: """If you're curious on the HTML this is meant to generate:
@@ -154,10 +154,10 @@ def run(self) -> List[nodes.Node]: return [node] -def build_lookup_table(env: BuildEnvironment) -> Dict[str, List[str]]: +def build_lookup_table(env: BuildEnvironment) -> dict[str, list[str]]: # Given an environment, load up a lookup table of # full-class-name: objects - result: DefaultDict[str, List[str]] = defaultdict(list) + result: defaultdict[str, list[str]] = defaultdict(list) domain = env.domains["py"] ignored = { @@ -180,7 +180,7 @@ def build_lookup_table(env: BuildEnvironment) -> Dict[str, List[str]]: class TableElement(NamedTuple): fullname: str label: str - badge: Optional[attributetablebadge] + badge: attributetablebadge | None def process_attributetable(app: Sphinx, doctree: nodes.document, docname: str) -> None: @@ -209,12 +209,12 @@ def process_attributetable(app: Sphinx, doctree: nodes.document, docname: str) - def get_class_results( - lookup: Dict[str, List[str]], modulename: str, name: str, fullname: str -) -> Dict[str, List[TableElement]]: + lookup: dict[str, list[str]], modulename: str, name: str, fullname: str +) -> dict[str, list[TableElement]]: module = importlib.import_module(modulename) cls = getattr(module, name) - groups: Dict[str, List[TableElement]] = { + groups: dict[str, list[TableElement]] = { _("Attributes"): [], _("Methods"): [], } @@ -263,7 +263,7 @@ def get_class_results( return groups -def class_results_to_node(key: str, elements: List[TableElement]) -> attributetablecolumn: +def class_results_to_node(key: str, elements: list[TableElement]) -> attributetablecolumn: title = attributetabletitle(key, key) ul = nodes.bullet_list("") ul["classes"].append("py-attribute-table-list") diff --git a/docs/extensions/collapse.py b/docs/extensions/collapse.py index a37bdd3780..037d0b7e2b 100644 --- a/docs/extensions/collapse.py +++ b/docs/extensions/collapse.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT from __future__ import annotations -from typing import TYPE_CHECKING, ClassVar, List +from typing import TYPE_CHECKING, ClassVar from docutils import nodes from docutils.parsers.rst import Directive, directives @@ -36,7 +36,7 @@ class CollapseDirective(Directive): option_spec: ClassVar[OptionSpec] = {"open": directives.flag} - def run(self) -> List[collapse]: + def run(self) -> list[collapse]: self.assert_has_content() node = collapse( "\n".join(self.content), diff --git a/docs/extensions/exception_hierarchy.py b/docs/extensions/exception_hierarchy.py index 49ed16f539..586059e9be 100644 --- a/docs/extensions/exception_hierarchy.py +++ b/docs/extensions/exception_hierarchy.py @@ -1,7 +1,7 @@ # SPDX-License-Identifier: MIT from __future__ import annotations -from typing import TYPE_CHECKING, List +from typing import TYPE_CHECKING from docutils import nodes from docutils.parsers.rst import Directive @@ -28,7 +28,7 @@ def depart_exception_hierarchy_node(self: HTMLTranslator, node: nodes.Element) - class ExceptionHierarchyDirective(Directive): has_content = True - def run(self) -> List[exception_hierarchy]: + def run(self) -> list[exception_hierarchy]: self.assert_has_content() node = exception_hierarchy("\n".join(self.content)) self.state.nested_parse(self.content, self.content_offset, node) diff --git a/docs/extensions/fulltoc.py b/docs/extensions/fulltoc.py index d5d4f62ba8..b11aa3a50f 100644 --- a/docs/extensions/fulltoc.py +++ b/docs/extensions/fulltoc.py @@ -29,7 +29,7 @@ from __future__ import annotations -from typing import TYPE_CHECKING, List, cast +from typing import TYPE_CHECKING, cast from docutils import nodes from sphinx import addnodes @@ -112,7 +112,7 @@ def build_full_toctree( """ env: BuildEnvironment = builder.env doctree = env.get_doctree(index) - toctrees: List[nodes.Element] = [] + toctrees: list[nodes.Element] = [] for toctreenode in doctree.traverse(addnodes.toctree): toctree = env.resolve_toctree( docname, diff --git a/docs/extensions/redirects.py b/docs/extensions/redirects.py index 46114dd743..b008b25db2 100644 --- a/docs/extensions/redirects.py +++ b/docs/extensions/redirects.py @@ -3,7 +3,7 @@ import json from pathlib import Path -from typing import TYPE_CHECKING, Dict +from typing import TYPE_CHECKING from sphinx.application import Sphinx from sphinx.util.fileutil import copy_asset_file @@ -14,10 +14,10 @@ SCRIPT_PATH = "_templates/api_redirect.js_t" -def collect_redirects(app: Sphinx) -> Dict[str, str]: +def collect_redirects(app: Sphinx) -> dict[str, str]: # mapping of html node id (i.e., thing after "#" in URLs) to the correct page name # e.g, api.html#disnake.Thread => api/channels.html - mapping: Dict[str, str] = {} + mapping: dict[str, str] = {} # see https://www.sphinx-doc.org/en/master/extdev/domainapi.html#sphinx.domains.Domain.get_objects domain = app.env.domains["py"] diff --git a/docs/extensions/resourcelinks.py b/docs/extensions/resourcelinks.py index 994bdf4f55..4acfba3a29 100644 --- a/docs/extensions/resourcelinks.py +++ b/docs/extensions/resourcelinks.py @@ -4,7 +4,8 @@ # Licensed under BSD. from __future__ import annotations -from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Tuple +from collections.abc import Sequence +from typing import TYPE_CHECKING, Any from docutils import nodes, utils from sphinx.util.nodes import split_explicit_title @@ -18,16 +19,16 @@ from ._types import SphinxExtensionMeta -def make_link_role(resource_links: Dict[str, str]) -> RoleFunction: +def make_link_role(resource_links: dict[str, str]) -> RoleFunction: def role( typ: str, rawtext: str, text: str, lineno: int, inliner: Inliner, - options: Optional[Dict[str, Any]] = None, - content: Optional[Sequence[str]] = None, - ) -> Tuple[List[Node], List[system_message]]: + options: dict[str, Any] | None = None, + content: Sequence[str] | None = None, + ) -> tuple[list[Node], list[system_message]]: text = utils.unescape(text) has_explicit_title, title, key = split_explicit_title(text) full_url = resource_links[key] From a58731d23bca7ab8c97179552ef6f096c03fcdd6 Mon Sep 17 00:00:00 2001 From: arielle Date: Sun, 28 Sep 2025 13:54:31 -0400 Subject: [PATCH 04/15] deps: bump sphinxext-opengraph --- docs/extensions/builder.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/extensions/builder.py b/docs/extensions/builder.py index 6eee763436..7aa4bf03eb 100644 --- a/docs/extensions/builder.py +++ b/docs/extensions/builder.py @@ -7,7 +7,7 @@ from docutils import nodes from sphinx.environment.adapters.indexentries import IndexEntries -from sphinxext.opengraph.descriptionparser import DescriptionParser +from sphinxext.opengraph._description_parser import DescriptionParser if TYPE_CHECKING: from sphinx.application import Sphinx diff --git a/pyproject.toml b/pyproject.toml index 424282dbfe..abf8fde88d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -90,7 +90,7 @@ docs = [ "sphinx-notfound-page==1.1.0", "sphinxcontrib-towncrier==0.5.0a0", "sphinxcontrib-trio~=1.1.2", - "sphinxext-opengraph==0.9.1", + "sphinxext-opengraph==0.13.0", { include-group = "changelog" } ] codemod = [ From 823df050422e1f223ad021dda319a8ff150e5bf2 Mon Sep 17 00:00:00 2001 From: arielle Date: Sun, 28 Sep 2025 13:56:07 -0400 Subject: [PATCH 05/15] fix: don't install all dependencies with the dev action --- noxfile.py | 2 +- pyproject.toml | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/noxfile.py b/noxfile.py index b50a073173..f8f9ca7a68 100755 --- a/noxfile.py +++ b/noxfile.py @@ -475,7 +475,7 @@ def dev(session: nox.Session) -> None: """ session.run("uv", "lock", external=True) session.run("uv", "venv", "--clear", external=True) - session.run("uv", "sync", "--all-extras", "--all-groups", external=True) + session.run("uv", "sync", "--all-extras", external=True) session.run("uv", "run", "prek", "install", "--overwrite", external=True) diff --git a/pyproject.toml b/pyproject.toml index abf8fde88d..fa639f1afe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -64,7 +64,6 @@ dev = [ { include-group = "typing" }, { include-group = "test" }, { include-group = "build" }, - { include-group = "docs" }, ] nox = [ # note: nox should be synced with nox.needs_version in noxfile.py From 80e3281d41279ed2af1ccd50a9579dabb4bd42a4 Mon Sep 17 00:00:00 2001 From: arielle Date: Sun, 28 Sep 2025 13:56:35 -0400 Subject: [PATCH 06/15] bump towncrier --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index fa639f1afe..5a1c40d033 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -80,7 +80,7 @@ tools = [ { include-group = "ruff" }, ] changelog = [ - "towncrier==23.6.0", + "towncrier==25.8.0", ] docs = [ "sphinx==8.2.3", From 0f066532884752141a6eb30b8e611b0510f28bd7 Mon Sep 17 00:00:00 2001 From: arielle Date: Sun, 28 Sep 2025 14:16:26 -0400 Subject: [PATCH 07/15] apply suggestions --- docs/conf.py | 12 +++++++++++- docs/extensions/redirects.py | 3 ++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index a60d865d1d..1929505550 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -18,8 +18,10 @@ import re import subprocess # noqa: TID251 import sys +import warnings from typing import Any +import sphinx.deprecation from sphinx.application import Sphinx # If extensions (or modules to document with autodoc) are in another directory, @@ -28,6 +30,12 @@ sys.path.insert(0, os.path.abspath("..")) sys.path.append(os.path.abspath("extensions")) +warnings.filterwarnings( + "ignore", + category=sphinx.deprecation.RemovedInSphinx90Warning, + module="hoverxref.extension", +) + # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. @@ -90,7 +98,9 @@ templates_path = ["_templates"] # The suffix of source filenames. -source_suffix = ".rst" +source_suffix = { + ".rst": "restructuredtext", +} # The encoding of source files. # source_encoding = 'utf-8-sig' diff --git a/docs/extensions/redirects.py b/docs/extensions/redirects.py index b008b25db2..1a857160bd 100644 --- a/docs/extensions/redirects.py +++ b/docs/extensions/redirects.py @@ -27,7 +27,7 @@ def collect_redirects(app: Sphinx) -> dict[str, str]: return mapping -def copy_redirect_script(app: Sphinx, exception: Exception) -> None: +def copy_redirect_script(app: Sphinx, exception: Exception | None) -> None: if app.builder.format != "html" or exception: return @@ -41,6 +41,7 @@ def copy_redirect_script(app: Sphinx, exception: Exception) -> None: SCRIPT_PATH, str(Path(app.outdir, "_static", "api_redirect.js")), context=context, + force=True, ) From 0b745279061069e3abe006bc6aa0bb722ec1d71f Mon Sep 17 00:00:00 2001 From: shiftinv Date: Sun, 28 Sep 2025 22:19:44 +0200 Subject: [PATCH 08/15] fix: replace obsolete `URL_ROOT` with html data field for search --- docs/_templates/api_redirect.js_t | 4 ++-- docs/_templates/layout.html | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/_templates/api_redirect.js_t b/docs/_templates/api_redirect.js_t index ee4b68b64e..a07980dbc1 100644 --- a/docs/_templates/api_redirect.js_t +++ b/docs/_templates/api_redirect.js_t @@ -9,8 +9,8 @@ const redirects_map = {{ redirect_data }}; if (!url.pathname.endsWith("/api.html")) return; - // URL_ROOT is relative to `url`, and points to e.g. `/en/latest/` - const root = new URL(DOCUMENTATION_OPTIONS.URL_ROOT, url); + // content_root is relative to `url`, and points to e.g. `/en/latest/` + const root = new URL(document.documentElement.dataset.content_root, url); if (!root.pathname.endsWith("/")) root.pathname += "/"; const targetPath = redirects_map[url.hash.slice(1)]; diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html index 47bd68988d..cc349ab3d5 100644 --- a/docs/_templates/layout.html +++ b/docs/_templates/layout.html @@ -1,7 +1,7 @@ - + From 855988d16b4e986a1ee9492de8b432c5b188955b Mon Sep 17 00:00:00 2001 From: shiftinv Date: Tue, 30 Sep 2025 15:16:27 +0200 Subject: [PATCH 09/15] fix: override/reset :visited highlight --- docs/_static/style.css | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/_static/style.css b/docs/_static/style.css index fb9bece8b5..1ce8443812 100644 --- a/docs/_static/style.css +++ b/docs/_static/style.css @@ -200,13 +200,14 @@ body { } /* all URLs only show underline on hover */ -a { +/* (also overrides sphinx's :visited highlight) */ +a, a:visited { text-decoration: none; color: var(--link-text); transition: color 0.3s; } -a:hover { +a:hover, a:hover:visited { text-decoration: underline; color: var(--link-hover-text); transition: color 0.05s; @@ -236,12 +237,12 @@ header > nav { line-height: 1em; /* It defaults to 1.2, pushing some icons out of vertical alignment */ } -header > nav a { +header > nav a, header > nav a:visited { color: var(--nav-link-text); margin: 0 0.5em; } -header > nav a:hover { +header > nav a:hover, header > nav a:hover:visited { color: var(--nav-link-hover-text); text-decoration: none; } @@ -286,7 +287,7 @@ footer { z-index: 5; } -footer a { +footer a, footer a:visited { text-decoration: underline; color: var(--footer-link); } From 07defce9983d4dae5e5cbdb6462a05cdd90ac9b8 Mon Sep 17 00:00:00 2001 From: shiftinv Date: Tue, 30 Sep 2025 15:21:21 +0200 Subject: [PATCH 10/15] fix: remove duplicate `documentation_options.js` script see https://github.com/sphinx-doc/sphinx/commit/ee5560b7739932d0a7735be0cc81f28d76a61e92 --- docs/_templates/layout.html | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/_templates/layout.html b/docs/_templates/layout.html index cc349ab3d5..3e1c767ac6 100644 --- a/docs/_templates/layout.html +++ b/docs/_templates/layout.html @@ -21,7 +21,6 @@ {%- block scripts %} - {% if ("/" + pagename).endswith("/api") %} From 82f2d2548e6269e35821a2fcc88cbc5311d3d0d9 Mon Sep 17 00:00:00 2001 From: shiftinv Date: Tue, 30 Sep 2025 15:35:43 +0200 Subject: [PATCH 11/15] chore: rename `.js_t` to `.js.jinja` https://www.sphinx-doc.org/en/master/development/html_themes/index.html#static-templates --- docs/_templates/{api_redirect.js_t => api_redirect.js.jinja} | 0 docs/extensions/redirects.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename docs/_templates/{api_redirect.js_t => api_redirect.js.jinja} (100%) diff --git a/docs/_templates/api_redirect.js_t b/docs/_templates/api_redirect.js.jinja similarity index 100% rename from docs/_templates/api_redirect.js_t rename to docs/_templates/api_redirect.js.jinja diff --git a/docs/extensions/redirects.py b/docs/extensions/redirects.py index 1a857160bd..631e5796ea 100644 --- a/docs/extensions/redirects.py +++ b/docs/extensions/redirects.py @@ -11,7 +11,7 @@ if TYPE_CHECKING: from ._types import SphinxExtensionMeta -SCRIPT_PATH = "_templates/api_redirect.js_t" +SCRIPT_PATH = "_templates/api_redirect.js.jinja" def collect_redirects(app: Sphinx) -> dict[str, str]: From f568b9c6be8db65b32b32748e5455eab50b777ef Mon Sep 17 00:00:00 2001 From: shiftinv Date: Tue, 30 Sep 2025 15:59:10 +0200 Subject: [PATCH 12/15] fix: suppress two verbose/unimportant sphinx logs --- docs/conf.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 1929505550..e1290fb679 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -14,6 +14,7 @@ import importlib.util import inspect +import logging import os import re import subprocess # noqa: TID251 @@ -30,12 +31,6 @@ sys.path.insert(0, os.path.abspath("..")) sys.path.append(os.path.abspath("extensions")) -warnings.filterwarnings( - "ignore", - category=sphinx.deprecation.RemovedInSphinx90Warning, - module="hoverxref.extension", -) - # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. @@ -516,3 +511,19 @@ def setup(app: Sphinx) -> None: import disnake del disnake.Embed.Empty # type: ignore + + warnings.filterwarnings( + "ignore", + category=sphinx.deprecation.RemovedInSphinx90Warning, + module="hoverxref.extension", + ) + + # silence somewhat verbose `Writing evaluated template result to ...` log + logging.getLogger("sphinx.sphinx.util.fileutil").addFilter( + lambda r: getattr(r, "subtype", None) != "template_evaluation" + ) + + # `document is referenced in multiple toctrees:` is fine and expected + logging.getLogger("sphinx.sphinx.environment").addFilter( + lambda r: getattr(r, "subtype", None) != "multiple_toc_parents" + ) From cc80518b8318c4a9b615778409af59f0226ad8c9 Mon Sep 17 00:00:00 2001 From: shiftinv Date: Tue, 30 Sep 2025 16:30:28 +0200 Subject: [PATCH 13/15] fix: ignore `__pycache__` when autobuilding, to avoid building twice --- noxfile.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/noxfile.py b/noxfile.py index f8f9ca7a68..8fa587d574 100755 --- a/noxfile.py +++ b/noxfile.py @@ -230,6 +230,8 @@ def docs(session: nox.Session) -> None: "sphinx-autobuild", "--ignore", "_build", + "--re-ignore", + "__pycache__", "--watch", "../disnake", "--watch", From b5e04966d2fbb1392441339cf94386a671f12d35 Mon Sep 17 00:00:00 2001 From: shiftinv Date: Wed, 1 Oct 2025 11:21:13 +0200 Subject: [PATCH 14/15] fix: base custom search scorer on base title score this is by no means perfect; long story short, sphinx changed the search scorer algorithm to actually take the configured `title` score (15) into account for matching titles, instead of a fixed 100. This, in turn, meant that any and all page matches would now be ranked at the bottom, since the custom search scorer inflates the score of all `disnake.*` objects to a score right below 100. To resolve this, the scorer now assigns these API results a score of 14-15, i.e. right below pages with matching titles again. API results with a longer or later submatch continue to receive a higher score penalty, and are therefore closer to 14 rather than 15. --- docs/_static/scorer.js | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/docs/_static/scorer.js b/docs/_static/scorer.js index f3bc8ce584..a674278215 100644 --- a/docs/_static/scorer.js +++ b/docs/_static/scorer.js @@ -17,6 +17,7 @@ function __score(haystack, regex) { } let subLength = match[0].length; let start = match.index; + // longer (and later) submatches get a higher score penalty return (subLength * 1000 + start) / 1000.0; } @@ -38,23 +39,29 @@ function __setPattern() { Scorer = { // Implement the following function to further tweak the score for each result - // The function takes a result array [filename, title, anchor, descr, score] + // The function takes a result array [docname, title, anchor, descr, score, filename, kind] // and returns the new score. score: (result) => { - // only inflate the score of things that are actual API reference things - const [, title, , , score,] = result; + const [, title, , , score, , kind] = result; if (queryBeingDone === undefined) { __setPattern(); } + // penalize text matches a little bit, sphinx scores pages that have a matching subtitle + // the same as pages that actually have the search term as the title, for some reason + if (kind === "text") return score - 1; + + // only inflate the score of things that are actual API reference things if (pattern !== null && title.startsWith('disnake.')) { - let _score = __score(title, pattern); - if (_score === Number.MAX_VALUE) { + const penalty = __score(title, pattern); + if (penalty === Number.MAX_VALUE) { return score; } - let newScore = 100 + queryBeingDone.length - _score; - // console.log(`${title}: ${score} -> ${newScore} (${_score})`); + // calculate new score on top of title score; we want to rank *all* API results + // right below matching pages, and have pages with only a fulltext match appear last + const newScore = Scorer.title - (penalty / 1000); + console.log(`${title}: ${score} -> ${newScore} (${penalty})`); return newScore; } return score; From 8913dc1e87c56143980b7733105c91b12ffec4af Mon Sep 17 00:00:00 2001 From: shiftinv Date: Wed, 1 Oct 2025 11:54:53 +0200 Subject: [PATCH 15/15] chore: comment debug console.log again --- docs/_static/scorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_static/scorer.js b/docs/_static/scorer.js index a674278215..51647bfea2 100644 --- a/docs/_static/scorer.js +++ b/docs/_static/scorer.js @@ -61,7 +61,7 @@ Scorer = { // calculate new score on top of title score; we want to rank *all* API results // right below matching pages, and have pages with only a fulltext match appear last const newScore = Scorer.title - (penalty / 1000); - console.log(`${title}: ${score} -> ${newScore} (${penalty})`); + // console.log(`${title}: ${score} -> ${newScore} (${penalty})`); return newScore; } return score;