From e47e5a6e5c900e5dca8a655ceee1d42a75aa3dc9 Mon Sep 17 00:00:00 2001
From: Jack DeVries <jdevries3133@gmail.com>
Date: Mon, 2 May 2022 17:58:35 -0400
Subject: [PATCH 001/175] create Makefile for faster iteration

* makefile can automatically build the package, then navigate to the
  cpython repository to install the package and/or rebuild documentation
---
 CONTRIBUTING.rst |  9 +++++++++
 Makefile         | 21 +++++++++++++++++++++
 2 files changed, 30 insertions(+)
 create mode 100644 Makefile

diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 8f5edaa..65d06ce 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -13,3 +13,12 @@
 - bump version (YYYY.MM.dev) in setup.py and python_docs_theme/theme.conf
 - Commit this last bump.
 - push and push the tag (``git push && git push --tags``)
+
+# Makefile Usage
+
+This project includes a simple Makefile for syncing changes to the theme with
+the main cpython repository. Run ``make help`` for details on available rules.
+
+There is one configurable variable, ``CPYTHON_ROOT``, which should be the path
+to the cpython repository on your machine. By default, it points to
+``../cpython``.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..a14ff16
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,21 @@
+CPYTHON_ROOT               = ../cpython
+PACKAGE_ABS_PATH = $(shell pwd)/$(shell find dist/python-docs-theme-*.tar.gz)
+
+
+.PHONY: all
+all: install
+	cd $(CPYTHON_ROOT)/Doc && \
+		make html
+
+
+.PHONY: install
+install:
+	python3 -m build
+	cd $(CPYTHON_ROOT)/Doc && \
+		./venv/bin/pip install $(PACKAGE_ABS_PATH)
+
+.PHONY: help
+help:
+	@echo "all: run the \`\`\install\`\\ rule, and also rebuild the cpython docs"
+	@echo "install: build the package, and install it in the virtual environment"
+	@echo "         at $(CPYTHON_ROOT)/Doc/venv"

From da9de512b66931fed1e114714cd3a9b2349af5b1 Mon Sep 17 00:00:00 2001
From: Jack DeVries <jdevries3133@gmail.com>
Date: Mon, 2 May 2022 19:57:35 -0400
Subject: [PATCH 002/175] rename `CPYTHON_ROOT` -> `CPYTHON_PATH`

---
 CONTRIBUTING.rst | 2 +-
 Makefile         | 8 ++++----
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 65d06ce..38807d1 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -19,6 +19,6 @@
 This project includes a simple Makefile for syncing changes to the theme with
 the main cpython repository. Run ``make help`` for details on available rules.
 
-There is one configurable variable, ``CPYTHON_ROOT``, which should be the path
+There is one configurable variable, ``CPYTHON_PATH``, which should be the path
 to the cpython repository on your machine. By default, it points to
 ``../cpython``.
diff --git a/Makefile b/Makefile
index a14ff16..c5e9702 100644
--- a/Makefile
+++ b/Makefile
@@ -1,21 +1,21 @@
-CPYTHON_ROOT               = ../cpython
+CPYTHON_PATH               = ../cpython
 PACKAGE_ABS_PATH = $(shell pwd)/$(shell find dist/python-docs-theme-*.tar.gz)
 
 
 .PHONY: all
 all: install
-	cd $(CPYTHON_ROOT)/Doc && \
+	cd $(CPYTHON_PATH)/Doc && \
 		make html
 
 
 .PHONY: install
 install:
 	python3 -m build
-	cd $(CPYTHON_ROOT)/Doc && \
+	cd $(CPYTHON_PATH)/Doc && \
 		./venv/bin/pip install $(PACKAGE_ABS_PATH)
 
 .PHONY: help
 help:
 	@echo "all: run the \`\`\install\`\\ rule, and also rebuild the cpython docs"
 	@echo "install: build the package, and install it in the virtual environment"
-	@echo "         at $(CPYTHON_ROOT)/Doc/venv"
+	@echo "         at $(CPYTHON_PATH)/Doc/venv"

From fb7f510c09831d8a61b775ce5b648c426839ba22 Mon Sep 17 00:00:00 2001
From: Jack DeVries <jdevries3133@gmail.com>
Date: Mon, 2 May 2022 20:03:05 -0400
Subject: [PATCH 003/175] revise help text

---
 Makefile | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile
index c5e9702..a7cf07a 100644
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,6 @@ install:
 
 .PHONY: help
 help:
-	@echo "all: run the \`\`\install\`\\ rule, and also rebuild the cpython docs"
-	@echo "install: build the package, and install it in the virtual environment"
-	@echo "         at $(CPYTHON_PATH)/Doc/venv"
+	@echo "all:		default rule; run the \`install\` rule, and also rebuild the cpython docs"
+	@echo "install: 	build the package, and install it into the virtual environment"
+	@echo "		at $(CPYTHON_PATH)/Doc/venv"

From 57affc06f05b9e14a2da3f11fef2edd69faac200 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Fri, 11 Nov 2022 14:48:09 +0000
Subject: [PATCH 004/175] Update test workflow

---
 .github/workflows/tests.yml | 38 ++++++++++++++++++++-----------------
 1 file changed, 21 insertions(+), 17 deletions(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 824bb0c..6d985ba 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -1,35 +1,39 @@
----
-
 name: Tests
 
 on:
   push:
-    branches:
-      - master
   pull_request:
-    branches:
-      - master
+  workflow_dispatch:
 
 jobs:
   build_doc:
-    name: 'Build cpython doc'
+    name: Build CPython documentation
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v2
-      - uses: actions/setup-python@v2
+      - uses: actions/checkout@v3
+      - uses: actions/setup-python@v4
         with:
-          python-version: 3.8
-      - name: clone docsbuild scripts
+          python-version: 3
+      - name: Clone docsbuild scripts
         run: |
           git clone https://github.com/python/docsbuild-scripts/
-      - name: setup requirements
+      - name: Setup requirements
         run: |
           python -m pip install --upgrade pip
-          python -m pip install jinja2 markupsafe zc.lockfile
-      - name: build docs
-        run: |
-          python3 ./docsbuild-scripts/build_docs.py --quick --build-root ./build_root --www-root ./www --log-directory ./logs --group $(id -g) --skip-cache-invalidation --theme $(pwd) --language en --branch 3.9
-      - name: 'Upload'
+          python -m pip install -r docsbuild-scripts/requirements.txt
+      - name: Build documentation
+        run: >
+          python ./docsbuild-scripts/build_docs.py 
+          --quick 
+          --build-root ./build_root 
+          --www-root ./www 
+          --log-directory ./logs 
+          --group $(id -g) 
+          --skip-cache-invalidation 
+          --theme $(pwd) 
+          --language en 
+          --branch 3.11
+      - name: Upload
         uses: actions/upload-artifact@v2.2.2
         with:
           name: doc-html

From 0f704cf475f652b2dd879e4d867050ee82661790 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sun, 16 Oct 2022 17:20:20 +0100
Subject: [PATCH 005/175] Use pyproject

---
 MANIFEST.in    |  2 --
 pyproject.toml | 48 ++++++++++++++++++++++++++++++++++++++++++++----
 setup.cfg      |  2 --
 setup.py       | 38 --------------------------------------
 4 files changed, 44 insertions(+), 46 deletions(-)
 delete mode 100644 MANIFEST.in
 delete mode 100644 setup.cfg
 delete mode 100644 setup.py

diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index 3ae74ec..0000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,2 +0,0 @@
-include LICENSE README.rst
-recursive-include python_docs_theme *.*
diff --git a/pyproject.toml b/pyproject.toml
index de11f32..f215cae 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,7 +1,47 @@
 [build-system]
-requires = [
-    "setuptools>=42",
-    "wheel"
+requires = ["flit_core>=3.7"]
+build-backend = "flit_core.buildapi"
+
+# project metadata
+[project]
+name = "python-docs-theme"
+version = "2022.1"
+description = "The Sphinx theme for the CPython docs and related projects"
+readme = "README.rst"
+urls.Code = "https://github.com/python/python-docs-theme"
+urls.Download = "https://pypi.org/project/python-docs-theme/"
+urls.Homepage = "https://github.com/python/python-docs-theme/"
+urls."Issue tracker" = "https://github.com/python/python-docs-theme/issues"
+license.text = "PSF-2.0"
+requires-python = ">=3.8"
+
+# Classifiers list: https://pypi.org/classifiers/
+classifiers = [
+    "Development Status :: 5 - Production/Stable",
+    "Intended Audience :: Developers",
+    "License :: OSI Approved :: Python Software Foundation License",
+    "Operating System :: OS Independent",
+    "Topic :: Documentation",
+    "Topic :: Software Development :: Documentation",
+    "Programming Language :: Python",
+    "Programming Language :: Python :: 3",
+    "Programming Language :: Python :: 3.8",
+    "Programming Language :: Python :: 3.9",
+    "Programming Language :: Python :: 3.10",
+    "Programming Language :: Python :: 3.11",
 ]
-build-backend = "setuptools.build_meta"
 
+[[project.authors]]
+name = "PyPA"
+email = "distutils-sig@python.org"
+
+[project.entry-points."sphinx.html_themes"]
+python_docs_theme = 'python_docs_theme'
+
+[tool.flit.module]
+name = "python_docs_theme"
+
+[tool.flit.sdist]
+include = [
+    "python_docs_theme/",
+]
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 2a9acf1..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,2 +0,0 @@
-[bdist_wheel]
-universal = 1
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 578cf1c..0000000
--- a/setup.py
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/usr/bin/env python
-
-import io
-
-from setuptools import setup
-
-# README into long description
-with io.open("README.rst", encoding="utf-8") as readme_file:
-    long_description = readme_file.read()
-
-
-setup(
-    name="python-docs-theme",
-    # Version is date based as year.month[.serial], where serial is used
-    # if multiple releases are needed to address build failures.
-    version="2022.1",
-    description="The Sphinx theme for the CPython docs and related projects",
-    long_description=long_description,
-    author="PyPA",
-    author_email="distutils-sig@python.org",
-    url="https://github.com/python/python-docs-theme/",
-    packages=["python_docs_theme"],
-    include_package_data=True,
-    entry_points={
-        "sphinx.html_themes": [
-            "python_docs_theme = python_docs_theme",
-        ]
-    },
-    classifiers=[
-        "Intended Audience :: Developers",
-        "License :: OSI Approved :: Python Software Foundation License",
-        "Operating System :: OS Independent",
-        "Topic :: Documentation",
-        "Topic :: Software Development :: Documentation",
-        "Programming Language :: Python",
-        "Programming Language :: Python :: 3",
-    ],
-)

From eb7834828e877df791f94cddab7700727107b582 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Fri, 11 Nov 2022 15:20:27 +0000
Subject: [PATCH 006/175] Add Framework :: Sphinx :: Theme

---
 pyproject.toml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/pyproject.toml b/pyproject.toml
index f215cae..3d4c8b2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -18,6 +18,7 @@ requires-python = ">=3.8"
 # Classifiers list: https://pypi.org/classifiers/
 classifiers = [
     "Development Status :: 5 - Production/Stable",
+    "Framework :: Sphinx :: Theme",
     "Intended Audience :: Developers",
     "License :: OSI Approved :: Python Software Foundation License",
     "Operating System :: OS Independent",

From b08ad169baed8152cffcb57d96c72291ec973cca Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Sun, 13 Nov 2022 18:21:51 +0000
Subject: [PATCH 007/175] Notes from Hugo

---
 .github/workflows/tests.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 6d985ba..6ae5953 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -17,7 +17,7 @@ jobs:
       - name: Clone docsbuild scripts
         run: |
           git clone https://github.com/python/docsbuild-scripts/
-      - name: Setup requirements
+      - name: Set up requirements
         run: |
           python -m pip install --upgrade pip
           python -m pip install -r docsbuild-scripts/requirements.txt
@@ -34,7 +34,7 @@ jobs:
           --language en 
           --branch 3.11
       - name: Upload
-        uses: actions/upload-artifact@v2.2.2
+        uses: actions/upload-artifact@v3
         with:
           name: doc-html
           path: www/

From b888ef79dc967ab7afa56efd7dd87820fecbc00c Mon Sep 17 00:00:00 2001
From: Septatrix <24257556+Septatrix@users.noreply.github.com>
Date: Mon, 10 May 2021 12:19:39 +0200
Subject: [PATCH 008/175] Add preliminary dark theme implementation

---
 python_docs_theme/layout.html                |  11 ++
 python_docs_theme/static/pydoctheme.css      |  93 +++++++++++----
 python_docs_theme/static/pydoctheme_dark.css | 119 +++++++++++++++++++
 python_docs_theme/static/themetoggle.js      |  39 ++++++
 python_docs_theme/theme.conf                 |   1 +
 5 files changed, 237 insertions(+), 26 deletions(-)
 create mode 100644 python_docs_theme/static/pydoctheme_dark.css
 create mode 100644 python_docs_theme/static/themetoggle.js

diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index a9a0e6f..abf3664 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -59,13 +59,24 @@ <h3>{{ _('Navigation') }}</h3>
 {% block relbar1 %} {% if builder != 'qthelp' %} {{ relbar() }} {% endif %} {% endblock %}
 {% block relbar2 %} {% if builder != 'qthelp' %} {{ relbar() }} {% endif %} {% endblock %}
 
+{% block relbaritems %}
+{%- if pagename != "search" and builder != "singlehtml" and builder != "htmlhelp" %}
+<li class="right">
+    {{ searchbox() }}
+    {{ reldelim2 }}
+</li>
+{%- endif %}
+<li class="right"><input type="button" value="Toggle theme" class="theme-toggle" onclick="toggleTheme()">{{ reldelim2 }}</li>
+{% endblock %}
 
 {%- block extrahead -%}
+    <link rel="stylesheet" href="{{ pathto('_static/pydoctheme_dark.css', 1) }}" media="(prefers-color-scheme: dark)" id="pydoctheme_dark_css">
     <link rel="shortcut icon" type="image/png" href="{{ pathto('_static/' + theme_root_icon, 1) }}" />
     {%- if builder != "htmlhelp" %}
         {%- if not embedded %}
             <script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>
             <script type="text/javascript" src="{{ pathto('_static/menu.js', 1) }}"></script>
+            <script type="text/javascript" src="{{ pathto('_static/themetoggle.js', 1) }}"></script>
         {%- endif -%}
     {%- endif -%}
     {{ super() }}
diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 151f06e..21be22c 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -1,7 +1,29 @@
-@import url("default.css");
+@import url('classic.css');
+
+/* unset some styles from the classic stylesheet */
+div.document,
+div.body,
+div.related,
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6,
+div.sphinxsidebar a,
+div.sphinxsidebar p,
+div.sphinxsidebar ul,
+div.sphinxsidebar h3,
+div.sphinxsidebar h3 a,
+div.sphinxsidebar h4,
+table.docutils td,
+table.indextable tr.cap,
+pre {
+    background-color: inherit;
+    color: inherit;
+}
 
 body {
-    background-color: white;
     margin-left: 1em;
     margin-right: 1em;
 }
@@ -14,12 +36,12 @@ body {
 div.related {
     margin-bottom: 1.2em;
     padding: 0.5em 0;
-    border-bottom: 1px solid #ccc;
+    border-top: 1px solid #ccc;
     margin-top: 0.5em;
 }
 
 div.related a:hover {
-    color: #0095C4;
+    color: #0095c4;
 }
 
 div.related ~ div.related {
@@ -27,6 +49,11 @@ div.related ~ div.related {
     border-bottom: none;
 }
 
+div.related:first-child {
+    border-top: 0;
+    border-bottom: 1px solid #ccc;
+}
+
 .related .switchers {
     display: inline-flex;
 }
@@ -41,13 +68,19 @@ div.related ~ div.related {
     background-color: white;
 }
 
-.inline-search {
-    display: inline;
+
+div.related ul::after {
+    content: '';
+    clear: both;
+    display: block;
 }
+
+.inline-search,
 form.inline-search input {
     display: inline;
 }
-form.inline-search input[type="submit"] {
+
+form.inline-search input[type='submit'] {
     width: 40px;
 }
 
@@ -60,13 +93,15 @@ div.sphinxsidebar {
     position: sticky;
     top: 0;
     max-height: 100vh;
-    background-color: #eeeeee;
+    color: #444;
+    background-color: #eee;
     border-radius: 5px;
     line-height: 130%;
     font-size: smaller;
 }
 
-div.sphinxsidebar h3, div.sphinxsidebar h4 {
+div.sphinxsidebar h3,
+div.sphinxsidebar h4 {
     margin-top: 1.5em;
 }
 
@@ -86,18 +121,19 @@ div.sphinxsidebarwrapper > ul > li > ul > li {
 }
 
 div.sphinxsidebar a:hover {
-    color: #0095C4;
+    color: #0095c4;
 }
 
 form.inline-search input,
-div.sphinxsidebar input {
-    font-family: 'Lucida Grande',Arial,sans-serif;
+div.sphinxsidebar input,
+div.related input {
+    font-family: 'Lucida Grande', Arial, sans-serif;
     border: 1px solid #999999;
     font-size: smaller;
     border-radius: 3px;
 }
 
-div.sphinxsidebar input[type=text] {
+div.sphinxsidebar input[type='text'] {
     max-width: 150px;
 }
 
@@ -126,7 +162,8 @@ div.body pre {
     border: 1px solid #ac9;
 }
 
-div.body div.admonition, div.body div.impl-detail {
+div.body div.admonition,
+div.body div.impl-detail {
     border-radius: 3px;
 }
 
@@ -147,7 +184,7 @@ div.body a:visited {
 }
 
 div.body a:hover {
-    color: #00B0E4;
+    color: #00b0e4;
 }
 
 tt, code, pre {
@@ -155,15 +192,20 @@ tt, code, pre {
     font-size: 96.5%;
 }
 
-div.body tt, div.body code {
+div.body tt,
+div.body code {
     border-radius: 3px;
 }
 
-div.body tt.descname, div.body code.descname {
+div.body tt.descname,
+div.body code.descname {
     font-size: 120%;
 }
 
-div.body tt.xref, div.body a tt, div.body code.xref, div.body a code {
+div.body tt.xref,
+div.body a tt,
+div.body code.xref,
+div.body a code {
     font-weight: normal;
 }
 
@@ -175,12 +217,14 @@ table.docutils {
     margin-bottom: 10px;
 }
 
-table.docutils td, table.docutils th {
+table.docutils td,
+table.docutils th {
     border: 1px solid #ddd !important;
     border-radius: 3px;
 }
 
-table p, table li {
+table p,
+table li {
     text-align: left !important;
 }
 
@@ -194,7 +238,8 @@ table.docutils td {
     padding: 0.3em 0.5em;
 }
 
-table.footnote, table.footnote td {
+table.footnote,
+table.footnote td {
     border: 0 !important;
 }
 
@@ -207,7 +252,7 @@ div.footer {
 }
 
 div.footer a:hover {
-    color: #0095C4;
+    color: #0095c4;
 }
 
 .refcount {
@@ -218,10 +263,6 @@ div.footer a:hover {
     color: #229;
 }
 
-.highlight {
-    background: none !important;
-}
-
 dl > dt span ~ em {
     font-family: "monospace", monospace;
 }
diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
new file mode 100644
index 0000000..d263f94
--- /dev/null
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -0,0 +1,119 @@
+
+/* Browser elements */
+:root {
+    scrollbar-color: #616161 transparent;
+    color-scheme: dark light;
+}
+
+html,
+body {
+    background-color: #222;
+    color: rgba(255, 255, 255, 0.87);
+}
+
+div.related {
+    color: rgba(255, 255, 255, 0.7); /* classic overwrite */
+    border-top-color: #424242;
+}
+
+div.related:first-child {
+    /* use :first-child because border-color would need !important */
+    border-bottom-color: #424242;
+}
+
+/* SIDEBAR */
+div.sphinxsidebar {
+    background-color: #333;
+    color: inherit;
+}
+
+#sidebarbutton {
+    /* important to overwrite style attribute */
+    background-color: #555 !important;
+    color: inherit !important;
+}
+
+div.sidebar {
+    background-color: #424242;
+    border-color: #616161;
+}
+
+/* ANCHORS AND HIGHLIGHTS */
+div.body a {
+    color: #7af;
+}
+
+div.body a:visited {
+    color: #09e;
+}
+
+a.headerlink:hover {
+    background-color: #424242;
+}
+
+div.related a {
+    color: currentColor;
+}
+
+div.footer,
+div.footer a {
+    color: currentColor; /* classic overwrites */
+}
+
+dt:target,
+span.highlighted {
+    background-color: #616161;
+}
+
+/* Below for most things in text */
+
+dl.field-list > dt {
+    background-color: #434;
+}
+
+table.docutils td,
+table.docutils th {
+    border-color: #616161 !important;
+}
+
+table.docutils th {
+    background-color: #424242;
+}
+
+.refcount {
+    color: #afa;
+}
+
+.stableabi {
+    color: #bbf;
+}
+
+div.body pre {
+    border-color: #616161;
+}
+
+code {
+    background-color: #424242;
+}
+
+div.body div.seealso {
+    background-color: rgba(255, 255, 0, 0.1);
+}
+
+div.warning {
+    background-color: rgba(255, 0, 0, 0.2);
+}
+
+.warning code {
+    background-color: rgba(255, 0, 0, 0.5);
+}
+
+div.topic,
+div.note {
+    background-color: rgba(255, 255, 255, 0.1);
+    border-color: currentColor;
+}
+
+.note code {
+    background-color: rgba(255, 255, 255, 0.1);
+}
diff --git a/python_docs_theme/static/themetoggle.js b/python_docs_theme/static/themetoggle.js
new file mode 100644
index 0000000..605d042
--- /dev/null
+++ b/python_docs_theme/static/themetoggle.js
@@ -0,0 +1,39 @@
+let currentTheme = localStorage.getItem('currentTheme') || 'auto'
+
+const pygmentsDark = document.getElementById('pygments_dark_css')
+const pydocthemeDark = document.getElementById('pydoctheme_dark_css')
+
+const themeOrder = {
+  light: 'dark',
+  dark: 'auto',
+  auto: 'light',
+}
+
+updateTheme()
+
+function toggleTheme() {
+  currentTheme = themeOrder[currentTheme]
+  localStorage.setItem('currentTheme', currentTheme)
+  updateTheme()
+}
+
+function updateTheme() {
+  const buttons = Array.from(document.getElementsByClassName('theme-toggle'))
+  switch (currentTheme) {
+    case 'light':
+      pydocthemeDark.media = 'not all'
+      pygmentsDark.media = 'not all'
+      buttons.forEach(e => e.value = "Toggle theme (light)")
+      break;
+    case 'dark':
+      pydocthemeDark.media = 'all'
+      pygmentsDark.media = 'all'
+      buttons.forEach(e => e.value = "Toggle theme (dark)")
+      break;
+    default:
+      // auto
+      pydocthemeDark.media = '(prefers-color-scheme: dark)'
+      pygmentsDark.media = '(prefers-color-scheme: dark)'
+      buttons.forEach(e => e.value = "Toggle theme (auto)")
+  }
+}
diff --git a/python_docs_theme/theme.conf b/python_docs_theme/theme.conf
index 11670d3..a011f5b 100644
--- a/python_docs_theme/theme.conf
+++ b/python_docs_theme/theme.conf
@@ -2,6 +2,7 @@
 inherit = default
 stylesheet = pydoctheme.css?2022.1
 pygments_style = default
+pygments_dark_style = monokai
 
 [options]
 bodyfont = 'Lucida Grande', Arial, sans-serif

From 647a1a3b694e59d664f08a25481b398353478e3c Mon Sep 17 00:00:00 2001
From: Julien Palard <julien@palard.fr>
Date: Mon, 10 May 2021 16:23:30 +0200
Subject: [PATCH 009/175] Show me the logs.

---
 .github/workflows/tests.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 824bb0c..61ce649 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -29,6 +29,7 @@ jobs:
       - name: build docs
         run: |
           python3 ./docsbuild-scripts/build_docs.py --quick --build-root ./build_root --www-root ./www --log-directory ./logs --group $(id -g) --skip-cache-invalidation --theme $(pwd) --language en --branch 3.9
+          cat logs/docsbuild.log
       - name: 'Upload'
         uses: actions/upload-artifact@v2.2.2
         with:

From 31e888d6065c70fff4bd62e06640bc22000fe28b Mon Sep 17 00:00:00 2001
From: Septatrix <24257556+Septatrix@users.noreply.github.com>
Date: Fri, 18 Nov 2022 22:27:54 +0200
Subject: [PATCH 010/175] Fix dark theme issues

---
 python_docs_theme/layout.html                | 11 +--------
 python_docs_theme/static/pydoctheme.css      | 26 +++++++-------------
 python_docs_theme/static/pydoctheme_dark.css |  7 +-----
 3 files changed, 11 insertions(+), 33 deletions(-)

diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index abf3664..f05f166 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -37,6 +37,7 @@ <h3>{{ _('Navigation') }}</h3>
                     {{ reldelim2 }}
                 </li>
             {%- endif %}
+            <li class="right"><input type="button" value="Toggle theme" class="theme-toggle" onclick="toggleTheme()">{{ reldelim2 }}</li>
             {% endblock %}
       </ul>
     </div>
@@ -59,16 +60,6 @@ <h3>{{ _('Navigation') }}</h3>
 {% block relbar1 %} {% if builder != 'qthelp' %} {{ relbar() }} {% endif %} {% endblock %}
 {% block relbar2 %} {% if builder != 'qthelp' %} {{ relbar() }} {% endif %} {% endblock %}
 
-{% block relbaritems %}
-{%- if pagename != "search" and builder != "singlehtml" and builder != "htmlhelp" %}
-<li class="right">
-    {{ searchbox() }}
-    {{ reldelim2 }}
-</li>
-{%- endif %}
-<li class="right"><input type="button" value="Toggle theme" class="theme-toggle" onclick="toggleTheme()">{{ reldelim2 }}</li>
-{% endblock %}
-
 {%- block extrahead -%}
     <link rel="stylesheet" href="{{ pathto('_static/pydoctheme_dark.css', 1) }}" media="(prefers-color-scheme: dark)" id="pydoctheme_dark_css">
     <link rel="shortcut icon" type="image/png" href="{{ pathto('_static/' + theme_root_icon, 1) }}" />
diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 21be22c..18ad610 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -34,24 +34,23 @@ body {
 }
 
 div.related {
+    margin-top: 0.5em;
     margin-bottom: 1.2em;
     padding: 0.5em 0;
-    border-top: 1px solid #ccc;
-    margin-top: 0.5em;
+    border-width: 1px;
+    border-color: #ccc;
 }
 
-div.related a:hover {
-    color: #0095c4;
+.mobile-nav + div.related {
+    border-bottom-style: solid;
 }
 
-div.related ~ div.related {
-    border-top: 1px solid #ccc;
-    border-bottom: none;
+.document + div.related {
+    border-top-style: solid;
 }
 
-div.related:first-child {
-    border-top: 0;
-    border-bottom: 1px solid #ccc;
+div.related a:hover {
+    color: #0095c4;
 }
 
 .related .switchers {
@@ -62,13 +61,6 @@ div.related:first-child {
     margin-right: 5px;
 }
 
-.version_switcher_placeholder,
-.language_switcher_placeholder {
-    padding-left: 5px;
-    background-color: white;
-}
-
-
 div.related ul::after {
     content: '';
     clear: both;
diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index d263f94..c101687 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -13,12 +13,7 @@ body {
 
 div.related {
     color: rgba(255, 255, 255, 0.7); /* classic overwrite */
-    border-top-color: #424242;
-}
-
-div.related:first-child {
-    /* use :first-child because border-color would need !important */
-    border-bottom-color: #424242;
+    border-color: #424242;
 }
 
 /* SIDEBAR */

From dd5772236307153b1361b0e825f329cebe8df65d Mon Sep 17 00:00:00 2001
From: Septatrix <24257556+Septatrix@users.noreply.github.com>
Date: Mon, 10 May 2021 16:38:16 +0200
Subject: [PATCH 011/175] Adjust to responsive changes

---
 python_docs_theme/static/pydoctheme.css      | 16 ++++++++--------
 python_docs_theme/static/pydoctheme_dark.css |  6 +++++-
 2 files changed, 13 insertions(+), 9 deletions(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 18ad610..69a59df 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -16,6 +16,12 @@ div.sphinxsidebar ul,
 div.sphinxsidebar h3,
 div.sphinxsidebar h3 a,
 div.sphinxsidebar h4,
+.menu a,
+.menu p,
+.menu ul,
+.menu h3,
+.menu h3 a,
+.menu h4,
 table.docutils td,
 table.indextable tr.cap,
 pre {
@@ -213,6 +219,7 @@ table.docutils td,
 table.docutils th {
     border: 1px solid #ddd !important;
     border-radius: 3px;
+    padding: 0.3em 0.5em;
 }
 
 table p,
@@ -222,12 +229,6 @@ table li {
 
 table.docutils th {
     background-color: #eee;
-    padding: 0.3em 0.5em;
-}
-
-table.docutils td {
-    background-color: white;
-    padding: 0.3em 0.5em;
 }
 
 table.footnote,
@@ -465,6 +466,7 @@ dl > dt span ~ em {
         width: 300px;
         height: 100%;
         background-color: #eee;
+        color: #444444;
         box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
         overflow-y: auto;
     }
@@ -484,7 +486,6 @@ dl > dt span ~ em {
         font-size: 1.3em;
     }
     .menu-wrapper h3 {
-        color: #444444;
         font-size: 1.4em;
     }
     .menu-wrapper h3 + p,
@@ -493,7 +494,6 @@ dl > dt span ~ em {
     }
     .menu a {
         font-size: smaller;
-        color: #444444;
         text-decoration: none;
     }
     .menu ul {
diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index c101687..2d574ad 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -17,7 +17,7 @@ div.related {
 }
 
 /* SIDEBAR */
-div.sphinxsidebar {
+div.sphinxsidebar, .menu-wrapper {
     background-color: #333;
     color: inherit;
 }
@@ -112,3 +112,7 @@ div.note {
 .note code {
     background-color: rgba(255, 255, 255, 0.1);
 }
+
+.mobile-nav {
+    box-shadow: rgba(255, 255, 255, 0.25) 0 0 2px 0;
+}
\ No newline at end of file

From 3bf3806b1f829b29ed5664b6772c1e9d163f270c Mon Sep 17 00:00:00 2001
From: Septatrix <24257556+Septatrix@users.noreply.github.com>
Date: Fri, 18 Nov 2022 22:31:44 +0200
Subject: [PATCH 012/175] Fix more bugs with the new mobile view

---
 python_docs_theme/layout.html                | 50 +++++++-----
 python_docs_theme/static/caret-down.svg      |  1 -
 python_docs_theme/static/pydoctheme.css      | 85 ++++++++++----------
 python_docs_theme/static/pydoctheme_dark.css |  8 ++
 python_docs_theme/static/themetoggle.js      | 31 ++-----
 5 files changed, 89 insertions(+), 86 deletions(-)
 delete mode 100644 python_docs_theme/static/caret-down.svg

diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index f05f166..3b28497 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -37,7 +37,7 @@ <h3>{{ _('Navigation') }}</h3>
                     {{ reldelim2 }}
                 </li>
             {%- endif %}
-            <li class="right"><input type="button" value="Toggle theme" class="theme-toggle" onclick="toggleTheme()">{{ reldelim2 }}</li>
+            <li class="right">{{ themeselector() }}{{ reldelim2 }}</li>
             {% endblock %}
       </ul>
     </div>
@@ -57,6 +57,17 @@ <h3>{{ _('Navigation') }}</h3>
     {%- endif %}
 {%- endmacro %}
 
+{%- macro themeselector() %}
+<label class="theme-selector-label">
+    {{ _('Color theme') }}
+    <select class="theme-selector" oninput="activateTheme(this.value)">
+        <option value="auto" selected>{{ _('Auto (default)') }}</option>
+        <option value="light">{{ _('Light theme') }}</option>
+        <option value="dark">{{ _('Dark theme') }}</option>
+    </select>
+</label>
+{%- endmacro %}
+
 {% block relbar1 %} {% if builder != 'qthelp' %} {{ relbar() }} {% endif %} {% endblock %}
 {% block relbar2 %} {% if builder != 'qthelp' %} {{ relbar() }} {% endif %} {% endblock %}
 
@@ -84,28 +95,31 @@ <h3>{{ _('Navigation') }}</h3>
 <div class="mobile-nav">
     <input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
            aria-pressed="false" aria-expanded="false" role="button" aria-label="{{ _('Menu')}}" />
-    <label for="menuToggler" class="toggler__label">
-        <span></span>
-    </label>
     <nav class="nav-content" role="navigation">
-         <a href="{{ theme_root_url }}" class="nav-logo">
-             <img src="{{ pathto('_static/py.svg', 1) }}" alt="Logo"/>
-         </a>
-        <div class="version_switcher_placeholder"></div>
-        {%- if pagename != "search" and builder != "singlehtml" %}
-        <form role="search" class="search" action="{{ pathto('search') }}" method="get">
-            <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
-                <path fill-rule="nonzero"
-                        d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" fill="#444"></path>
-            </svg>
-            <input type="text" name="q" aria-label="{{ _('Quick search') }}"/>
-            <input type="submit" value="{{ _('Go') }}"/>
-        </form>
-        {%- endif %}
+        <label for="menuToggler" class="toggler__label">
+            <span></span>
+        </label>
+        <span class="nav-items-wrapper">
+            <a href="{{ theme_root_url }}" class="nav-logo">
+                <img src="{{ pathto('_static/py.svg', 1) }}" alt="Logo"/>
+            </a>
+            <span class="version_switcher_placeholder"></span>
+            {%- if pagename != "search" and builder != "singlehtml" %}
+            <form id="searchbox" role="search" class="search" action="{{ pathto('search') }}" method="get">
+                <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
+                    <path fill-rule="nonzero" fill="currentColor" d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
+                </svg>
+                <input type="search" name="q" aria-label="{{ _('Quick search') }}"/>
+                <input type="submit" value="{{ _('Go') }}"/>
+                {# TODO missing hidden inputs #}
+            </form>
+            {%- endif %}
+        </span>
     </nav>
     <div class="menu-wrapper">
         <nav class="menu" role="navigation" aria-label="main navigation">
             <div class="language_switcher_placeholder"></div>
+            {{ themeselector() }}
             {%- if logo %}
             <p class="logo">
                 <a href="{{ pathto('index') }}">
diff --git a/python_docs_theme/static/caret-down.svg b/python_docs_theme/static/caret-down.svg
deleted file mode 100644
index fc55b34..0000000
--- a/python_docs_theme/static/caret-down.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg viewBox="0 0 30 30" xmlns="http://www.w3.org/2000/svg"><path d="M7.45896 11.25H22.5351c1.043 0 1.5645 1.2598.8262 1.998l-7.5352 7.5411c-.457.457-1.2011.457-1.6582 0L6.63279 13.248c-.73828-.7382-.2168-1.998.82617-1.998z" fill="#444"/></svg>
diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 69a59df..150965e 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -264,6 +264,10 @@ dl > dt span ~ em {
     padding-left: 20px;
 }
 
+.theme-selector {
+    margin-left: .5em;
+}
+
 @media (max-width: 1023px) {
     /* Body layout */
     div.body {
@@ -309,7 +313,6 @@ dl > dt span ~ em {
         position: fixed;
         top: 0;
         left: 0;
-        background-color: white;
         box-shadow: rgba(0, 0, 0, 0.25) 0 0 2px 0;
         z-index: 1;
     }
@@ -318,58 +321,55 @@ dl > dt span ~ em {
     }
     .nav-content {
         position: absolute;
-        z-index: 2;
-        left: 0;
-        top: 0;
+        z-index: 1;
         height: 40px;
         width: 100%;
         max-width: 100vw;
         padding: 0 1rem 0 45px;
         display: flex;
-        align-items: center;
         background-color: white;
     }
-    .nav-logo {
-        margin-right: 0.7rem;
+    .nav-items-wrapper {
         display: flex;
-        flex: 0 0 auto;
+        flex: auto;
+        padding: .5rem;
+    }
+    .nav-logo {
+        margin-right: 1rem;
+        flex-shrink: 0;
     }
     .nav-content img {
+        display: block;
         width: 20px;
-        height: auto;
     }
     .version_switcher_placeholder {
-        flex: 0 1 0;
         margin-right: 1rem;
     }
+    .version_switcher_placeholder > select {
+        height: 100%;
+    }
     .nav-content .search {
         display: flex;
-        flex: 1 1 auto;
-        align-items: center;
-        padding: 0 0 0 2px;
+        flex: auto;
         border: 1px solid #a9a9a9;
-        height: 30px;
-        overflow: hidden;
     }
     .nav-content .search:hover {
         box-shadow: 0 1px 6px 0 rgba(32,33,36,0.28);
         border-color: rgba(223,225,229,0);
     }
-    .nav-content .search input[type=text] {
+    .nav-content .search input[type=search] {
         border: 0;
         outline: 0;
-        box-shadow: none;
-        width: 40px;
-        height: 28px;
-        flex: 1 1 auto;
+        padding-left: 20px;
+        flex: 1;
     }
     .nav-content .search input[type=submit] {
         height: 100%;
         appearance: none;
         -webkit-appearance: none;
-        border: 1px solid transparent;
-        border-left-color: #a9a9a9;
         box-shadow: none;
+        border: 0;
+        outline: 1px solid #999;
         cursor: pointer;
         background-color: #f0f0f0;
         margin-right: 0;
@@ -378,34 +378,21 @@ dl > dt span ~ em {
         border-color: #a9a9a9;
     }
     .nav-content .search svg {
-        flex: 0 0 20px;
-        fill: #333;
+        position: absolute;
     }
     .toggler__input {
-        width: 40px;
-        height: 40px;
-        left: 0;
-        opacity: 0;
-        position: absolute;
-        z-index: 3;
-        margin: 0;
+        display: none;
     }
     .toggler__label {
         width: 40px;
-        height: 40px;
-        margin: 0;
-        position: absolute;
         cursor: pointer;
-        top: 0;
-        left: 0;
         background-color: transparent;
         border: 1px solid white;
-        box-shadow: none;
-        z-index: 3;
         display: flex;
         align-items: center;
         justify-content: center;
-        padding: 0 8px;
+        padding: 8px;
+        flex-shrink: 0;
     }
     .toggler__label:focus {
         background-color: #eee;
@@ -438,17 +425,17 @@ dl > dt span ~ em {
     .toggler__label > span::after {
         top: 8px;
     }
-    .toggler__input:checked ~ .toggler__label span {
+    .toggler__input:checked ~ nav > .toggler__label span {
         transform: rotate(135deg);
     }
-    .toggler__input:checked ~ .toggler__label span::before {
+    .toggler__input:checked ~ nav > .toggler__label span::before {
         transform: rotate(90deg);
     }
-    .toggler__input:checked ~ .toggler__label span::before,
-    .toggler__input:checked ~ .toggler__label span::after {
+    .toggler__input:checked ~ nav > .toggler__label span::before,
+    .toggler__input:checked ~ nav > .toggler__label span::after {
         top: 0;
     }
-    .toggler__input:checked:hover ~ .toggler__label span {
+    .toggler__input:checked:hover ~ nav > .toggler__label span {
         transform: rotate(315deg);
     }
     .toggler__input:checked ~ .menu-wrapper {
@@ -554,4 +541,14 @@ dl > dt span ~ em {
         width: 100%;
         overflow-x: auto;
     }
+
+    .menu .theme-selector-label {
+        margin-top: .5em;
+        display: flex;
+        width: 100%;
+    }
+
+    .menu .theme-selector {
+        flex: auto;
+    }
 }
diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index 2d574ad..9a7dc3b 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -115,4 +115,12 @@ div.note {
 
 .mobile-nav {
     box-shadow: rgba(255, 255, 255, 0.25) 0 0 2px 0;
+}
+
+.nav-content {
+    background-color: black;
+}
+
+.nav-content .search svg {
+    color: black;
 }
\ No newline at end of file
diff --git a/python_docs_theme/static/themetoggle.js b/python_docs_theme/static/themetoggle.js
index 605d042..f9394c6 100644
--- a/python_docs_theme/static/themetoggle.js
+++ b/python_docs_theme/static/themetoggle.js
@@ -1,39 +1,24 @@
-let currentTheme = localStorage.getItem('currentTheme') || 'auto'
-
-const pygmentsDark = document.getElementById('pygments_dark_css')
 const pydocthemeDark = document.getElementById('pydoctheme_dark_css')
+const pygmentsDark = document.getElementById('pygments_dark_css')
+const themeSelectors = document.getElementsByClassName('theme-selector')
 
-const themeOrder = {
-  light: 'dark',
-  dark: 'auto',
-  auto: 'light',
-}
-
-updateTheme()
-
-function toggleTheme() {
-  currentTheme = themeOrder[currentTheme]
-  localStorage.setItem('currentTheme', currentTheme)
-  updateTheme()
-}
-
-function updateTheme() {
-  const buttons = Array.from(document.getElementsByClassName('theme-toggle'))
-  switch (currentTheme) {
+function activateTheme(theme) {
+  localStorage.setItem('currentTheme', theme);
+  [...themeSelectors].forEach(e => e.value = theme)
+  switch (theme) {
     case 'light':
       pydocthemeDark.media = 'not all'
       pygmentsDark.media = 'not all'
-      buttons.forEach(e => e.value = "Toggle theme (light)")
       break;
     case 'dark':
       pydocthemeDark.media = 'all'
       pygmentsDark.media = 'all'
-      buttons.forEach(e => e.value = "Toggle theme (dark)")
       break;
     default:
       // auto
       pydocthemeDark.media = '(prefers-color-scheme: dark)'
       pygmentsDark.media = '(prefers-color-scheme: dark)'
-      buttons.forEach(e => e.value = "Toggle theme (auto)")
   }
 }
+
+activateTheme(localStorage.getItem('currentTheme') || 'auto')

From 9b7588938cfe85d58d422535c18ba2e4061940c5 Mon Sep 17 00:00:00 2001
From: Septatrix <24257556+Septatrix@users.noreply.github.com>
Date: Sat, 19 Nov 2022 00:24:28 +0200
Subject: [PATCH 013/175] Update dark theme to work with mobile style

---
 python_docs_theme/layout.html                |  8 +--
 python_docs_theme/static/pydoctheme.css      | 68 ++++----------------
 python_docs_theme/static/pydoctheme_dark.css |  8 +--
 3 files changed, 17 insertions(+), 67 deletions(-)

diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index 3b28497..5327b38 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -59,11 +59,11 @@ <h3>{{ _('Navigation') }}</h3>
 
 {%- macro themeselector() %}
 <label class="theme-selector-label">
-    {{ _('Color theme') }}
+    {{ _('Theme') }}
     <select class="theme-selector" oninput="activateTheme(this.value)">
-        <option value="auto" selected>{{ _('Auto (default)') }}</option>
-        <option value="light">{{ _('Light theme') }}</option>
-        <option value="dark">{{ _('Dark theme') }}</option>
+        <option value="auto" selected>{{ _('Auto') }}</option>
+        <option value="light">{{ _('Light') }}</option>
+        <option value="dark">{{ _('Dark') }}</option>
     </select>
 </label>
 {%- endmacro %}
diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 150965e..f48311a 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -324,19 +324,19 @@ dl > dt span ~ em {
         z-index: 1;
         height: 40px;
         width: 100%;
-        max-width: 100vw;
-        padding: 0 1rem 0 45px;
         display: flex;
         background-color: white;
     }
     .nav-items-wrapper {
         display: flex;
         flex: auto;
-        padding: .5rem;
+        padding: .25rem;
+        align-items: stretch;
     }
     .nav-logo {
         margin-right: 1rem;
         flex-shrink: 0;
+        align-self: center;
     }
     .nav-content img {
         display: block;
@@ -352,33 +352,25 @@ dl > dt span ~ em {
         display: flex;
         flex: auto;
         border: 1px solid #a9a9a9;
-    }
-    .nav-content .search:hover {
-        box-shadow: 0 1px 6px 0 rgba(32,33,36,0.28);
-        border-color: rgba(223,225,229,0);
+        align-items: stretch;
     }
     .nav-content .search input[type=search] {
         border: 0;
-        outline: 0;
-        padding-left: 20px;
+        padding-left: 24px;
         flex: 1;
     }
     .nav-content .search input[type=submit] {
         height: 100%;
-        appearance: none;
-        -webkit-appearance: none;
         box-shadow: none;
         border: 0;
-        outline: 1px solid #999;
+        border-left: 1px solid #a9a9a9;
         cursor: pointer;
-        background-color: #f0f0f0;
         margin-right: 0;
     }
-    .nav-content .search input[type=submit]:hover {
-        border-color: #a9a9a9;
-    }
     .nav-content .search svg {
         position: absolute;
+        align-self: center;
+        padding-left: 4px;
     }
     .toggler__input {
         display: none;
@@ -386,30 +378,21 @@ dl > dt span ~ em {
     .toggler__label {
         width: 40px;
         cursor: pointer;
-        background-color: transparent;
-        border: 1px solid white;
         display: flex;
         align-items: center;
         justify-content: center;
         padding: 8px;
         flex-shrink: 0;
     }
-    .toggler__label:focus {
-        background-color: #eee;
-        border: 1px solid #ededed;
-        box-shadow: rgba(0, 0, 0, 0.25) 1px 0 2px 0;
-    }
-    .toggler__label:hover {
-        background-color: #eee;
-        border: 1px solid #ededed;
-        box-shadow: rgba(0, 0, 0, 0.25) 1px 0 2px 0;
+    .toggler__label:hover, .toggler__label:focus {
+        background-color: rgba(127 127 127 / 50%);
     }
     .toggler__label > span {
         position: relative;
         flex: none;
         height: 2px;
         width: 100%;
-        background: #444;
+        background: currentColor;
         transition: all 400ms ease;
     }
     .toggler__label > span::before,
@@ -496,38 +479,9 @@ dl > dt span ~ em {
     .menu ul li {
         margin-bottom: 0.5rem;
     }
-    .language_switcher_placeholder,
-    .version_switcher_placeholder {
-        position: relative;
-        border: 1px solid #a8a8a8;
-        height: 30px;
-        padding-right: 7px;
-    }
     .language_switcher_placeholder {
         margin-top: 2rem;
     }
-    .language_switcher_placeholder::after,
-    .version_switcher_placeholder::after {
-        content: url('../_static/caret-down.svg');
-        position: absolute;
-        top: 7px;
-        width: 15px;
-        height: 15px;
-        right: 0;
-        pointer-events: none;
-    }
-    .language_switcher_placeholder select,
-    .version_switcher_placeholder select {
-        -webkit-appearance: none;
-        appearance: none;
-        border: 0;
-        height: 100%;
-        background-color: white;
-    }
-    .language_switcher_placeholder:focus-visible,
-    .version_switcher_placeholder:focus-visible {
-        outline-offset: 5px;
-    }
     .language_switcher_placeholder select {
         width: 100%;
     }
diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index 9a7dc3b..4aa657b 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -2,7 +2,7 @@
 /* Browser elements */
 :root {
     scrollbar-color: #616161 transparent;
-    color-scheme: dark light;
+    color-scheme: dark;
 }
 
 html,
@@ -28,7 +28,7 @@ div.sphinxsidebar, .menu-wrapper {
     color: inherit !important;
 }
 
-div.sidebar {
+div.sidebar, aside.sidebar {
     background-color: #424242;
     border-color: #616161;
 }
@@ -120,7 +120,3 @@ div.note {
 .nav-content {
     background-color: black;
 }
-
-.nav-content .search svg {
-    color: black;
-}
\ No newline at end of file

From 15c8fc99d430a2bdf14456cf41cd3738cc221d03 Mon Sep 17 00:00:00 2001
From: Peter Hill <peter.hill@york.ac.uk>
Date: Mon, 30 Jan 2023 16:51:22 +0000
Subject: [PATCH 014/175] Fix problem with monospace rendering in Vivaldi

Fixes #98
---
 python_docs_theme/static/pydoctheme.css | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 151f06e..4396e1b 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -151,7 +151,7 @@ div.body a:hover {
 }
 
 tt, code, pre {
-    font-family: "monospace", monospace;
+    font-family: ui-monospace, "Cascadia Mono", "Segoe UI Mono", "Liberation Mono", Menlo, Monaco, Consolas, monospace;
     font-size: 96.5%;
 }
 
@@ -223,7 +223,7 @@ div.footer a:hover {
 }
 
 dl > dt span ~ em {
-    font-family: "monospace", monospace;
+    font-family: ui-monospace, "Cascadia Mono", "Segoe UI Mono", "Liberation Mono", Menlo, Monaco, Consolas, monospace;
 }
 
 .toctree-wrapper ul {

From b52b8cf68741b3cd55a699c5c8402d0e1e56923b Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Tue, 7 Feb 2023 00:44:34 +0200
Subject: [PATCH 015/175] Apply suggestions from code review

---
 CONTRIBUTING.rst |  6 +++---
 Makefile         | 17 +++++++++--------
 2 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 38807d1..b313093 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -14,11 +14,11 @@
 - Commit this last bump.
 - push and push the tag (``git push && git push --tags``)
 
-# Makefile Usage
+# Makefile usage
 
 This project includes a simple Makefile for syncing changes to the theme with
-the main cpython repository. Run ``make help`` for details on available rules.
+the main CPython repository. Run ``make help`` for details on available rules.
 
 There is one configurable variable, ``CPYTHON_PATH``, which should be the path
-to the cpython repository on your machine. By default, it points to
+to the CPython repository on your machine. By default, it points to
 ``../cpython``.
diff --git a/Makefile b/Makefile
index a7cf07a..7cde7e9 100644
--- a/Makefile
+++ b/Makefile
@@ -2,20 +2,21 @@ CPYTHON_PATH               = ../cpython
 PACKAGE_ABS_PATH = $(shell pwd)/$(shell find dist/python-docs-theme-*.tar.gz)
 
 
-.PHONY: all
-all: install
+.PHONY: html
+html: venv
 	cd $(CPYTHON_PATH)/Doc && \
 		make html
 
 
-.PHONY: install
-install:
+.PHONY: venv
+venv:
 	python3 -m build
-	cd $(CPYTHON_PATH)/Doc && \
-		./venv/bin/pip install $(PACKAGE_ABS_PATH)
+	cd $(CPYTHON_PATH)/Doc \
+		&& make venv \
+		&& ./venv/bin/pip install $(PACKAGE_ABS_PATH)
 
 .PHONY: help
 help:
-	@echo "all:		default rule; run the \`install\` rule, and also rebuild the cpython docs"
-	@echo "install: 	build the package, and install it into the virtual environment"
+	@echo "html:		default rule; run the \`venv\` rule, and also rebuild the CPython docs"
+	@echo "venv: 		build the package, and install it into the virtual environment"
 	@echo "		at $(CPYTHON_PATH)/Doc/venv"

From be22407d3a2d103768b58a24c982ca8c942bc52b Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Tue, 31 Jan 2023 23:40:56 +0200
Subject: [PATCH 016/175] Makefile suggestions

---
 Makefile | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
index 7cde7e9..cf8144e 100644
--- a/Makefile
+++ b/Makefile
@@ -10,6 +10,7 @@ html: venv
 
 .PHONY: venv
 venv:
+	python3 -m pip install build
 	python3 -m build
 	cd $(CPYTHON_PATH)/Doc \
 		&& make venv \
@@ -18,5 +19,5 @@ venv:
 .PHONY: help
 help:
 	@echo "html:		default rule; run the \`venv\` rule, and also rebuild the CPython docs"
-	@echo "venv: 		build the package, and install it into the virtual environment"
+	@echo "venv:		build the package, and install it into the virtual environment"
 	@echo "		at $(CPYTHON_PATH)/Doc/venv"

From d3834dae382c46b73e4c03a3512304c40706a7e7 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Tue, 31 Jan 2023 23:42:04 +0200
Subject: [PATCH 017/175] Build CPython docs with this theme on Read the Docs

---
 .readthedocs.yml | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
 create mode 100644 .readthedocs.yml

diff --git a/.readthedocs.yml b/.readthedocs.yml
new file mode 100644
index 0000000..7ac1f46
--- /dev/null
+++ b/.readthedocs.yml
@@ -0,0 +1,15 @@
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+# Project page: https://readthedocs.org/projects/python-docs-theme-previews/
+
+version: 2
+
+build:
+  os: ubuntu-22.04
+  tools:
+    python: "3"
+
+  commands:
+    - git clone --depth=1 https://github.com/python/cpython
+    - make html CPYTHON_PATH=cpython
+    - mv cpython/Doc/build _readthedocs

From 9a3e9888584640a8b76bfbf4e3f34d36e8fbd2f1 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Tue, 7 Feb 2023 18:44:44 +0200
Subject: [PATCH 018/175] Add 'make htmlview' and be consistent with our other
 Makefiles

---
 Makefile | 32 +++++++++++++++++++-------------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/Makefile b/Makefile
index cf8144e..bae8932 100644
--- a/Makefile
+++ b/Makefile
@@ -1,23 +1,29 @@
-CPYTHON_PATH               = ../cpython
+# You can set these variables from the command line.
+CPYTHON_PATH = ../cpython
+PYTHON       = python3
 PACKAGE_ABS_PATH = $(shell pwd)/$(shell find dist/python-docs-theme-*.tar.gz)
 
 
-.PHONY: html
-html: venv
-	cd $(CPYTHON_PATH)/Doc && \
-		make html
-
+.PHONY: help
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  venv       to create a venv with necessary tools at $(CPYTHON_PATH)/Doc/venv"
+	@echo "  html       to make standalone CPython HTML files"
+	@echo "  htmlview   to open the index page built by the html target in your browser"
 
 .PHONY: venv
 venv:
-	python3 -m pip install build
-	python3 -m build
+	$(PYTHON) -m pip install build
+	$(PYTHON) -m build
 	cd $(CPYTHON_PATH)/Doc \
 		&& make venv \
 		&& ./venv/bin/pip install $(PACKAGE_ABS_PATH)
 
-.PHONY: help
-help:
-	@echo "html:		default rule; run the \`venv\` rule, and also rebuild the CPython docs"
-	@echo "venv:		build the package, and install it into the virtual environment"
-	@echo "		at $(CPYTHON_PATH)/Doc/venv"
+.PHONY: html
+html: venv
+	cd $(CPYTHON_PATH)/Doc && \
+		make html
+
+.PHONY: htmlview
+htmlview: html
+	$(PYTHON) -c "import os, webbrowser; webbrowser.open('file://' + os.path.realpath('$(CPYTHON_PATH)/Doc/build/html/index.html'))"

From 9913e1dd8dd3ba42046e3aa0a88da5d695463fd8 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Mon, 6 Feb 2023 12:29:14 +0200
Subject: [PATCH 019/175] Reduce footer only for desktop

---
 python_docs_theme/static/pydoctheme.css | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 4396e1b..4e4d2e7 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -200,7 +200,6 @@ table.footnote, table.footnote td {
 
 div.footer {
     line-height: 150%;
-    margin-top: -2em;
     text-align: right;
     width: auto;
     margin-right: 10px;
@@ -522,3 +521,9 @@ dl > dt span ~ em {
         overflow-x: auto;
     }
 }
+
+@media (min-width: 1024px) {
+    div.footer {
+        margin-top: -2em;
+    }
+}

From a51bc0a922accd526ed7d6bee291812c715761b3 Mon Sep 17 00:00:00 2001
From: philg314 <110174000+philg314@users.noreply.github.com>
Date: Mon, 8 Aug 2022 16:47:20 +0200
Subject: [PATCH 020/175] Fix mobile nav obstructing content

---
 python_docs_theme/static/pydoctheme.css | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 4396e1b..bb1697c 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -266,6 +266,9 @@ dl > dt span ~ em {
     html {
         scroll-padding-top: 40px;
     }
+    body {
+        margin-top: 40px;
+    }
 
     /* Top navigation bar */
     .mobile-nav {
@@ -512,7 +515,6 @@ dl > dt span ~ em {
         width: 100%;
     }
     .document {
-        padding-top: 40px;
         position: relative;
         z-index: 0;
     }

From 859f780cb52d014801face1546732e2cb0c74ec7 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Wed, 18 Jan 2023 12:14:42 +0200
Subject: [PATCH 021/175] A11y: Increase the target area for single-letter
 index links

---
 python_docs_theme/static/pydoctheme.css | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 4396e1b..b5b6ff9 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -230,6 +230,10 @@ dl > dt span ~ em {
     padding-left: 20px;
 }
 
+div.genindex-jumpbox a {
+    padding: 0 0.5em;
+}
+
 @media (max-width: 1023px) {
     /* Body layout */
     div.body {

From 75b8026ada65adb50b06bebeee5fd20fadb4a9ef Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Wed, 18 Jan 2023 21:59:38 +0200
Subject: [PATCH 022/175] A11y: Increase the target area for single-letter
 index links

---
 python_docs_theme/static/pydoctheme.css | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index b5b6ff9..2a35f9a 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -230,8 +230,16 @@ dl > dt span ~ em {
     padding-left: 20px;
 }
 
+div.genindex-jumpbox,
+div.genindex-jumpbox > p {
+    display: inline-flex;
+    flex-wrap: wrap;
+}
+
 div.genindex-jumpbox a {
-    padding: 0 0.5em;
+    margin: 0 5px;
+    min-width: 30px;
+    text-align: center;
 }
 
 @media (max-width: 1023px) {

From 6e3e8f037d7a5a5fb6bc522eff0157935f3309dc Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Thu, 16 Feb 2023 15:03:29 +0200
Subject: [PATCH 023/175] Append a hash ?digest to CSS files for cache-busting

---
 python_docs_theme/__init__.py | 51 +++++++++++++++++++++++++++++++++++
 python_docs_theme/theme.conf  |  2 +-
 2 files changed, 52 insertions(+), 1 deletion(-)

diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py
index 407d62a..62b16f0 100644
--- a/python_docs_theme/__init__.py
+++ b/python_docs_theme/__init__.py
@@ -1,4 +1,53 @@
+import hashlib
 import os
+from functools import lru_cache
+from pathlib import Path
+from typing import Any, Dict, List
+
+import sphinx.application
+from sphinx.builders.html import StandaloneHTMLBuilder
+
+THEME_PATH = Path(__file__).parent.resolve()
+
+
+@lru_cache(maxsize=None)
+def _asset_hash(path: str) -> str:
+    """Append a `?digest=` to an url based on the file content."""
+    full_path = THEME_PATH / path.replace("_static/", "static/")
+    digest = hashlib.sha1(full_path.read_bytes()).hexdigest()
+
+    return f"{path}?digest={digest}"
+
+
+def _add_asset_hashes(static: List[str], add_digest_to: List[str]) -> None:
+    for asset in add_digest_to:
+        index = static.index(asset)
+        static[index].filename = _asset_hash(asset)  # type: ignore
+
+
+def _html_page_context(
+    app: sphinx.application.Sphinx,
+    pagename: str,
+    templatename: str,
+    context: Dict[str, Any],
+    doctree: Any,
+) -> None:
+    if app.config.html_theme != "python_docs_theme":
+        return
+
+    assert isinstance(app.builder, StandaloneHTMLBuilder)
+
+    if "css_files" in context:
+        if "_static/pydoctheme.css" not in context["css_files"]:
+            raise ValueError(
+                "This documentation is not using `pydoctheme.css` as the stylesheet. "
+                "If you have set `html_style` in your conf.py file, remove it."
+            )
+
+        _add_asset_hashes(
+            context["css_files"],
+            ["_static/pydoctheme.css"],
+        )
 
 
 def setup(app):
@@ -6,6 +55,8 @@ def setup(app):
     app.add_html_theme(
         'python_docs_theme', current_dir)
 
+    app.connect("html-page-context", _html_page_context)
+
     return {
         'parallel_read_safe': True,
         'parallel_write_safe': True,
diff --git a/python_docs_theme/theme.conf b/python_docs_theme/theme.conf
index 11670d3..dfdfdff 100644
--- a/python_docs_theme/theme.conf
+++ b/python_docs_theme/theme.conf
@@ -1,6 +1,6 @@
 [theme]
 inherit = default
-stylesheet = pydoctheme.css?2022.1
+stylesheet = pydoctheme.css
 pygments_style = default
 
 [options]

From eb5e3cb052c71e3344068f28c7ea1c5bc66101d1 Mon Sep 17 00:00:00 2001
From: Septatrix <24257556+Septatrix@users.noreply.github.com>
Date: Fri, 24 Feb 2023 16:05:43 +0100
Subject: [PATCH 024/175] Fix search bar width and remove legacy fields

---
 python_docs_theme/layout.html           | 7 ++-----
 python_docs_theme/static/pydoctheme.css | 1 +
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index 5327b38..bf4e425 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -48,10 +48,8 @@ <h3>{{ _('Navigation') }}</h3>
     {%- if builder != "htmlhelp" %}
     <div class="inline-search" role="search">
         <form class="inline-search" action="{{ pathto('search') }}" method="get">
-          <input placeholder="{{ _('Quick search') }}" aria-label="{{ _('Quick search') }}" type="text" name="q" />
+          <input placeholder="{{ _('Quick search') }}" aria-label="{{ _('Quick search') }}" type="search" name="q" />
           <input type="submit" value="{{ _('Go') }}" />
-          <input type="hidden" name="check_keywords" value="yes" />
-          <input type="hidden" name="area" value="default" />
         </form>
     </div>
     {%- endif %}
@@ -109,9 +107,8 @@ <h3>{{ _('Navigation') }}</h3>
                 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
                     <path fill-rule="nonzero" fill="currentColor" d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
                 </svg>
-                <input type="search" name="q" aria-label="{{ _('Quick search') }}"/>
+                <input placeholder="{{ _('Quick search') }}" aria-label="{{ _('Quick search') }}" type="search" name="q" />
                 <input type="submit" value="{{ _('Go') }}"/>
-                {# TODO missing hidden inputs #}
             </form>
             {%- endif %}
         </span>
diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index f48311a..cfbcc18 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -357,6 +357,7 @@ dl > dt span ~ em {
     .nav-content .search input[type=search] {
         border: 0;
         padding-left: 24px;
+        width: 100%;
         flex: 1;
     }
     .nav-content .search input[type=submit] {

From acd47543c2dfd6f15dc177ed2872968dc4479336 Mon Sep 17 00:00:00 2001
From: Julien Palard <julien@palard.fr>
Date: Tue, 7 Mar 2023 18:31:42 +0100
Subject: [PATCH 025/175] Releasing v2023.3

---
 CHANGELOG.rst    | 9 +++++++++
 CONTRIBUTING.rst | 2 +-
 pyproject.toml   | 2 +-
 3 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 73fb190..2ca52c6 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,6 +2,15 @@
 Changelog
 =========
 
+`2023.3 <https://github.com/python/python-docs-theme/releases/tag/v2023.3>`_
+----------------------------------------------------------------------------
+
+- Fix problem with monospace rendering in Vivaldi #104
+- Fix mobile nav obstructing content #96
+- Reduce footer margin only for desktop #106
+- Append a hash ?digest to CSS files for cache-busting #108
+
+
 `2022.1 <https://github.com/python/python-docs-theme/releases/tag/v2022.1>`_
 ----------------------------------------------------------------------------------
 
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index b313093..eb499bb 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -1,7 +1,7 @@
 # How to release
 
 - Update CHANGELOG.rst
-- bump version (YYYY.MM) in setup.py and python_docs_theme/theme.conf
+- bump version (YYYY.MM) in pyproject.toml
 - commit
 - push to check one last time if the tests pass github side.
 - tag it (YYYY.MM).
diff --git a/pyproject.toml b/pyproject.toml
index 3d4c8b2..02a4f52 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,7 +5,7 @@ build-backend = "flit_core.buildapi"
 # project metadata
 [project]
 name = "python-docs-theme"
-version = "2022.1"
+version = "2023.3"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.rst"
 urls.Code = "https://github.com/python/python-docs-theme"

From 8b88430553fdaa1d7a85296a106158b5faf99a4b Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sat, 11 Mar 2023 13:32:42 +0200
Subject: [PATCH 026/175] Skip cache-busting for old Sphinx

---
 python_docs_theme/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py
index 62b16f0..bbe1352 100644
--- a/python_docs_theme/__init__.py
+++ b/python_docs_theme/__init__.py
@@ -37,7 +37,7 @@ def _html_page_context(
 
     assert isinstance(app.builder, StandaloneHTMLBuilder)
 
-    if "css_files" in context:
+    if sphinx.version_info >= (4,) and "css_files" in context:
         if "_static/pydoctheme.css" not in context["css_files"]:
             raise ValueError(
                 "This documentation is not using `pydoctheme.css` as the stylesheet. "

From 4d54ea04c01383432695d398df3a0b7171babe1e Mon Sep 17 00:00:00 2001
From: Maciej Olko <maciej.olko@affirm.com>
Date: Sat, 11 Mar 2023 17:02:54 +0100
Subject: [PATCH 027/175] Add matrix strategy to test with all supported Python
 versions

---
 .github/workflows/tests.yml | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 6ae5953..6982204 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -9,6 +9,9 @@ jobs:
   build_doc:
     name: Build CPython documentation
     runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        version: [3.7, 3.8, 3.9, '3.10', 3.11]
     steps:
       - uses: actions/checkout@v3
       - uses: actions/setup-python@v4
@@ -32,7 +35,7 @@ jobs:
           --skip-cache-invalidation 
           --theme $(pwd) 
           --language en 
-          --branch 3.11
+          --branch ${{ matrix.version }}
       - name: Upload
         uses: actions/upload-artifact@v3
         with:

From 1e8dfe719525ebc6dbdccbec3ac69592620e7e8e Mon Sep 17 00:00:00 2001
From: Julien Palard <julien@palard.fr>
Date: Mon, 13 Mar 2023 11:57:01 +0100
Subject: [PATCH 028/175] Releasing v2023.3.1 (#116)

---
 CHANGELOG.rst  | 6 ++++++
 pyproject.toml | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 2ca52c6..d06040d 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,6 +2,12 @@
 Changelog
 =========
 
+`2023.3.1 <https://github.com/python/python-docs-theme/releases/tag/v2023.3.1>`_
+--------------------------------------------------------------------------------
+
+- Skip cache-busting for old Sphinx #113
+
+
 `2023.3 <https://github.com/python/python-docs-theme/releases/tag/v2023.3>`_
 ----------------------------------------------------------------------------
 
diff --git a/pyproject.toml b/pyproject.toml
index 02a4f52..39e986d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,7 +5,7 @@ build-backend = "flit_core.buildapi"
 # project metadata
 [project]
 name = "python-docs-theme"
-version = "2023.3"
+version = "2023.3.1"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.rst"
 urls.Code = "https://github.com/python/python-docs-theme"

From 259399c55752e7dba4dcb4ad8dbd539da3e0d576 Mon Sep 17 00:00:00 2001
From: Maciej Olko <maciej.olko@affirm.com>
Date: Sun, 12 Mar 2023 23:20:23 +0100
Subject: [PATCH 029/175] Test also with main branch of Python

---
 .github/workflows/tests.yml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 6982204..cec17c3 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -7,11 +7,11 @@ on:
 
 jobs:
   build_doc:
-    name: Build CPython documentation
+    name: Build CPython docs
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        version: [3.7, 3.8, 3.9, '3.10', 3.11]
+        branch: [origin/main, 3.11, '3.10', 3.9, 3.8, 3.7]
     steps:
       - uses: actions/checkout@v3
       - uses: actions/setup-python@v4
@@ -35,7 +35,7 @@ jobs:
           --skip-cache-invalidation 
           --theme $(pwd) 
           --language en 
-          --branch ${{ matrix.version }}
+          --branch ${{ matrix.branch }}
       - name: Upload
         uses: actions/upload-artifact@v3
         with:

From 460959987687396493aa12703edbc96294f7ec85 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Mon, 27 Mar 2023 19:57:47 +0300
Subject: [PATCH 030/175] Include license file in sdist (#123)

---
 pyproject.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pyproject.toml b/pyproject.toml
index 39e986d..f0296e5 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -12,7 +12,7 @@ urls.Code = "https://github.com/python/python-docs-theme"
 urls.Download = "https://pypi.org/project/python-docs-theme/"
 urls.Homepage = "https://github.com/python/python-docs-theme/"
 urls."Issue tracker" = "https://github.com/python/python-docs-theme/issues"
-license.text = "PSF-2.0"
+license.file = "LICENSE"
 requires-python = ">=3.8"
 
 # Classifiers list: https://pypi.org/classifiers/

From 14e362fb00702633a02f4a5d99666630c0dc81f2 Mon Sep 17 00:00:00 2001
From: Septatrix <24257556+Septatrix@users.noreply.github.com>
Date: Wed, 12 Apr 2023 22:45:48 +0200
Subject: [PATCH 031/175] Remove searchbox id from form (fixes #117)

---
 python_docs_theme/layout.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index bf4e425..b4502ba 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -103,7 +103,7 @@ <h3>{{ _('Navigation') }}</h3>
             </a>
             <span class="version_switcher_placeholder"></span>
             {%- if pagename != "search" and builder != "singlehtml" %}
-            <form id="searchbox" role="search" class="search" action="{{ pathto('search') }}" method="get">
+            <form role="search" class="search" action="{{ pathto('search') }}" method="get">
                 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
                     <path fill-rule="nonzero" fill="currentColor" d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
                 </svg>

From 32115c4ce888d4147fb98a62b96a4ecb272c7e00 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Date: Thu, 13 Apr 2023 14:42:24 +0100
Subject: [PATCH 032/175] Update ``python-docs-theme`` to work with Sphinx 5 &
 6 (#99)

* Use double quotation marks in ``__init__.py``
* Drop semicolons in ``menu.js``
* Use braces for if-statements in ``menu.js``
* Use double quotation marks in ``menu.js``
* Mark a parameter as unused in ``menu.js``
* Drop jQuery in ``sidebars.js``
* Drop jQuery in ``copybutton.js``
* Introduce ``getHideableCopyButtonElements()``
* Mild JavaScript refactor
---
 python_docs_theme/__init__.py           |   7 +-
 python_docs_theme/static/copybutton.js  | 140 ++++++++++--------
 python_docs_theme/static/menu.js        |  64 +++++----
 python_docs_theme/static/pydoctheme.css |  49 +++++++
 python_docs_theme/static/sidebar.js     | 179 ++++++++----------------
 python_docs_theme/theme.conf            |   1 +
 6 files changed, 230 insertions(+), 210 deletions(-)

diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py
index bbe1352..68bb9e3 100644
--- a/python_docs_theme/__init__.py
+++ b/python_docs_theme/__init__.py
@@ -52,12 +52,11 @@ def _html_page_context(
 
 def setup(app):
     current_dir = os.path.abspath(os.path.dirname(__file__))
-    app.add_html_theme(
-        'python_docs_theme', current_dir)
+    app.add_html_theme("python_docs_theme", current_dir)
 
     app.connect("html-page-context", _html_page_context)
 
     return {
-        'parallel_read_safe': True,
-        'parallel_write_safe': True,
+        "parallel_read_safe": True,
+        "parallel_write_safe": True,
     }
diff --git a/python_docs_theme/static/copybutton.js b/python_docs_theme/static/copybutton.js
index 16dee00..7367c4a 100644
--- a/python_docs_theme/static/copybutton.js
+++ b/python_docs_theme/static/copybutton.js
@@ -1,64 +1,92 @@
-$(document).ready(function() {
-    /* Add a [>>>] button on the top-right corner of code samples to hide
+// ``function*`` denotes a generator in JavaScript, see
+// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
+function* getHideableCopyButtonElements(rootElement) {
+    // yield all elements with the "go" (Generic.Output),
+    // "gp" (Generic.Prompt), or "gt" (Generic.Traceback) CSS class
+    for (const el of rootElement.querySelectorAll('.go, .gp, .gt')) {
+        yield el
+    }
+    // tracebacks (.gt) contain bare text elements that need to be
+    // wrapped in a span to hide or show the element
+    for (let el of rootElement.querySelectorAll('.gt')) {
+        while ((el = el.nextSibling) && el.nodeType !== Node.DOCUMENT_NODE) {
+            // stop wrapping text nodes when we hit the next output or
+            // prompt element
+            if (el.nodeType === Node.ELEMENT_NODE && el.matches(".gp, .go")) {
+                break
+            }
+            // if the node is a text node with content, wrap it in a
+            // span element so that we can control visibility
+            if (el.nodeType === Node.TEXT_NODE && el.textContent.trim()) {
+                const wrapper = document.createElement("span")
+                el.after(wrapper)
+                wrapper.appendChild(el)
+                el = wrapper
+            }
+            yield el
+        }
+    }
+}
+
+
+const loadCopyButton = () => {
+    /* Add a [>>>] button in the top-right corner of code samples to hide
      * the >>> and ... prompts and the output and thus make the code
      * copyable. */
-    var div = $('.highlight-python .highlight,' +
-                '.highlight-python3 .highlight,' +
-                '.highlight-pycon .highlight,' +
-                '.highlight-pycon3 .highlight,' +
-                '.highlight-default .highlight');
-    var pre = div.find('pre');
+    const hide_text = "Hide the prompts and output"
+    const show_text = "Show the prompts and output"
 
-    // get the styles from the current theme
-    pre.parent().parent().css('position', 'relative');
-    var hide_text = 'Hide the prompts and output';
-    var show_text = 'Show the prompts and output';
-    var border_width = pre.css('border-top-width');
-    var border_style = pre.css('border-top-style');
-    var border_color = pre.css('border-top-color');
-    var button_styles = {
-        'cursor':'pointer', 'position': 'absolute', 'top': '0', 'right': '0',
-        'border-color': border_color, 'border-style': border_style,
-        'border-width': border_width, 'color': border_color, 'text-size': '75%',
-        'font-family': 'monospace', 'padding-left': '0.2em', 'padding-right': '0.2em',
-        'border-radius': '0 3px 0 0'
+    const button = document.createElement("span")
+    button.classList.add("copybutton")
+    button.innerText = ">>>"
+    button.title = hide_text
+    button.dataset.hidden = "false"
+    const buttonClick = event => {
+        // define the behavior of the button when it's clicked
+        event.preventDefault()
+        const buttonEl = event.currentTarget
+        const codeEl = buttonEl.nextElementSibling
+        if (buttonEl.dataset.hidden === "false") {
+            // hide the code output
+            for (const el of getHideableCopyButtonElements(codeEl)) {
+                el.hidden = true
+            }
+            buttonEl.title = show_text
+            buttonEl.dataset.hidden = "true"
+        } else {
+            // show the code output
+            for (const el of getHideableCopyButtonElements(codeEl)) {
+                el.hidden = false
+            }
+            buttonEl.title = hide_text
+            buttonEl.dataset.hidden = "false"
+        }
     }
 
+    const highlightedElements = document.querySelectorAll(
+        ".highlight-python .highlight,"
+        + ".highlight-python3 .highlight,"
+        + ".highlight-pycon .highlight,"
+        + ".highlight-pycon3 .highlight,"
+        + ".highlight-default .highlight"
+    )
+
     // create and add the button to all the code blocks that contain >>>
-    div.each(function(index) {
-        var jthis = $(this);
-        if (jthis.find('.gp').length > 0) {
-            var button = $('<span class="copybutton">&gt;&gt;&gt;</span>');
-            button.css(button_styles)
-            button.attr('title', hide_text);
-            button.data('hidden', 'false');
-            jthis.prepend(button);
-        }
-        // tracebacks (.gt) contain bare text elements that need to be
-        // wrapped in a span to work with .nextUntil() (see later)
-        jthis.find('pre:has(.gt)').contents().filter(function() {
-            return ((this.nodeType == 3) && (this.data.trim().length > 0));
-        }).wrap('<span>');
-    });
+    highlightedElements.forEach(el => {
+        el.style.position = "relative"
 
-    // define the behavior of the button when it's clicked
-    $('.copybutton').click(function(e){
-        e.preventDefault();
-        var button = $(this);
-        if (button.data('hidden') === 'false') {
-            // hide the code output
-            button.parent().find('.go, .gp, .gt').hide();
-            button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden');
-            button.css('text-decoration', 'line-through');
-            button.attr('title', show_text);
-            button.data('hidden', 'true');
-        } else {
-            // show the code output
-            button.parent().find('.go, .gp, .gt').show();
-            button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible');
-            button.css('text-decoration', 'none');
-            button.attr('title', hide_text);
-            button.data('hidden', 'false');
+        // if we find a console prompt (.gp), prepend the (deeply cloned) button
+        const clonedButton = button.cloneNode(true)
+        // the onclick attribute is not cloned, set it on the new element
+        clonedButton.onclick = buttonClick
+        if (el.querySelector(".gp") !== null) {
+            el.prepend(clonedButton)
         }
-    });
-});
+    })
+}
+
+if (document.readyState !== "loading") {
+    loadCopyButton()
+} else {
+    document.addEventListener("DOMContentLoaded", loadCopyButton)
+}
diff --git a/python_docs_theme/static/menu.js b/python_docs_theme/static/menu.js
index b2eabb3..e233585 100644
--- a/python_docs_theme/static/menu.js
+++ b/python_docs_theme/static/menu.js
@@ -1,55 +1,57 @@
-document.addEventListener('DOMContentLoaded', function () {
+document.addEventListener("DOMContentLoaded", function () {
 
     // Make tables responsive by wrapping them in a div and making them scrollable
-    const tables = document.querySelectorAll('table.docutils');
+    const tables = document.querySelectorAll("table.docutils")
     tables.forEach(function(table){
-        table.outerHTML = '<div class="responsive-table__container">' + table.outerHTML + '</div>'
-    });
+        table.outerHTML = '<div class="responsive-table__container">' + table.outerHTML + "</div>"
+    })
 
-    const togglerInput = document.querySelector('.toggler__input');
-    const togglerLabel = document.querySelector('.toggler__label');
-    const sideMenu = document.querySelector('.menu-wrapper');
-    const menuItems = document.querySelectorAll('.menu')
-    const doc = document.querySelector('.document');
-    const body = document.querySelector('body');
+    const togglerInput = document.querySelector(".toggler__input")
+    const togglerLabel = document.querySelector(".toggler__label")
+    const sideMenu = document.querySelector(".menu-wrapper")
+    const menuItems = document.querySelectorAll(".menu")
+    const doc = document.querySelector(".document")
+    const body = document.querySelector("body")
 
     function closeMenu() {
-        togglerInput.checked = false;
-        sideMenu.setAttribute("aria-expanded", 'false');
-        sideMenu.setAttribute('aria-hidden', 'true');
-        togglerLabel.setAttribute('aria-pressed', 'false');
-        body.style.overflow = 'visible';
+        togglerInput.checked = false
+        sideMenu.setAttribute("aria-expanded", "false")
+        sideMenu.setAttribute("aria-hidden", "true")
+        togglerLabel.setAttribute("aria-pressed", "false")
+        body.style.overflow = "visible"
     }
     function openMenu() {
-        togglerInput.checked = true;
-        sideMenu.setAttribute("aria-expanded", 'true');
-        sideMenu.setAttribute('aria-hidden', 'false');
-        togglerLabel.setAttribute('aria-pressed', 'true');
-        body.style.overflow = 'hidden';
+        togglerInput.checked = true
+        sideMenu.setAttribute("aria-expanded", "true")
+        sideMenu.setAttribute("aria-hidden", "false")
+        togglerLabel.setAttribute("aria-pressed", "true")
+        body.style.overflow = "hidden"
     }
 
     // Close menu when link on the sideMenu is clicked
-    sideMenu.addEventListener('click', function (event) {
-        let target = event.target;
-        if (target.tagName.toLowerCase() !== 'a') return;
-        closeMenu();
+    sideMenu.addEventListener("click", function (event) {
+        let target = event.target
+        if (target.tagName.toLowerCase() !== "a") {
+            return
+        }
+        closeMenu()
     })
     // Add accessibility data when sideMenu is opened/closed
-    togglerInput.addEventListener('change', function (e) {
-        togglerInput.checked ? openMenu() : closeMenu();
-    });
+    togglerInput.addEventListener("change", function (_event) {
+        togglerInput.checked ? openMenu() : closeMenu()
+    })
     // Make sideMenu links tabbable only when visible
     for(let menuItem of menuItems) {
         if(togglerInput.checked) {
-          menuItem.setAttribute('tabindex', '0');
+          menuItem.setAttribute("tabindex", "0")
         } else {
-          menuItem.setAttribute('tabindex', '-1');
+          menuItem.setAttribute("tabindex", "-1")
         }
     }
     // Close sideMenu when document body is clicked
-    doc.addEventListener('click', function () {
+    doc.addEventListener("click", function () {
         if (togglerInput.checked) {
-            closeMenu();
+            closeMenu()
         }
     })
 })
\ No newline at end of file
diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 6c141f8..5c0d394 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -104,10 +104,12 @@ div.sphinxsidebar h4 {
 }
 
 div.sphinxsidebarwrapper {
+    width: 217px;
     box-sizing: border-box;
     height: 100%;
     overflow-x: hidden;
     overflow-y: auto;
+    float: left;
 }
 
 div.sphinxsidebarwrapper > h3:first-child {
@@ -135,6 +137,33 @@ div.sphinxsidebar input[type='text'] {
     max-width: 150px;
 }
 
+#sidebarbutton {
+    /* Sphinx 4.x and earlier compat */
+    height: 100%;
+    background-color: #CCCCCC;
+    margin-left: 0;
+    color: #444444;
+    font-size: 1.2em;
+    cursor: pointer;
+    padding-top: 1px;
+    float: right;
+    display: table;
+    /* after Sphinx 4.x and earlier is dropped, only the below is needed */
+    width: 12px;
+    border-radius: 0 5px 5px 0;
+    border-left: none;
+}
+
+#sidebarbutton span {
+    /* Sphinx 4.x and earlier compat */
+    display: table-cell;
+    vertical-align: middle;
+}
+
+#sidebarbutton:hover {
+    background-color: #AAAAAA;
+}
+
 div.body {
     padding: 0 0 0 1.2em;
 }
@@ -279,6 +308,26 @@ div.genindex-jumpbox a {
     text-align: center;
 }
 
+.copybutton {
+    cursor: pointer;
+    position: absolute;
+    top: 0;
+    right: 0;
+    text-size: 75%;
+    font-family: monospace;
+    padding-left: 0.2em;
+    padding-right: 0.2em;
+    border-radius: 0 3px 0 0;
+    color: #ac9; /* follows div.body pre */
+    border-color: #ac9; /* follows div.body pre */
+    border-style: solid; /* follows div.body pre */
+    border-width: 1px; /* follows div.body pre */
+}
+
+.copybutton[data-hidden='true'] {
+    text-decoration: line-through;
+}
+
 @media (max-width: 1023px) {
     /* Body layout */
     div.body {
diff --git a/python_docs_theme/static/sidebar.js b/python_docs_theme/static/sidebar.js
index 6b5c694..70886d4 100644
--- a/python_docs_theme/static/sidebar.js
+++ b/python_docs_theme/static/sidebar.js
@@ -2,142 +2,83 @@
  * sidebar.js
  * ~~~~~~~~~~
  *
- * This script makes the Sphinx sidebar collapsible. This is a slightly
- * modified version of Sphinx's own sidebar.js.
+ * This file is functionally identical to "sidebar.js" in Sphinx 5.0.
+ * When support for Sphinx 4 and earlier is dropped from the theme,
+ * this file can be removed.
  *
- * .sphinxsidebar contains .sphinxsidebarwrapper.  This script adds in
- * .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton used to
- * collapse and expand the sidebar.
+ * This script makes the Sphinx sidebar collapsible.
  *
- * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden and the
- * width of the sidebar and the margin-left of the document are decreased.
- * When the sidebar is expanded the opposite happens.  This script saves a
- * per-browser/per-session cookie used to remember the position of the sidebar
- * among the pages.  Once the browser is closed the cookie is deleted and the
- * position reset to the default (expanded).
+ * .sphinxsidebar contains .sphinxsidebarwrapper.  This script adds
+ * in .sphinxsidebar, after .sphinxsidebarwrapper, the #sidebarbutton
+ * used to collapse and expand the sidebar.
  *
- * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
+ * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden
+ * and the width of the sidebar and the margin-left of the document
+ * are decreased. When the sidebar is expanded the opposite happens.
+ * This script saves a per-browser/per-session cookie used to
+ * remember the position of the sidebar among the pages.
+ * Once the browser is closed the cookie is deleted and the position
+ * reset to the default (expanded).
+ *
+ * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
  * :license: BSD, see LICENSE for details.
  *
  */
 
-$(function() {
+const initialiseSidebar = () => {
   // global elements used by the functions.
-  // the 'sidebarbutton' element is defined as global after its
-  // creation, in the add_sidebar_button function
-  var bodywrapper = $('.bodywrapper');
-  var sidebar = $('.sphinxsidebar');
-  var sidebarwrapper = $('.sphinxsidebarwrapper');
-
-  // original margin-left of the bodywrapper and width of the sidebar
-  // with the sidebar expanded
-  var bw_margin_expanded = bodywrapper.css('margin-left');
-  var ssb_width_expanded = sidebar.width();
-
-  // margin-left of the bodywrapper and width of the sidebar
-  // with the sidebar collapsed
-  var bw_margin_collapsed = '.8em';
-  var ssb_width_collapsed = '.8em';
-
-  // colors used by the current theme
-  var dark_color = '#AAAAAA';
-  var light_color = '#CCCCCC';
+  const bodyWrapper = document.getElementsByClassName("bodywrapper")[0]
+  const sidebar = document.getElementsByClassName("sphinxsidebar")[0]
+  const sidebarWrapper = document.getElementsByClassName("sphinxsidebarwrapper")[0]
 
-  function sidebar_is_collapsed() {
-    return sidebarwrapper.is(':not(:visible)');
+  // exit early if the document has no sidebar for some reason
+  if (typeof sidebar === "undefined") {
+    return
   }
 
-  function toggle_sidebar() {
-    if (sidebar_is_collapsed())
-      expand_sidebar();
-    else
-      collapse_sidebar();
-  }
+  // create the sidebar button element
+  const sidebarButton = document.createElement("div")
+  sidebarButton.id = "sidebarbutton"
+  // create the sidebar button arrow element
+  const sidebarArrow = document.createElement("span")
+  sidebarArrow.innerText =  "«"
+  sidebarButton.appendChild(sidebarArrow)
+  sidebar.appendChild(sidebarButton)
 
-  function collapse_sidebar() {
-    sidebarwrapper.hide();
-    sidebar.css('width', ssb_width_collapsed);
-    bodywrapper.css('margin-left', bw_margin_collapsed);
-    sidebarbutton.css({
-        'margin-left': '0',
-        'border-radius': '5px'
-    });
-    sidebarbutton.find('span').text('»');
-    sidebarbutton.attr('title', _('Expand sidebar'));
-    document.cookie = 'sidebar=collapsed';
+  const collapse_sidebar = () => {
+    bodyWrapper.style.marginLeft = ".8em"
+    sidebar.style.width = ".8em"
+    sidebarWrapper.style.display = "none"
+    sidebarArrow.innerText = "»"
+    sidebarButton.title = _("Expand sidebar")
+    window.localStorage.setItem("sidebar", "collapsed")
   }
 
-  function expand_sidebar() {
-    bodywrapper.css('margin-left', bw_margin_expanded);
-    sidebar.css('width', ssb_width_expanded);
-    sidebarwrapper.show();
-    sidebarbutton.css({
-        'margin-left': ssb_width_expanded-12,
-        'border-radius': '0 5px 5px 0'
-    });
-    sidebarbutton.find('span').text('«');
-    sidebarbutton.attr('title', _('Collapse sidebar'));
-    document.cookie = 'sidebar=expanded';
+  const expand_sidebar = () => {
+    bodyWrapper.style.marginLeft = ""
+    sidebar.style.removeProperty("width")
+    sidebarWrapper.style.display = ""
+    sidebarArrow.innerText = "«"
+    sidebarButton.title = _("Collapse sidebar")
+    window.localStorage.setItem("sidebar", "expanded")
   }
 
-  function add_sidebar_button() {
-    sidebarwrapper.css({
-        'float': 'left',
-        'margin-right': '0',
-        'width': ssb_width_expanded - 13
-    });
-    // create the button
-    sidebar.append(
-      '<div id="sidebarbutton"><span>&laquo;</span></div>'
-    );
-    var sidebarbutton = $('#sidebarbutton');
-    sidebarbutton.find('span').css({
-        'display': 'block',
-        'position': 'fixed',
-        'top': '50%'
-    });
-
-    sidebarbutton.click(toggle_sidebar);
-    sidebarbutton.attr('title', _('Collapse sidebar'));
-    sidebarbutton.css({
-        'border-radius': '0 5px 5px 0',
-        'color': '#444444',
-        'background-color': '#CCCCCC',
-        'font-size': '1.2em',
-        'cursor': 'pointer',
-        'height': '100%',
-        'padding-left': '1px',
-        'margin-left': ssb_width_expanded - 12
-    });
+  sidebarButton.addEventListener("click", () => {
+    (sidebarWrapper.style.display === "none") ? expand_sidebar() : collapse_sidebar()
+  })
 
-    sidebarbutton.hover(
-      function () {
-          $(this).css('background-color', dark_color);
-      },
-      function () {
-          $(this).css('background-color', light_color);
-      }
-    );
+  const sidebar_state = window.localStorage.getItem("sidebar")
+  if (sidebar_state === "collapsed") {
+    collapse_sidebar()
   }
-
-  function set_position_from_cookie() {
-    if (!document.cookie)
-      return;
-    var items = document.cookie.split(';');
-    for(var k=0; k<items.length; k++) {
-      var key_val = items[k].split('=');
-      var key = key_val[0];
-      if (key == 'sidebar') {
-        var value = key_val[1];
-        if ((value == 'collapsed') && (!sidebar_is_collapsed()))
-          collapse_sidebar();
-        else if ((value == 'expanded') && (sidebar_is_collapsed()))
-          expand_sidebar();
-      }
-    }
+  else if (sidebar_state === "expanded") {
+    expand_sidebar()
   }
+}
 
-  add_sidebar_button();
-  var sidebarbutton = $('#sidebarbutton');
-  set_position_from_cookie();
-});
+if (document.readyState !== "loading") {
+  initialiseSidebar()
+}
+else {
+  document.addEventListener("DOMContentLoaded", initialiseSidebar)
+}
diff --git a/python_docs_theme/theme.conf b/python_docs_theme/theme.conf
index fef7720..564c9c5 100644
--- a/python_docs_theme/theme.conf
+++ b/python_docs_theme/theme.conf
@@ -15,6 +15,7 @@ relbarlinkcolor = #444444
 sidebarbgcolor = white
 sidebartextcolor = #444444
 sidebarlinkcolor = #444444
+sidebarbtncolor = #cccccc
 bgcolor = white
 textcolor = #222222
 linkcolor = #0090c0

From 09d972d60ed24939649184aeb0a84a823cb588b8 Mon Sep 17 00:00:00 2001
From: Julien Palard <julien@palard.fr>
Date: Mon, 17 Apr 2023 11:17:51 +0200
Subject: [PATCH 033/175] Simplify release process. (#112)

---
 CONTRIBUTING.rst | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index eb499bb..c184a9c 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -10,9 +10,8 @@
   ``./venv/bin/pip install ../../python-docs-theme/dist/python-docs-theme-2021.8.tar.gz``
   then build the doc using ``make html``).
 - upload it: ``twine upload dist/*``.
-- bump version (YYYY.MM.dev) in setup.py and python_docs_theme/theme.conf
-- Commit this last bump.
-- push and push the tag (``git push && git push --tags``)
+- push the tag (``git push --tags``)
+
 
 # Makefile usage
 

From aaca238208fcc91faa6572f1b9ee5d0eba787bb8 Mon Sep 17 00:00:00 2001
From: Chris Warrick <kwpolska@gmail.com>
Date: Sat, 25 Mar 2023 15:40:36 +0100
Subject: [PATCH 034/175] Override font for .sig for consistency with other
 code blocks

---
 python_docs_theme/static/pydoctheme.css | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 5c0d394..005bbca 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -284,7 +284,8 @@ div.footer a:hover {
     color: #229;
 }
 
-dl > dt span ~ em {
+dl > dt span ~ em,
+.sig {
     font-family: ui-monospace, "Cascadia Mono", "Segoe UI Mono", "Liberation Mono", Menlo, Monaco, Consolas, monospace;
 }
 

From 0c6a8173f3f234f2f746d1f9642a7f945c31d6fd Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Thu, 20 Apr 2023 22:27:46 +0100
Subject: [PATCH 035/175] Rename ``sidebar.js`` to be a static template file

---
 python_docs_theme/static/{sidebar.js => sidebar.js_t} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename python_docs_theme/static/{sidebar.js => sidebar.js_t} (100%)

diff --git a/python_docs_theme/static/sidebar.js b/python_docs_theme/static/sidebar.js_t
similarity index 100%
rename from python_docs_theme/static/sidebar.js
rename to python_docs_theme/static/sidebar.js_t

From d5d628549a73bf527cf4559c32fa915207414b65 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+aa-turner@users.noreply.github.com>
Date: Thu, 20 Apr 2023 22:28:09 +0100
Subject: [PATCH 036/175] Don't duplicate the sidebar button on Sphinx 5 and
 newer

---
 python_docs_theme/static/sidebar.js_t | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/python_docs_theme/static/sidebar.js_t b/python_docs_theme/static/sidebar.js_t
index 70886d4..179feae 100644
--- a/python_docs_theme/static/sidebar.js_t
+++ b/python_docs_theme/static/sidebar.js_t
@@ -36,6 +36,16 @@ const initialiseSidebar = () => {
     return
   }
 
+{# Check if we need to dynamically insert the sidebar button.
+ # We prefer the ``sphinx_version_tuple`` variable, and if it is undefined we
+ # know we are running a Sphinx version older than 4.2.
+ #
+ # See: https://www.sphinx-doc.org/en/master/development/templating.html#sphinx_version_tuple
+ #}
+{% if sphinx_version_tuple is defined and sphinx_version_tuple[0] >= 5 %}
+  const sidebarButton = document.getElementById("sidebarbutton")
+  const sidebarArrow = sidebarButton.querySelector('span')
+{%  else %}
   // create the sidebar button element
   const sidebarButton = document.createElement("div")
   sidebarButton.id = "sidebarbutton"
@@ -44,6 +54,7 @@ const initialiseSidebar = () => {
   sidebarArrow.innerText =  "«"
   sidebarButton.appendChild(sidebarArrow)
   sidebar.appendChild(sidebarButton)
+{% endif %}
 
   const collapse_sidebar = () => {
     bodyWrapper.style.marginLeft = ".8em"

From d39c3112a89023492d9f0efa9bdf7a51ca7f436d Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Date: Thu, 20 Apr 2023 22:50:42 +0100
Subject: [PATCH 037/175] whitespace

---
 python_docs_theme/static/sidebar.js_t | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python_docs_theme/static/sidebar.js_t b/python_docs_theme/static/sidebar.js_t
index 179feae..a08aa0f 100644
--- a/python_docs_theme/static/sidebar.js_t
+++ b/python_docs_theme/static/sidebar.js_t
@@ -45,7 +45,7 @@ const initialiseSidebar = () => {
 {% if sphinx_version_tuple is defined and sphinx_version_tuple[0] >= 5 %}
   const sidebarButton = document.getElementById("sidebarbutton")
   const sidebarArrow = sidebarButton.querySelector('span')
-{%  else %}
+{% else %}
   // create the sidebar button element
   const sidebarButton = document.createElement("div")
   sidebarButton.id = "sidebarbutton"

From cfa17802db70ece5b67c0a2c97f59a511afbb899 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Fri, 28 Apr 2023 21:50:16 +0300
Subject: [PATCH 038/175] Dark mode: add class to invert image brightness

---
 python_docs_theme/static/pydoctheme_dark.css | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index 4aa657b..7882a67 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -120,3 +120,7 @@ div.note {
 .nav-content {
     background-color: black;
 }
+
+img.invert-in-dark-mode {
+    filter: invert(1) hue-rotate(.5turn);
+}

From 4dbc102a556c520b10fc387821967e54dee77654 Mon Sep 17 00:00:00 2001
From: Julien Palard <julien@palard.fr>
Date: Mon, 17 Apr 2023 11:36:05 +0200
Subject: [PATCH 039/175] Releasing v2023.5

---
 CHANGELOG.rst  | 15 +++++++++++++++
 pyproject.toml |  2 +-
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index d06040d..1d0d8a0 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,6 +2,21 @@
 Changelog
 =========
 
+`2023.5 <https://github.com/python/python-docs-theme/releases/tag/v2023.5>`_
+----------------------------------------------------------------------------
+
+- Add a dark theme. (#44)
+  Contributed by Nils K
+- Fix: Remove searchbox id from form. (fixes #117)
+  Contributed by Nils K
+- Update ``python-docs-theme`` to work with Sphinx 5 & 6. (#99 & #127)
+  Contributed by Adam Turner
+- Override font for ``.sig`` for consistency with other code blocks. (#121)
+  Contributed by Chris Warrick
+- Dark mode: add class to invert image brightness. (#128)
+  Contributed by Hugo van Kemenade
+
+
 `2023.3.1 <https://github.com/python/python-docs-theme/releases/tag/v2023.3.1>`_
 --------------------------------------------------------------------------------
 
diff --git a/pyproject.toml b/pyproject.toml
index f0296e5..5f93a6b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,7 +5,7 @@ build-backend = "flit_core.buildapi"
 # project metadata
 [project]
 name = "python-docs-theme"
-version = "2023.3.1"
+version = "2023.5"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.rst"
 urls.Code = "https://github.com/python/python-docs-theme"

From 007b23a4a640db11aaf27df0e36b785231621c98 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Fri, 7 Jul 2023 17:46:31 +0300
Subject: [PATCH 040/175] Dark mode: fix contrast for C++ specific styling

---
 python_docs_theme/static/pydoctheme_dark.css | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index 7882a67..7056fba 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -124,3 +124,12 @@ div.note {
 img.invert-in-dark-mode {
     filter: invert(1) hue-rotate(.5turn);
 }
+
+/* -- object description styles --------------------------------------------- */
+
+/* C++ specific styling */
+
+.sig.c   .k, .sig.c   .kt,
+.sig.cpp .k, .sig.cpp .kt {
+    color: #5283ff;
+}

From be0cec8323e8fa6c64cb24d8145fbc6f28771690 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sat, 8 Jul 2023 11:30:03 +0300
Subject: [PATCH 041/175] Comment why we're changing the colour

---
 python_docs_theme/static/pydoctheme_dark.css | 1 +
 1 file changed, 1 insertion(+)

diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index 7056fba..8abce7d 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -129,6 +129,7 @@ img.invert-in-dark-mode {
 
 /* C++ specific styling */
 
+/* Override Sphinx's basic.css to fix colour contrast */
 .sig.c   .k, .sig.c   .kt,
 .sig.cpp .k, .sig.cpp .kt {
     color: #5283ff;

From ef296e2dca4784672d858af98868392e8f0b6302 Mon Sep 17 00:00:00 2001
From: Pradyun Gedam <pradyunsg@gmail.com>
Date: Wed, 26 Jul 2023 19:58:21 +0100
Subject: [PATCH 042/175] Do not append asset hashes on Sphinx 7.1+

The relevant functionality has been added to Sphinx natively.
---
 python_docs_theme/__init__.py | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py
index 68bb9e3..4b53467 100644
--- a/python_docs_theme/__init__.py
+++ b/python_docs_theme/__init__.py
@@ -4,6 +4,7 @@
 from pathlib import Path
 from typing import Any, Dict, List
 
+import sphinx
 import sphinx.application
 from sphinx.builders.html import StandaloneHTMLBuilder
 
@@ -20,6 +21,11 @@ def _asset_hash(path: str) -> str:
 
 
 def _add_asset_hashes(static: List[str], add_digest_to: List[str]) -> None:
+    if sphinx.version_info >= (7, 1):
+        # https://github.com/sphinx-doc/sphinx/pull/11415 added the relevant
+        # functionality to Sphinx, so we don't need to do anything.
+        return
+
     for asset in add_digest_to:
         index = static.index(asset)
         static[index].filename = _asset_hash(asset)  # type: ignore

From c7958dac93a1f22ad274703e0408512ae6e6f936 Mon Sep 17 00:00:00 2001
From: Pradyun Gedam <pradyunsg@gmail.com>
Date: Wed, 26 Jul 2023 22:13:42 +0100
Subject: [PATCH 043/175] Rework based on suggested changes

Sphinx 7.1 added the relevant functionality natively.
---
 python_docs_theme/__init__.py | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py
index 4b53467..0857b5f 100644
--- a/python_docs_theme/__init__.py
+++ b/python_docs_theme/__init__.py
@@ -4,7 +4,6 @@
 from pathlib import Path
 from typing import Any, Dict, List
 
-import sphinx
 import sphinx.application
 from sphinx.builders.html import StandaloneHTMLBuilder
 
@@ -21,11 +20,6 @@ def _asset_hash(path: str) -> str:
 
 
 def _add_asset_hashes(static: List[str], add_digest_to: List[str]) -> None:
-    if sphinx.version_info >= (7, 1):
-        # https://github.com/sphinx-doc/sphinx/pull/11415 added the relevant
-        # functionality to Sphinx, so we don't need to do anything.
-        return
-
     for asset in add_digest_to:
         index = static.index(asset)
         static[index].filename = _asset_hash(asset)  # type: ignore
@@ -43,7 +37,7 @@ def _html_page_context(
 
     assert isinstance(app.builder, StandaloneHTMLBuilder)
 
-    if sphinx.version_info >= (4,) and "css_files" in context:
+    if (4,) <= sphinx.version_info < (7, 1) and "css_files" in context:
         if "_static/pydoctheme.css" not in context["css_files"]:
             raise ValueError(
                 "This documentation is not using `pydoctheme.css` as the stylesheet. "

From cd41ccd9ed53a8583be3cd4991013d753d8c55dd Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Thu, 27 Jul 2023 13:45:49 +0300
Subject: [PATCH 044/175] Sphinx 6.2 fix: add nav.contents where that div.topic
 is used

---
 python_docs_theme/static/pydoctheme_dark.css | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index 7882a67..8bdddf6 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -104,7 +104,8 @@ div.warning {
 }
 
 div.topic,
-div.note {
+div.note,
+nav.contents {
     background-color: rgba(255, 255, 255, 0.1);
     border-color: currentColor;
 }

From 6787cd68befbef6a7be35f53fd40dfdd0263e698 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Thu, 27 Jul 2023 14:10:40 +0300
Subject: [PATCH 045/175] Don't let long code literals extend beyond the right
 side of the screen

---
 python_docs_theme/static/pydoctheme.css | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 005bbca..68aad06 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -368,6 +368,11 @@ div.genindex-jumpbox a {
     body {
         margin-top: 40px;
     }
+    /* Don't let long code literals extend beyond the right side of the screen */
+    span.pre {
+        overflow-wrap: break-word;
+        white-space: unset;
+    }
 
     /* Top navigation bar */
     .mobile-nav {

From c6542c738634ffba38d7b1b137c62d356aaa686c Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Thu, 27 Jul 2023 14:11:58 +0300
Subject: [PATCH 046/175] Test 3.12 branch, now main is 3.13

---
 .github/workflows/tests.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index cec17c3..86e5a42 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -11,7 +11,7 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        branch: [origin/main, 3.11, '3.10', 3.9, 3.8, 3.7]
+        branch: [origin/main, 3.12, 3.11, '3.10', 3.9, 3.8, 3.7]
     steps:
       - uses: actions/checkout@v3
       - uses: actions/setup-python@v4

From b61860b2dd578b1e19c47fe4244b9b38c6c3b9c5 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Thu, 27 Jul 2023 14:38:03 +0300
Subject: [PATCH 047/175] Remove EOL 3.7

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
---
 .github/workflows/tests.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 86e5a42..fa5ed35 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -11,7 +11,7 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        branch: [origin/main, 3.12, 3.11, '3.10', 3.9, 3.8, 3.7]
+        branch: [origin/main, 3.12, 3.11, '3.10', 3.9, 3.8]
     steps:
       - uses: actions/checkout@v3
       - uses: actions/setup-python@v4

From 44e62ddbd3bb3bbbe31a25249133d74b82ad6f67 Mon Sep 17 00:00:00 2001
From: Mike Fiedler <miketheman@gmail.com>
Date: Thu, 27 Jul 2023 11:17:12 -0400
Subject: [PATCH 048/175] chore: remove unnecessary responsive layout

The CSS in the base template was updated to include this directive in #7695
and released in sphinx v3.1.0.

The original implementation was in #46, prior to the basic theme
including it, and now we have the same meta tag duplicated.

Remove the block, and reduce the duplication.

Signed-off-by: Mike Fiedler <miketheman@gmail.com>
---
 python_docs_theme/layout.html | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index b4502ba..08e41df 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -82,11 +82,6 @@ <h3>{{ _('Navigation') }}</h3>
     {{ super() }}
 {%- endblock -%}
 
-{%- block css -%}
-    <meta name="viewport" content="width=device-width, initial-scale=1.0">
-    {{ super() }}
-{%- endblock -%}
-
 {%- block body_tag %}
 {{ super() }}
 {%- if builder != 'htmlhelp' %}

From 788fee715f2e0a4be29c7d4ac8d10c967c8e96f7 Mon Sep 17 00:00:00 2001
From: Mike Fiedler <miketheman@gmail.com>
Date: Thu, 27 Jul 2023 11:57:20 -0400
Subject: [PATCH 049/175] fix: override correct tag

When the template was made responsive, the choice was made to override
the `body_tag` fragment.
The `body_tag` block is a literal `<body>` which allows the theme developer
to set properties on the `body` tag.
See: https://github.com/sphinx-doc/sphinx/pull/4140

Instead, use the `document` block as documented.
https://www.sphinx-doc.org/en/master/development/templating.html#blocks

Overriding the correct block places the `mobile-nav` section _after_ the
majority of the other HTML parts, which enables the correct function of
the `/` keyboard shortcut.

Resolves #130
Closes #131
Closes #135

Signed-off-by: Mike Fiedler <miketheman@gmail.com>
---
 python_docs_theme/layout.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index 08e41df..f830491 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -82,7 +82,7 @@ <h3>{{ _('Navigation') }}</h3>
     {{ super() }}
 {%- endblock -%}
 
-{%- block body_tag %}
+{%- block document %}
 {{ super() }}
 {%- if builder != 'htmlhelp' %}
 <div class="mobile-nav">

From b2bd51807f28c208771f7ffdb59e8115ab7110ed Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sun, 30 Jul 2023 12:16:52 +0300
Subject: [PATCH 050/175] Apply no-wrap to container

---
 python_docs_theme/static/pydoctheme.css | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 68aad06..ce032f1 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -84,6 +84,13 @@ form.inline-search input[type='submit'] {
 
 div.document {
     display: flex;
+    /* Don't let long code literals extend beyond the right side of the screen */
+    overflow-wrap: break-word;
+}
+
+/* Don't let long code literals extend beyond the right side of the screen */
+span.pre {
+    white-space: unset;
 }
 
 div.sphinxsidebar {
@@ -368,11 +375,6 @@ div.genindex-jumpbox a {
     body {
         margin-top: 40px;
     }
-    /* Don't let long code literals extend beyond the right side of the screen */
-    span.pre {
-        overflow-wrap: break-word;
-        white-space: unset;
-    }
 
     /* Top navigation bar */
     .mobile-nav {

From 83d1b698bcc18c1c5015ecf87a3ef702ca7091c4 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sun, 30 Jul 2023 17:42:41 +0300
Subject: [PATCH 051/175] Add changelog for 2023.7

---
 CHANGELOG.rst | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 1d0d8a0..2e32082 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,6 +2,22 @@
 Changelog
 =========
 
+`2023.7 <https://github.com/python/python-docs-theme/releases/tag/v2023.7>`_
+----------------------------------------------------------------------------
+
+- Do not append asset hashes on Sphinx 7.1+ (#137)
+   Contributed by Pradyun Gedam
+- Use correct block, enable built-in slash keypress (#141)
+   Contributed by Mike Fiedler
+- Sphinx 6.2 fix: add ``nav.contents`` where that ``div.topic`` is used (#138)
+   Contributed by Hugo van Kemenade
+- Dark mode: fix contrast for C++ specific styling (#133)
+  Contributed by Hugo van Kemenade
+- Don't let long code literals extend beyond the right side of the screen (#139)
+   Contributed by Hugo van Kemenade
+- Test 3.12 branch, now `main` is 3.13 (#140)
+   Contributed by Hugo van Kemenade
+
 `2023.5 <https://github.com/python/python-docs-theme/releases/tag/v2023.5>`_
 ----------------------------------------------------------------------------
 

From 17dd77dc44f612becbaf955fcd3004115e1206cb Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sun, 30 Jul 2023 17:43:21 +0300
Subject: [PATCH 052/175] Consistent formatting

---
 CHANGELOG.rst | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 2e32082..aa53870 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -22,15 +22,15 @@ Changelog
 ----------------------------------------------------------------------------
 
 - Add a dark theme. (#44)
-  Contributed by Nils K
+   Contributed by Nils K
 - Fix: Remove searchbox id from form. (fixes #117)
-  Contributed by Nils K
+   Contributed by Nils K
 - Update ``python-docs-theme`` to work with Sphinx 5 & 6. (#99 & #127)
-  Contributed by Adam Turner
+   Contributed by Adam Turner
 - Override font for ``.sig`` for consistency with other code blocks. (#121)
-  Contributed by Chris Warrick
+   Contributed by Chris Warrick
 - Dark mode: add class to invert image brightness. (#128)
-  Contributed by Hugo van Kemenade
+   Contributed by Hugo van Kemenade
 
 
 `2023.3.1 <https://github.com/python/python-docs-theme/releases/tag/v2023.3.1>`_
@@ -60,27 +60,27 @@ Changelog
 -----------------------------------------------------------------------------------
 
 - Fix monospace again, on buggy Google Chrome (#87)
-  Contributed by Tushar Sadhwani
+   Contributed by Tushar Sadhwani
 
 
 `2021.11 <https://github.com/python/python-docs-theme/releases/tag/v2021.11>`_
 -------------------------------------------------------------------------------
 
 - Fix monospace on buggy Google Chrome (#85)
-  Contributed by Tushar Sadhwani
+   Contributed by Tushar Sadhwani
 
 
 `2021.8 <https://github.com/python/python-docs-theme/releases/tag/v2021.8>`_
 ------------------------------------------------------------------------------
 
 - Add the copyright_url variable in the theme (#67)
-  Contributed by jablonskidev
+   Contributed by jablonskidev
 - Improve readability (#79)
-  Contributed by Olga Bulat
+   Contributed by Olga Bulat
 - Remove #searchbox on mobile to fix a layout bug (#76)
-  Contributed by Olga Bulat
+   Contributed by Olga Bulat
 - Fix the appearance of version/language selects (#74)
-  Contributed by Olga Bulat
+   Contributed by Olga Bulat
 
 
 `2021.5 <https://github.com/python/python-docs-theme/releases/tag/v2021.5>`_

From 7e0b2e45bde90ad6a452526a9b97b16db4c90a54 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sun, 30 Jul 2023 17:49:55 +0300
Subject: [PATCH 053/175] Bump version to 2023.7

---
 pyproject.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pyproject.toml b/pyproject.toml
index 5f93a6b..b4179d1 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,7 +5,7 @@ build-backend = "flit_core.buildapi"
 # project metadata
 [project]
 name = "python-docs-theme"
-version = "2023.5"
+version = "2023.7"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.rst"
 urls.Code = "https://github.com/python/python-docs-theme"

From ac97b7664325fa1ce5dc1ebcf7fb71a3ada7ea24 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sun, 30 Jul 2023 22:23:06 +0300
Subject: [PATCH 054/175] Improve wording

Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
---
 CHANGELOG.rst | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index aa53870..b275b76 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -5,17 +5,17 @@ Changelog
 `2023.7 <https://github.com/python/python-docs-theme/releases/tag/v2023.7>`_
 ----------------------------------------------------------------------------
 
-- Do not append asset hashes on Sphinx 7.1+ (#137)
+- Fix compatability with Sphinx 7.1 (#137)
    Contributed by Pradyun Gedam
-- Use correct block, enable built-in slash keypress (#141)
+- Enable the slash keypress to focus the search field (#141)
    Contributed by Mike Fiedler
-- Sphinx 6.2 fix: add ``nav.contents`` where that ``div.topic`` is used (#138)
+- Sphinx 6.2 fix: add ``nav.contents`` where ``div.topic`` is used (#138)
    Contributed by Hugo van Kemenade
 - Dark mode: fix contrast for C++ specific styling (#133)
   Contributed by Hugo van Kemenade
 - Don't let long code literals extend beyond the right side of the screen (#139)
    Contributed by Hugo van Kemenade
-- Test 3.12 branch, now `main` is 3.13 (#140)
+- Test with Python 3.12 (#140)
    Contributed by Hugo van Kemenade
 
 `2023.5 <https://github.com/python/python-docs-theme/releases/tag/v2023.5>`_

From 891819101a4c16632bd753512ea87ef7ef5e3cb2 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sun, 13 Aug 2023 23:13:14 -0600
Subject: [PATCH 055/175] Revert "Use correct block, enable built-in slash
 keypress"

---
 python_docs_theme/layout.html | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index f830491..b4502ba 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -82,7 +82,12 @@ <h3>{{ _('Navigation') }}</h3>
     {{ super() }}
 {%- endblock -%}
 
-{%- block document %}
+{%- block css -%}
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    {{ super() }}
+{%- endblock -%}
+
+{%- block body_tag %}
 {{ super() }}
 {%- if builder != 'htmlhelp' %}
 <div class="mobile-nav">

From fc8a8bd0d389aaa8696f3dca6f4a3b118ee5e01f Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Mon, 14 Aug 2023 08:35:45 +0300
Subject: [PATCH 056/175] Bump version to allow CI conflict resolution due to
 https://github.com/python/cpython/pull/107666

---
 pyproject.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pyproject.toml b/pyproject.toml
index b4179d1..4042fd5 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,7 +5,7 @@ build-backend = "flit_core.buildapi"
 # project metadata
 [project]
 name = "python-docs-theme"
-version = "2023.7"
+version = "2023.8"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.rst"
 urls.Code = "https://github.com/python/python-docs-theme"

From d766a12d3269ab3624178f07cc4493133345da12 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sun, 20 Aug 2023 13:22:35 +0300
Subject: [PATCH 057/175] Add Python 3.12 classifier

---
 pyproject.toml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/pyproject.toml b/pyproject.toml
index b4179d1..9461479 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -30,6 +30,7 @@ classifiers = [
     "Programming Language :: Python :: 3.9",
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
+    "Programming Language :: Python :: 3.12",
 ]
 
 [[project.authors]]

From 14201581d8fe396d270defa93599f133841b379c Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sun, 20 Aug 2023 04:27:19 -0600
Subject: [PATCH 058/175] Add Python 3.13 classifier

Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
---
 pyproject.toml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/pyproject.toml b/pyproject.toml
index 9461479..949cb25 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -31,6 +31,7 @@ classifiers = [
     "Programming Language :: Python :: 3.10",
     "Programming Language :: Python :: 3.11",
     "Programming Language :: Python :: 3.12",
+    "Programming Language :: Python :: 3.13",
 ]
 
 [[project.authors]]

From 1ea6d1e6fe1c21b1fb1e16671dc6775cf0e018f2 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Mon, 14 Aug 2023 08:35:45 +0300
Subject: [PATCH 059/175] Bump version to allow CI conflict resolution due to
 https://github.com/python/cpython/pull/107666

---
 pyproject.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pyproject.toml b/pyproject.toml
index 949cb25..9be4a24 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,7 +5,7 @@ build-backend = "flit_core.buildapi"
 # project metadata
 [project]
 name = "python-docs-theme"
-version = "2023.7"
+version = "2023.8"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.rst"
 urls.Code = "https://github.com/python/python-docs-theme"

From 3f1b3b3b100c24c3f5e59e296ad046cdb0b0c082 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sun, 20 Aug 2023 13:16:00 +0300
Subject: [PATCH 060/175] Build & maybe upload PyPI package via trusted
 publishing

---
 .github/workflows/pypi-package.yml | 67 ++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)
 create mode 100644 .github/workflows/pypi-package.yml

diff --git a/.github/workflows/pypi-package.yml b/.github/workflows/pypi-package.yml
new file mode 100644
index 0000000..e482641
--- /dev/null
+++ b/.github/workflows/pypi-package.yml
@@ -0,0 +1,67 @@
+---
+name: Build & maybe upload PyPI package
+
+on:
+  push:
+    branches: [main]
+    tags: ["*"]
+  pull_request:
+    branches: [main]
+  release:
+    types:
+      - published
+  workflow_dispatch:
+
+permissions:
+  contents: read
+  id-token: write
+
+jobs:
+  # Always build & lint package.
+  build-package:
+    name: Build & verify package
+    runs-on: ubuntu-latest
+
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+
+      - uses: hynek/build-and-inspect-python-package@v1
+
+  # Upload to Test PyPI on every commit on main.
+  release-test-pypi:
+    name: Publish in-dev package to test.pypi.org
+    if: github.repository_owner == 'python' && github.event_name == 'push' && github.ref == 'refs/heads/main'
+    runs-on: ubuntu-latest
+    needs: build-package
+
+    steps:
+      - name: Download packages built by build-and-inspect-python-package
+        uses: actions/download-artifact@v3
+        with:
+          name: Packages
+          path: dist
+
+      - name: Upload package to Test PyPI
+        uses: pypa/gh-action-pypi-publish@release/v1
+        with:
+          repository-url: https://test.pypi.org/legacy/
+
+  # Upload to real PyPI on GitHub Releases.
+  release-pypi:
+    name: Publish released package to pypi.org
+    environment: release-pypi
+    if: github.repository_owner == 'python' && github.event.action == 'published'
+    runs-on: ubuntu-latest
+    needs: build-package
+
+    steps:
+      - name: Download packages built by build-and-inspect-python-package
+        uses: actions/download-artifact@v3
+        with:
+          name: Packages
+          path: dist
+
+      - name: Upload package to PyPI
+        uses: pypa/gh-action-pypi-publish@release/v1

From 1e4b09e2a64d911088816c6fde937f10dabbf1a6 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Mon, 21 Aug 2023 08:29:20 +0300
Subject: [PATCH 061/175] Apply suggestions from code review

Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
---
 .github/workflows/pypi-package.yml | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/.github/workflows/pypi-package.yml b/.github/workflows/pypi-package.yml
index e482641..6703e19 100644
--- a/.github/workflows/pypi-package.yml
+++ b/.github/workflows/pypi-package.yml
@@ -1,4 +1,3 @@
----
 name: Build & maybe upload PyPI package
 
 on:
@@ -50,7 +49,7 @@ jobs:
 
   # Upload to real PyPI on GitHub Releases.
   release-pypi:
-    name: Publish released package to pypi.org
+    name: Publish to PyPI
     environment: release-pypi
     if: github.repository_owner == 'python' && github.event.action == 'published'
     runs-on: ubuntu-latest

From a1740d85a91fd896c5f3e48fe48c7bdc42a81954 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Mon, 21 Aug 2023 08:51:56 +0300
Subject: [PATCH 062/175] Tighten permissions

---
 .github/workflows/pypi-package.yml | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/pypi-package.yml b/.github/workflows/pypi-package.yml
index 6703e19..4b05fe6 100644
--- a/.github/workflows/pypi-package.yml
+++ b/.github/workflows/pypi-package.yml
@@ -13,7 +13,6 @@ on:
 
 permissions:
   contents: read
-  id-token: write
 
 jobs:
   # Always build & lint package.
@@ -35,6 +34,9 @@ jobs:
     runs-on: ubuntu-latest
     needs: build-package
 
+    permissions:
+      id-token: write
+
     steps:
       - name: Download packages built by build-and-inspect-python-package
         uses: actions/download-artifact@v3
@@ -55,6 +57,9 @@ jobs:
     runs-on: ubuntu-latest
     needs: build-package
 
+    permissions:
+      id-token: write
+
     steps:
       - name: Download packages built by build-and-inspect-python-package
         uses: actions/download-artifact@v3

From 5c5e94d96fa3a328e7c004efe173b10489fbce1e Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Mon, 21 Aug 2023 08:59:06 +0300
Subject: [PATCH 063/175] Don't fetch all history

---
 .github/workflows/pypi-package.yml | 2 --
 1 file changed, 2 deletions(-)

diff --git a/.github/workflows/pypi-package.yml b/.github/workflows/pypi-package.yml
index 4b05fe6..4f6fd2b 100644
--- a/.github/workflows/pypi-package.yml
+++ b/.github/workflows/pypi-package.yml
@@ -22,8 +22,6 @@ jobs:
 
     steps:
       - uses: actions/checkout@v3
-        with:
-          fetch-depth: 0
 
       - uses: hynek/build-and-inspect-python-package@v1
 

From 6d82be0f1d0bb044105ccdf31b0b2a0871f2e8db Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Mon, 21 Aug 2023 17:39:34 +0300
Subject: [PATCH 064/175] Don't upload to TestPyPI

---
 .github/workflows/pypi-package.yml | 25 +------------------------
 1 file changed, 1 insertion(+), 24 deletions(-)

diff --git a/.github/workflows/pypi-package.yml b/.github/workflows/pypi-package.yml
index 4f6fd2b..926dacd 100644
--- a/.github/workflows/pypi-package.yml
+++ b/.github/workflows/pypi-package.yml
@@ -2,10 +2,9 @@ name: Build & maybe upload PyPI package
 
 on:
   push:
-    branches: [main]
+    branches:
     tags: ["*"]
   pull_request:
-    branches: [main]
   release:
     types:
       - published
@@ -25,28 +24,6 @@ jobs:
 
       - uses: hynek/build-and-inspect-python-package@v1
 
-  # Upload to Test PyPI on every commit on main.
-  release-test-pypi:
-    name: Publish in-dev package to test.pypi.org
-    if: github.repository_owner == 'python' && github.event_name == 'push' && github.ref == 'refs/heads/main'
-    runs-on: ubuntu-latest
-    needs: build-package
-
-    permissions:
-      id-token: write
-
-    steps:
-      - name: Download packages built by build-and-inspect-python-package
-        uses: actions/download-artifact@v3
-        with:
-          name: Packages
-          path: dist
-
-      - name: Upload package to Test PyPI
-        uses: pypa/gh-action-pypi-publish@release/v1
-        with:
-          repository-url: https://test.pypi.org/legacy/
-
   # Upload to real PyPI on GitHub Releases.
   release-pypi:
     name: Publish to PyPI

From c39a9f14456cfe2caabe676ef0863913773da358 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Thu, 24 Aug 2023 21:20:16 +0300
Subject: [PATCH 065/175] Dark mode: Also give aside.topic a dark background

---
 python_docs_theme/static/pydoctheme_dark.css | 1 +
 1 file changed, 1 insertion(+)

diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index 49a29e3..46a2c7a 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -103,6 +103,7 @@ div.warning {
     background-color: rgba(255, 0, 0, 0.5);
 }
 
+aside.topic,
 div.topic,
 div.note,
 nav.contents {

From c72797c54576273c17144d5c7364498f6b828b1e Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Fri, 25 Aug 2023 09:05:09 +0300
Subject: [PATCH 066/175] Prepare 2023.8 release

---
 CHANGELOG.rst | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index b275b76..cbf71ce 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,6 +2,16 @@
 Changelog
 =========
 
+`2023.8 <https://github.com/python/python-docs-theme/releases/tag/v2023.8>`_
+----------------------------------------------------------------------------
+
+- Add Python 3.12 and 3.13 classifiers (#147)
+    Contributed by Hugo van Kemenade
+- Dark mode: Also give aside.topic a dark background (#150)
+   Contributed by Hugo van Kemenade
+- Revert "Enable the slash keypress to focus the search field (#141)" (#146)
+   Contributed by Hugo van Kemenade
+
 `2023.7 <https://github.com/python/python-docs-theme/releases/tag/v2023.7>`_
 ----------------------------------------------------------------------------
 

From a36aa936add2de3d763d561af52c834184a0ea9c Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Fri, 25 Aug 2023 00:23:47 -0600
Subject: [PATCH 067/175] Fix whitespace

Co-authored-by: Ezio Melotti <ezio.melotti@gmail.com>
---
 CHANGELOG.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index cbf71ce..5f6181f 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -6,7 +6,7 @@ Changelog
 ----------------------------------------------------------------------------
 
 - Add Python 3.12 and 3.13 classifiers (#147)
-    Contributed by Hugo van Kemenade
+   Contributed by Hugo van Kemenade
 - Dark mode: Also give aside.topic a dark background (#150)
    Contributed by Hugo van Kemenade
 - Revert "Enable the slash keypress to focus the search field (#141)" (#146)

From 8afde74e973b22b06849ea3b46cccf2f7ee5359d Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Fri, 25 Aug 2023 10:21:01 -0600
Subject: [PATCH 068/175] Improve wording

Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
---
 CHANGELOG.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 5f6181f..ae95309 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -9,7 +9,7 @@ Changelog
    Contributed by Hugo van Kemenade
 - Dark mode: Also give aside.topic a dark background (#150)
    Contributed by Hugo van Kemenade
-- Revert "Enable the slash keypress to focus the search field (#141)" (#146)
+- Restore the menu on mobile devices (inadvertently broken in 2023.7) (#146)
    Contributed by Hugo van Kemenade
 
 `2023.7 <https://github.com/python/python-docs-theme/releases/tag/v2023.7>`_

From f498f5548bdd5f6ea5f7b9fbd4ce17742c4c3a65 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Fri, 25 Aug 2023 19:22:07 +0300
Subject: [PATCH 069/175] Fix whitespace

---
 CHANGELOG.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index ae95309..cbf57d4 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -22,7 +22,7 @@ Changelog
 - Sphinx 6.2 fix: add ``nav.contents`` where ``div.topic`` is used (#138)
    Contributed by Hugo van Kemenade
 - Dark mode: fix contrast for C++ specific styling (#133)
-  Contributed by Hugo van Kemenade
+   Contributed by Hugo van Kemenade
 - Don't let long code literals extend beyond the right side of the screen (#139)
    Contributed by Hugo van Kemenade
 - Test with Python 3.12 (#140)

From 719222f002b0642b3553a5515c1cf8bbf08903fb Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sat, 26 Aug 2023 11:49:22 +0300
Subject: [PATCH 070/175] Simplify action triggers

---
 .github/workflows/pypi-package.yml | 2 --
 1 file changed, 2 deletions(-)

diff --git a/.github/workflows/pypi-package.yml b/.github/workflows/pypi-package.yml
index 926dacd..c4913eb 100644
--- a/.github/workflows/pypi-package.yml
+++ b/.github/workflows/pypi-package.yml
@@ -2,8 +2,6 @@ name: Build & maybe upload PyPI package
 
 on:
   push:
-    branches:
-    tags: ["*"]
   pull_request:
   release:
     types:

From f15aa6da50f62d10af02f6528deb0b703a95daf1 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sat, 26 Aug 2023 18:22:28 +0300
Subject: [PATCH 071/175] Comment when the release-pypi step is run

---
 .github/workflows/pypi-package.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/workflows/pypi-package.yml b/.github/workflows/pypi-package.yml
index c4913eb..2b8f8aa 100644
--- a/.github/workflows/pypi-package.yml
+++ b/.github/workflows/pypi-package.yml
@@ -26,6 +26,7 @@ jobs:
   release-pypi:
     name: Publish to PyPI
     environment: release-pypi
+    # Only run for published releases.
     if: github.repository_owner == 'python' && github.event.action == 'published'
     runs-on: ubuntu-latest
     needs: build-package

From 23f0b4296f141dd73789c4b8b3b757b6e03c254d Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Thu, 15 Jun 2023 17:40:02 +0300
Subject: [PATCH 072/175] Focus search box when pressing slash

---
 python_docs_theme/layout.html            |  3 ++-
 python_docs_theme/static/search-focus.js | 10 ++++++++++
 2 files changed, 12 insertions(+), 1 deletion(-)
 create mode 100644 python_docs_theme/static/search-focus.js

diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index b4502ba..82b7ef4 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -48,7 +48,7 @@ <h3>{{ _('Navigation') }}</h3>
     {%- if builder != "htmlhelp" %}
     <div class="inline-search" role="search">
         <form class="inline-search" action="{{ pathto('search') }}" method="get">
-          <input placeholder="{{ _('Quick search') }}" aria-label="{{ _('Quick search') }}" type="search" name="q" />
+          <input placeholder="{{ _('Quick search') }}" aria-label="{{ _('Quick search') }}" type="search" name="q" id="search-box" />
           <input type="submit" value="{{ _('Go') }}" />
         </form>
     </div>
@@ -76,6 +76,7 @@ <h3>{{ _('Navigation') }}</h3>
         {%- if not embedded %}
             <script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>
             <script type="text/javascript" src="{{ pathto('_static/menu.js', 1) }}"></script>
+            <script type="text/javascript" src="{{ pathto('_static/search-focus.js', 1) }}"></script>
             <script type="text/javascript" src="{{ pathto('_static/themetoggle.js', 1) }}"></script>
         {%- endif -%}
     {%- endif -%}
diff --git a/python_docs_theme/static/search-focus.js b/python_docs_theme/static/search-focus.js
new file mode 100644
index 0000000..d6f2826
--- /dev/null
+++ b/python_docs_theme/static/search-focus.js
@@ -0,0 +1,10 @@
+document.addEventListener('keydown', function(event) {
+  if (event.key === '/') {
+     // Prevent "/" from being entered in the search box
+    event.preventDefault();
+
+    // Set the focus on the search box
+    let searchBox = document.getElementById('search-box');
+    searchBox.focus();
+  }
+});

From 3f27d34ed682e2fce8dcc56b97bcc9557fb54bbe Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Fri, 16 Jun 2023 00:52:35 +0300
Subject: [PATCH 073/175] Allow / to be entered into search box, don't focus if
 edit already focused

---
 python_docs_theme/static/search-focus.js | 21 ++++++++++++++++-----
 1 file changed, 16 insertions(+), 5 deletions(-)

diff --git a/python_docs_theme/static/search-focus.js b/python_docs_theme/static/search-focus.js
index d6f2826..aa5b42f 100644
--- a/python_docs_theme/static/search-focus.js
+++ b/python_docs_theme/static/search-focus.js
@@ -1,10 +1,21 @@
+function isInputFocused() {
+  const activeElement = document.activeElement;
+  return (
+    activeElement.tagName === 'INPUT' ||
+    activeElement.tagName === 'TEXTAREA' ||
+    activeElement.isContentEditable
+  );
+}
+
 document.addEventListener('keydown', function(event) {
   if (event.key === '/') {
-     // Prevent "/" from being entered in the search box
-    event.preventDefault();
+    if (!isInputFocused()) {
+      // Prevent "/" from being entered in the search box
+      event.preventDefault();
 
-    // Set the focus on the search box
-    let searchBox = document.getElementById('search-box');
-    searchBox.focus();
+      // Set the focus on the search box
+      const searchBox = document.getElementById('search-box');
+      searchBox.focus();
+    }
   }
 });

From d389288cca97c3f12718b09ceff5b453f5e71329 Mon Sep 17 00:00:00 2001
From: Mariatta <Mariatta@users.noreply.github.com>
Date: Thu, 28 Sep 2023 09:43:15 -0700
Subject: [PATCH 074/175] Fix the markup on contributing.rst (#156)

It's rst not markdown. Replaced the leading hash with underlines.
---
 CONTRIBUTING.rst | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index c184a9c..0b2fbd6 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -1,4 +1,5 @@
-# How to release
+How to release
+--------------
 
 - Update CHANGELOG.rst
 - bump version (YYYY.MM) in pyproject.toml
@@ -13,7 +14,8 @@
 - push the tag (``git push --tags``)
 
 
-# Makefile usage
+Makefile usage
+--------------
 
 This project includes a simple Makefile for syncing changes to the theme with
 the main CPython repository. Run ``make help`` for details on available rules.

From dc194ed1a25258fa004a46cb465f34b768baf20b Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Wed, 4 Oct 2023 17:40:52 +0300
Subject: [PATCH 075/175] Add changelog for 2023.9

---
 CHANGELOG.rst  | 6 ++++++
 pyproject.toml | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index cbf57d4..ed7ca86 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,6 +2,12 @@
 Changelog
 =========
 
+`2023.9 <https://github.com/python/python-docs-theme/releases/tag/v2023.9>`_
+----------------------------------------------------------------------------
+
+- Focus search box when pressing slash (#153)
+   Contributed by Hugo van Kemenade
+
 `2023.8 <https://github.com/python/python-docs-theme/releases/tag/v2023.8>`_
 ----------------------------------------------------------------------------
 
diff --git a/pyproject.toml b/pyproject.toml
index 9be4a24..149c548 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,7 +5,7 @@ build-backend = "flit_core.buildapi"
 # project metadata
 [project]
 name = "python-docs-theme"
-version = "2023.8"
+version = "2023.9"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.rst"
 urls.Code = "https://github.com/python/python-docs-theme"

From d70dd100273e4992dd610786a2dc8219e2b99bcd Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Wed, 4 Oct 2023 18:30:59 +0300
Subject: [PATCH 076/175] Update release checklist

---
 CONTRIBUTING.rst | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 0b2fbd6..b0b4fa8 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -1,18 +1,20 @@
 How to release
 --------------
 
-- Update CHANGELOG.rst
-- bump version (YYYY.MM) in pyproject.toml
-- commit
-- push to check one last time if the tests pass github side.
-- tag it (YYYY.MM).
-- build (``python -m build``)
-- Test it (in :file:`cpython/Doc` run
-  ``./venv/bin/pip install ../../python-docs-theme/dist/python-docs-theme-2021.8.tar.gz``
-  then build the doc using ``make html``).
-- upload it: ``twine upload dist/*``.
-- push the tag (``git push --tags``)
-
+- Update ``CHANGELOG.rst``
+- Bump version (YYYY.MM) in ``pyproject.toml``
+- Commit
+- Push to check tests pass on
+  `GitHub Actions <https://github.com/python/python-docs-theme/actions>`__
+- Go to https://github.com/python/python-docs-theme/releases
+- Click "Draft a new release"
+- Click "Choose a tag"
+- Type the next YYYY.MM version and
+  select "**Create new tag: YYYY.MM** on publish"
+- Click "Generate release notes" and amend as required
+- Click "Publish release"
+- Check the tagged `GitHub Actions build <https://github.com/python/python-docs-theme/actions/workflows/pypi-package.yml>`__
+  has deployed to `PyPI <https://pypi.org/project/python-docs-theme/#history>`__
 
 Makefile usage
 --------------

From f738dc01fb2ce5f40ce495925a4c1aa01a045579 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Wed, 4 Oct 2023 21:40:32 +0300
Subject: [PATCH 077/175] Clarify checklist

---
 CONTRIBUTING.rst | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index b0b4fa8..2533e96 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -9,8 +9,9 @@ How to release
 - Go to https://github.com/python/python-docs-theme/releases
 - Click "Draft a new release"
 - Click "Choose a tag"
-- Type the next YYYY.MM version and
+- Type the next YYYY.MM version (no leading zero) and
   select "**Create new tag: YYYY.MM** on publish"
+- Leave the "Release title" blank (it will be autofilled)
 - Click "Generate release notes" and amend as required
 - Click "Publish release"
 - Check the tagged `GitHub Actions build <https://github.com/python/python-docs-theme/actions/workflows/pypi-package.yml>`__

From 79febab4027f3992165b1c14a2583a530cb35876 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Wed, 11 Oct 2023 12:35:45 +0200
Subject: [PATCH 078/175] Lint on GitHub Actions via pre-commit

---
 .flake8                            |  2 ++
 .github/workflows/lint.yml         | 20 ++++++++++++
 .github/workflows/pypi-package.yml |  2 +-
 .github/workflows/tests.yml        | 33 ++++++++++---------
 .pre-commit-config.yaml            | 50 +++++++++++++++++++++++++++++
 README.rst                         |  2 +-
 code_of_conduct.rst                |  1 -
 pyproject.toml                     | 51 ++++++++++++++----------------
 python_docs_theme/__init__.py      |  8 +++--
 python_docs_theme/static/menu.js   |  2 +-
 10 files changed, 121 insertions(+), 50 deletions(-)
 create mode 100644 .flake8
 create mode 100644 .github/workflows/lint.yml
 create mode 100644 .pre-commit-config.yaml

diff --git a/.flake8 b/.flake8
new file mode 100644
index 0000000..2bcd70e
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+max-line-length = 88
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
new file mode 100644
index 0000000..8509763
--- /dev/null
+++ b/.github/workflows/lint.yml
@@ -0,0 +1,20 @@
+name: Lint
+
+on: [push, pull_request, workflow_dispatch]
+
+env:
+  FORCE_COLOR: 1
+
+permissions:
+  contents: read
+
+jobs:
+  lint:
+    runs-on: ubuntu-latest
+
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/setup-python@v4
+        with:
+          python-version: "3.x"
+      - uses: pre-commit/action@v3.0.0
diff --git a/.github/workflows/pypi-package.yml b/.github/workflows/pypi-package.yml
index 2b8f8aa..355a35f 100644
--- a/.github/workflows/pypi-package.yml
+++ b/.github/workflows/pypi-package.yml
@@ -18,7 +18,7 @@ jobs:
     runs-on: ubuntu-latest
 
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
 
       - uses: hynek/build-and-inspect-python-package@v1
 
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index fa5ed35..e657890 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -1,22 +1,25 @@
 name: Tests
 
-on:
-  push:
-  pull_request:
-  workflow_dispatch:
+on: [push, pull_request, workflow_dispatch]
+
+env:
+  FORCE_COLOR: 1
 
 jobs:
   build_doc:
     name: Build CPython docs
     runs-on: ubuntu-latest
     strategy:
+      fail-fast: false
       matrix:
-        branch: [origin/main, 3.12, 3.11, '3.10', 3.9, 3.8]
+        branch: ["origin/main", "3.12", "3.11", "3.10", "3.9", "3.8"]
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-python@v4
         with:
           python-version: 3
+          allow-prereleases: true
+          cache: pip
       - name: Clone docsbuild scripts
         run: |
           git clone https://github.com/python/docsbuild-scripts/
@@ -26,15 +29,15 @@ jobs:
           python -m pip install -r docsbuild-scripts/requirements.txt
       - name: Build documentation
         run: >
-          python ./docsbuild-scripts/build_docs.py 
-          --quick 
-          --build-root ./build_root 
-          --www-root ./www 
-          --log-directory ./logs 
-          --group $(id -g) 
-          --skip-cache-invalidation 
-          --theme $(pwd) 
-          --language en 
+          python ./docsbuild-scripts/build_docs.py
+          --quick
+          --build-root ./build_root
+          --www-root ./www
+          --log-directory ./logs
+          --group $(id -g)
+          --skip-cache-invalidation
+          --theme $(pwd)
+          --language en
           --branch ${{ matrix.branch }}
       - name: Upload
         uses: actions/upload-artifact@v3
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..008784c
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,50 @@
+repos:
+  - repo: https://github.com/asottile/pyupgrade
+    rev: v3.15.0
+    hooks:
+      - id: pyupgrade
+        args: [--py38-plus]
+
+  - repo: https://github.com/psf/black-pre-commit-mirror
+    rev: 23.9.1
+    hooks:
+      - id: black
+
+  - repo: https://github.com/PyCQA/isort
+    rev: 5.12.0
+    hooks:
+      - id: isort
+        args: [--add-import=from __future__ import annotations]
+
+  - repo: https://github.com/PyCQA/flake8
+    rev: 6.1.0
+    hooks:
+      - id: flake8
+        additional_dependencies:
+          [flake8-2020, flake8-implicit-str-concat, flake8-logging]
+
+  - repo: https://github.com/pre-commit/pygrep-hooks
+    rev: v1.10.0
+    hooks:
+      - id: python-check-blanket-noqa
+
+  - repo: https://github.com/pre-commit/pre-commit-hooks
+    rev: v4.5.0
+    hooks:
+      - id: check-case-conflict
+      - id: check-executables-have-shebangs
+      - id: check-merge-conflict
+      - id: check-json
+      - id: check-toml
+      - id: check-yaml
+      - id: debug-statements
+      - id: end-of-file-fixer
+      - id: trailing-whitespace
+
+  - repo: https://github.com/abravalheri/validate-pyproject
+    rev: v0.14
+    hooks:
+      - id: validate-pyproject
+
+ci:
+  autoupdate_schedule: quarterly
diff --git a/README.rst b/README.rst
index 3f2e844..0a8db3f 100644
--- a/README.rst
+++ b/README.rst
@@ -10,7 +10,7 @@ projects if you so choose, but please keep in mind that in doing so you're also
 choosing to accept some of the responsibility for maintaining that collective
 trust.
 
-To use the theme, install it into your docs build environment via ``pip`` 
+To use the theme, install it into your docs build environment via ``pip``
 (preferably in a virtual environment).
 
 
diff --git a/code_of_conduct.rst b/code_of_conduct.rst
index 28de97c..4bc6630 100644
--- a/code_of_conduct.rst
+++ b/code_of_conduct.rst
@@ -11,4 +11,3 @@ which includes all infrastructure used in the development of Python itself
 
 In general this means everyone is expected to be open, considerate, and
 respectful of others no matter what their position is within the project.
-
diff --git a/pyproject.toml b/pyproject.toml
index 149c548..014cb94 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,43 +1,38 @@
 [build-system]
-requires = ["flit_core>=3.7"]
 build-backend = "flit_core.buildapi"
+requires = [
+  "flit_core>=3.7",
+]
 
-# project metadata
 [project]
 name = "python-docs-theme"
 version = "2023.9"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.rst"
-urls.Code = "https://github.com/python/python-docs-theme"
-urls.Download = "https://pypi.org/project/python-docs-theme/"
-urls.Homepage = "https://github.com/python/python-docs-theme/"
-urls."Issue tracker" = "https://github.com/python/python-docs-theme/issues"
 license.file = "LICENSE"
+authors = [{name = "PyPA", email = "distutils-sig@python.org"}]
 requires-python = ">=3.8"
-
-# Classifiers list: https://pypi.org/classifiers/
 classifiers = [
-    "Development Status :: 5 - Production/Stable",
-    "Framework :: Sphinx :: Theme",
-    "Intended Audience :: Developers",
-    "License :: OSI Approved :: Python Software Foundation License",
-    "Operating System :: OS Independent",
-    "Topic :: Documentation",
-    "Topic :: Software Development :: Documentation",
-    "Programming Language :: Python",
-    "Programming Language :: Python :: 3",
-    "Programming Language :: Python :: 3.8",
-    "Programming Language :: Python :: 3.9",
-    "Programming Language :: Python :: 3.10",
-    "Programming Language :: Python :: 3.11",
-    "Programming Language :: Python :: 3.12",
-    "Programming Language :: Python :: 3.13",
+  "Development Status :: 5 - Production/Stable",
+  "Framework :: Sphinx :: Theme",
+  "Intended Audience :: Developers",
+  "License :: OSI Approved :: Python Software Foundation License",
+  "Operating System :: OS Independent",
+  "Programming Language :: Python",
+  "Programming Language :: Python :: 3 :: Only",
+  "Programming Language :: Python :: 3.8",
+  "Programming Language :: Python :: 3.9",
+  "Programming Language :: Python :: 3.10",
+  "Programming Language :: Python :: 3.11",
+  "Programming Language :: Python :: 3.12",
+  "Programming Language :: Python :: 3.13",
+  "Topic :: Documentation",
+  "Topic :: Software Development :: Documentation",
 ]
-
-[[project.authors]]
-name = "PyPA"
-email = "distutils-sig@python.org"
-
+urls.Code = "https://github.com/python/python-docs-theme"
+urls.Download = "https://pypi.org/project/python-docs-theme/"
+urls.Homepage = "https://github.com/python/python-docs-theme/"
+urls."Issue tracker" = "https://github.com/python/python-docs-theme/issues"
 [project.entry-points."sphinx.html_themes"]
 python_docs_theme = 'python_docs_theme'
 
diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py
index 0857b5f..7747675 100644
--- a/python_docs_theme/__init__.py
+++ b/python_docs_theme/__init__.py
@@ -1,8 +1,10 @@
+from __future__ import annotations
+
 import hashlib
 import os
 from functools import lru_cache
 from pathlib import Path
-from typing import Any, Dict, List
+from typing import Any
 
 import sphinx.application
 from sphinx.builders.html import StandaloneHTMLBuilder
@@ -19,7 +21,7 @@ def _asset_hash(path: str) -> str:
     return f"{path}?digest={digest}"
 
 
-def _add_asset_hashes(static: List[str], add_digest_to: List[str]) -> None:
+def _add_asset_hashes(static: list[str], add_digest_to: list[str]) -> None:
     for asset in add_digest_to:
         index = static.index(asset)
         static[index].filename = _asset_hash(asset)  # type: ignore
@@ -29,7 +31,7 @@ def _html_page_context(
     app: sphinx.application.Sphinx,
     pagename: str,
     templatename: str,
-    context: Dict[str, Any],
+    context: dict[str, Any],
     doctree: Any,
 ) -> None:
     if app.config.html_theme != "python_docs_theme":
diff --git a/python_docs_theme/static/menu.js b/python_docs_theme/static/menu.js
index e233585..c7ab03e 100644
--- a/python_docs_theme/static/menu.js
+++ b/python_docs_theme/static/menu.js
@@ -54,4 +54,4 @@ document.addEventListener("DOMContentLoaded", function () {
             closeMenu()
         }
     })
-})
\ No newline at end of file
+})

From cc74a749c068441edb13ad2d4443570e4f5e5386 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Wed, 18 Oct 2023 21:58:41 +0300
Subject: [PATCH 079/175] Underline links for readability and a11y

---
 python_docs_theme/static/pydoctheme.css | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index ce032f1..664445e 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -29,6 +29,10 @@ pre {
     color: inherit;
 }
 
+a {
+    text-decoration: underline;
+}
+
 body {
     margin-left: 1em;
     margin-right: 1em;

From 071911ed9a375d993a780951d8c6957abf56f96e Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sat, 4 Nov 2023 20:35:12 +0200
Subject: [PATCH 080/175] Redunce underline thickness, move underline down,
 increase line height

---
 python_docs_theme/static/pydoctheme.css | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 664445e..cb8d2d9 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -30,7 +30,8 @@ pre {
 }
 
 a {
-    text-decoration: underline;
+    text-decoration: underline 1px;
+    text-underline-offset: 0.3em;
 }
 
 body {
@@ -181,7 +182,7 @@ div.body {
 
 div.body p, div.body dd, div.body li, div.body blockquote {
     text-align: left;
-    line-height: 1.4;
+    line-height: 1.6;
 }
 div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 {
     margin: 0;

From a5ca1f52f5b9ae6d18a80b91dac7e74d288171f6 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sun, 5 Nov 2023 23:03:52 +0200
Subject: [PATCH 081/175] Only underline actual links rather than placeholder
 links

Co-authored-by: Pradyun Gedam <pradyunsg@gmail.com>
---
 python_docs_theme/static/pydoctheme.css | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index cb8d2d9..a69cd17 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -29,7 +29,7 @@ pre {
     color: inherit;
 }
 
-a {
+a[href] {
     text-decoration: underline 1px;
     text-underline-offset: 0.3em;
 }

From 901c74796ba01192e264335b8559f0feeb9cc6eb Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Sun, 3 Dec 2023 12:41:10 +0200
Subject: [PATCH 082/175] Dark mode: fix contrast of footer highlight

---
 python_docs_theme/static/pydoctheme_dark.css | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index 46a2c7a..758d3de 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -60,6 +60,10 @@ span.highlighted {
     background-color: #616161;
 }
 
+.footnote:target {
+    background-color: #2c3e50;
+}
+
 /* Below for most things in text */
 
 dl.field-list > dt {

From 45793b571499bb383e2da53737b5855b64736241 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Wed, 10 Jan 2024 10:00:21 +0200
Subject: [PATCH 083/175] Show logs on error (#164)

---
 .github/workflows/tests.yml | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index e657890..9407ac7 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -39,6 +39,10 @@ jobs:
           --theme $(pwd)
           --language en
           --branch ${{ matrix.branch }}
+      - name: Show logs
+        if: failure()
+        run: |
+          cat ./logs/docsbuild.log
       - name: Upload
         uses: actions/upload-artifact@v3
         with:

From beb868fc38ae5d7b8ea511b4c75760fbb2ea6d12 Mon Sep 17 00:00:00 2001
From: Marko Budisic <mbudisic@gmail.com>
Date: Fri, 12 Jan 2024 12:44:50 -0500
Subject: [PATCH 084/175] Consistently reference `theme_root_icon` (#163)

Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Co-authored-by: Ezio Melotti <ezio.melotti@gmail.com>
Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
---
 python_docs_theme/layout.html | 8 ++++----
 python_docs_theme/theme.conf  | 1 +
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index 82b7ef4..81433e0 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -14,7 +14,7 @@ <h3>{{ _('Navigation') }}</h3>
           </li>
           {%- endfor %}
           {%- block rootrellink %}
-          <li><img src="{{ pathto('_static/py.svg', 1) }}" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
+          <li><img src="{{ pathto('_static/' ~ theme_root_icon, 1) }}" alt="{{ theme_root_icon_alt_text }}" style="vertical-align: middle; margin-top: -1px"/></li>
           <li><a href="{{theme_root_url}}">{{theme_root_name}}</a>{{ reldelim1 }}</li>
           <li class="switchers">
             <div class="language_switcher_placeholder"></div>
@@ -71,7 +71,7 @@ <h3>{{ _('Navigation') }}</h3>
 
 {%- block extrahead -%}
     <link rel="stylesheet" href="{{ pathto('_static/pydoctheme_dark.css', 1) }}" media="(prefers-color-scheme: dark)" id="pydoctheme_dark_css">
-    <link rel="shortcut icon" type="image/png" href="{{ pathto('_static/' + theme_root_icon, 1) }}" />
+    <link rel="shortcut icon" type="image/png" href="{{ pathto('_static/' ~ theme_root_icon, 1) }}" />
     {%- if builder != "htmlhelp" %}
         {%- if not embedded %}
             <script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>
@@ -100,7 +100,7 @@ <h3>{{ _('Navigation') }}</h3>
         </label>
         <span class="nav-items-wrapper">
             <a href="{{ theme_root_url }}" class="nav-logo">
-                <img src="{{ pathto('_static/py.svg', 1) }}" alt="Logo"/>
+                <img src="{{ pathto('_static/' ~ theme_root_icon, 1) }}" alt="{{ theme_root_icon_alt_text }}"/>
             </a>
             <span class="version_switcher_placeholder"></span>
             {%- if pagename != "search" and builder != "singlehtml" %}
@@ -121,7 +121,7 @@ <h3>{{ _('Navigation') }}</h3>
             {%- if logo %}
             <p class="logo">
                 <a href="{{ pathto('index') }}">
-                <img class="logo" src="{{ pathto('_static/' + logo, 1)|e }}" alt="Logo"/>
+                <img class="logo" src="{{ pathto('_static/' ~ logo, 1)|e }}" alt="Logo"/>
                 </a>
             </p>
             {%- endif %}
diff --git a/python_docs_theme/theme.conf b/python_docs_theme/theme.conf
index 564c9c5..e6008d9 100644
--- a/python_docs_theme/theme.conf
+++ b/python_docs_theme/theme.conf
@@ -31,5 +31,6 @@ license_url =
 root_name = Python
 root_url = https://www.python.org/
 root_icon = py.svg
+root_icon_alt_text = Python logo
 root_include_title = True
 copyright_url =

From 375517fec87a4c1283216c423771dd6c469dd9af Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Fri, 26 Jan 2024 15:38:21 +0200
Subject: [PATCH 085/175] Add hosted_on variable for a link in the footer

---
 python_docs_theme/layout.html | 3 +++
 python_docs_theme/theme.conf  | 1 +
 2 files changed, 4 insertions(+)

diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index 81433e0..c0d81dc 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -143,6 +143,9 @@ <h3>{{ _('Navigation') }}</h3>
     {% trans %}Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.{% endtrans %}
     <br />
     {% if theme_license_url %}{% trans license_file=theme_license_url %}See <a href="{{ license_file }}">History and License</a> for more information.{% endtrans %}<br />{% endif %}
+    {% if theme_hosted_on %}
+        {% trans hosted_on=theme_hosted_on %}Hosted on {{ hosted_on }}.{% endtrans %}<br />
+    {% endif %}
     <br />
 
     {% include "footerdonate.html" %}
diff --git a/python_docs_theme/theme.conf b/python_docs_theme/theme.conf
index e6008d9..1fbcabc 100644
--- a/python_docs_theme/theme.conf
+++ b/python_docs_theme/theme.conf
@@ -26,6 +26,7 @@ headlinkcolor = #aaaaaa
 codebgcolor = #eeffcc
 codetextcolor = #333333
 
+hosted_on =
 issues_url =
 license_url =
 root_name = Python

From 1dc112bc9a4861b4bfae6d25b34b3798c2363d2c Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Fri, 26 Jan 2024 16:08:30 +0200
Subject: [PATCH 086/175] Single line

---
 python_docs_theme/layout.html | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index c0d81dc..d387ef3 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -143,9 +143,7 @@ <h3>{{ _('Navigation') }}</h3>
     {% trans %}Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.{% endtrans %}
     <br />
     {% if theme_license_url %}{% trans license_file=theme_license_url %}See <a href="{{ license_file }}">History and License</a> for more information.{% endtrans %}<br />{% endif %}
-    {% if theme_hosted_on %}
-        {% trans hosted_on=theme_hosted_on %}Hosted on {{ hosted_on }}.{% endtrans %}<br />
-    {% endif %}
+    {% if theme_hosted_on %}{% trans hosted_on=theme_hosted_on %}Hosted on {{ hosted_on }}.{% endtrans %}<br />{% endif %}
     <br />
 
     {% include "footerdonate.html" %}

From 62b314f2ee9b03997ca8bcd306e45c0818549f0c Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sat, 27 Jan 2024 16:49:51 +0200
Subject: [PATCH 087/175] Reduce underline offset

---
 python_docs_theme/static/pydoctheme.css | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index a69cd17..962b63f 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -31,7 +31,7 @@ pre {
 
 a[href] {
     text-decoration: underline 1px;
-    text-underline-offset: 0.3em;
+    text-underline-offset: 0.2em;
 }
 
 body {

From cf5b9e630dfee9f47cf0651e77292c3f65bf7b12 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sat, 27 Jan 2024 18:46:37 +0200
Subject: [PATCH 088/175] Increase underline offset a bit more

---
 python_docs_theme/static/pydoctheme.css | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 962b63f..14464db 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -31,7 +31,7 @@ pre {
 
 a[href] {
     text-decoration: underline 1px;
-    text-underline-offset: 0.2em;
+    text-underline-offset: 0.25em;
 }
 
 body {

From 4f8095d6e6267591ff585d25a38d5d92602eb306 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sat, 27 Jan 2024 21:26:16 +0200
Subject: [PATCH 089/175] Prepare 2024.1 release

---
 CHANGELOG.rst  | 12 ++++++++++++
 pyproject.toml |  2 +-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index ed7ca86..f44760d 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,6 +2,18 @@
 Changelog
 =========
 
+`2024.1 <https://github.com/python/python-docs-theme/releases/tag/v2024.1>`_
+----------------------------------------------------------------------------
+
+- Underline links for readability and a11y (#160, #166)
+  Contributed by Hugo van Kemenade
+- Add ``hosted_on`` variable for a link in the footer (#165)
+  Contributed by Hugo van Kemenade
+- Consistently reference ``theme_root_icon`` (#163)
+  Contributed by Marko Budiselic
+- Dark mode: fix contrast of footer highlight (#162)
+  Contributed by Hugo van Kemenade
+
 `2023.9 <https://github.com/python/python-docs-theme/releases/tag/v2023.9>`_
 ----------------------------------------------------------------------------
 
diff --git a/pyproject.toml b/pyproject.toml
index 014cb94..ce22aed 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,7 +6,7 @@ requires = [
 
 [project]
 name = "python-docs-theme"
-version = "2023.9"
+version = "2024.1"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.rst"
 license.file = "LICENSE"

From 2c2072371ab944db5987a986094ddb0cdd8767fd Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Fri, 2 Feb 2024 15:07:10 +0200
Subject: [PATCH 090/175] Do not underline navigation links

---
 python_docs_theme/static/pydoctheme.css | 28 +++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 14464db..c5e44fc 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -33,6 +33,30 @@ a[href] {
     text-decoration: underline 1px;
     text-underline-offset: 0.25em;
 }
+/* No underline for navigation */
+div.genindex-jumpbox a,
+div.modindex-jumpbox a,
+div#search-results a,
+div.sphinxsidebar a,
+div.toctree-wrapper a,
+div[role=navigation] a,
+table.contentstable a,
+table.indextable a {
+    text-decoration: none;
+}
+
+/* Except when hovered */
+div.genindex-jumpbox a:hover,
+div.modindex-jumpbox a:hover,
+div#search-results a:hover,
+div.sphinxsidebar a:hover,
+div.toctree-wrapper a:hover,
+div[role=navigation] a:hover,
+table.contentstable a:hover,
+table.indextable a:hover {
+    text-decoration: underline;
+    text-underline-offset: auto;
+}
 
 body {
     margin-left: 1em;
@@ -284,6 +308,10 @@ div.footer {
     margin-right: 10px;
 }
 
+div.footer a {
+    text-underline-offset: auto;
+}
+
 div.footer a:hover {
     color: #0095c4;
 }

From 761de4d6feefa832cd3fdc57df3292464a1e9f29 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Fri, 2 Feb 2024 22:28:26 +0200
Subject: [PATCH 091/175] Update pre-commit

---
 .pre-commit-config.yaml | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 008784c..d429bb3 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -6,18 +6,18 @@ repos:
         args: [--py38-plus]
 
   - repo: https://github.com/psf/black-pre-commit-mirror
-    rev: 23.9.1
+    rev: 24.1.1
     hooks:
       - id: black
 
   - repo: https://github.com/PyCQA/isort
-    rev: 5.12.0
+    rev: 5.13.2
     hooks:
       - id: isort
         args: [--add-import=from __future__ import annotations]
 
   - repo: https://github.com/PyCQA/flake8
-    rev: 6.1.0
+    rev: 7.0.0
     hooks:
       - id: flake8
         additional_dependencies:
@@ -42,7 +42,7 @@ repos:
       - id: trailing-whitespace
 
   - repo: https://github.com/abravalheri/validate-pyproject
-    rev: v0.14
+    rev: v0.16
     hooks:
       - id: validate-pyproject
 

From 3e0f891d026e36414049192084a127e827ed0900 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Fri, 2 Feb 2024 22:28:48 +0200
Subject: [PATCH 092/175] Newlines for clarity

---
 .github/workflows/pypi-package.yml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/pypi-package.yml b/.github/workflows/pypi-package.yml
index 355a35f..bd704b5 100644
--- a/.github/workflows/pypi-package.yml
+++ b/.github/workflows/pypi-package.yml
@@ -27,7 +27,9 @@ jobs:
     name: Publish to PyPI
     environment: release-pypi
     # Only run for published releases.
-    if: github.repository_owner == 'python' && github.event.action == 'published'
+    if: |
+      github.repository_owner == 'python'
+      && github.event.action == 'published'
     runs-on: ubuntu-latest
     needs: build-package
 

From ed0650e30ad25239334006343ef044384063b0a1 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Fri, 2 Feb 2024 22:29:21 +0200
Subject: [PATCH 093/175] Specify isort profile for compatibility with Black

---
 pyproject.toml | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/pyproject.toml b/pyproject.toml
index ce22aed..6009f19 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -36,6 +36,9 @@ urls."Issue tracker" = "https://github.com/python/python-docs-theme/issues"
 [project.entry-points."sphinx.html_themes"]
 python_docs_theme = 'python_docs_theme'
 
+[tool.isort]
+profile = "black"
+
 [tool.flit.module]
 name = "python_docs_theme"
 

From 2b24269dfe4cad0f1ccafa2a6fd590a265622457 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Fri, 2 Feb 2024 22:32:23 +0200
Subject: [PATCH 094/175] Add Dependabot to keep GitHub Actions up-to-date

---
 .github/dependabot.yml | 10 ++++++++++
 1 file changed, 10 insertions(+)
 create mode 100644 .github/dependabot.yml

diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000..5c56314
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,10 @@
+version: 2
+updates:
+  - package-ecosystem: "github-actions"
+    directory: "/"
+    schedule:
+      interval: monthly
+    groups:
+      actions:
+        patterns:
+          - "*"

From 82c7468ec3fbd883c5ff7decec348728912cae65 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Fri, 2 Feb 2024 22:44:46 +0200
Subject: [PATCH 095/175] Add handy pre-commit checks

---
 .pre-commit-config.yaml | 14 +++++++++++---
 pyproject.toml          |  7 ++++---
 2 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index d429bb3..70b4e19 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -14,7 +14,6 @@ repos:
     rev: 5.13.2
     hooks:
       - id: isort
-        args: [--add-import=from __future__ import annotations]
 
   - repo: https://github.com/PyCQA/flake8
     rev: 7.0.0
@@ -32,19 +31,28 @@ repos:
     rev: v4.5.0
     hooks:
       - id: check-case-conflict
-      - id: check-executables-have-shebangs
       - id: check-merge-conflict
-      - id: check-json
       - id: check-toml
       - id: check-yaml
       - id: debug-statements
       - id: end-of-file-fixer
       - id: trailing-whitespace
 
+  - repo: https://github.com/tox-dev/pyproject-fmt
+    rev: 1.7.0
+    hooks:
+      - id: pyproject-fmt
+        args: [--max-supported-python=3.13]
+
   - repo: https://github.com/abravalheri/validate-pyproject
     rev: v0.16
     hooks:
       - id: validate-pyproject
 
+  - repo: meta
+    hooks:
+      - id: check-hooks-apply
+      - id: check-useless-excludes
+
 ci:
   autoupdate_schedule: quarterly
diff --git a/pyproject.toml b/pyproject.toml
index 6009f19..272d26c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -36,9 +36,6 @@ urls."Issue tracker" = "https://github.com/python/python-docs-theme/issues"
 [project.entry-points."sphinx.html_themes"]
 python_docs_theme = 'python_docs_theme'
 
-[tool.isort]
-profile = "black"
-
 [tool.flit.module]
 name = "python_docs_theme"
 
@@ -46,3 +43,7 @@ name = "python_docs_theme"
 include = [
     "python_docs_theme/",
 ]
+
+[tool.isort]
+add_imports = "from __future__ import annotations"
+profile = "black"

From 78fcd4b989aa5cb34190997fe1540d5852681076 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Fri, 2 Feb 2024 23:03:26 +0200
Subject: [PATCH 096/175] Add link to PR of docs preview

---
 .github/workflows/documentation-links.yml | 27 +++++++++++++++++++++++
 1 file changed, 27 insertions(+)
 create mode 100644 .github/workflows/documentation-links.yml

diff --git a/.github/workflows/documentation-links.yml b/.github/workflows/documentation-links.yml
new file mode 100644
index 0000000..f05df37
--- /dev/null
+++ b/.github/workflows/documentation-links.yml
@@ -0,0 +1,27 @@
+name: Read the Docs PR preview
+# Automatically edits a pull request's descriptions with a link
+# to the documentation's preview on Read the Docs.
+
+on:
+  pull_request_target:
+    types:
+      - opened
+    paths:
+    - 'Doc/**'
+    - '.github/workflows/doc.yml'
+
+permissions:
+  pull-requests: write
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
+  cancel-in-progress: true
+
+jobs:
+  documentation-links:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: readthedocs/actions/preview@v1
+        with:
+          project-slug: "python-docs-theme-previews"
+          single-version: "true"

From 2f38e86cea78c9b31372d0c291119deae5044c6f Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sat, 3 Feb 2024 23:26:28 +0200
Subject: [PATCH 097/175] Only apply underline offset to code formatting for
 underline visibility

---
 python_docs_theme/static/pydoctheme.css | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 14464db..dff8ee8 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -31,7 +31,10 @@ pre {
 
 a[href] {
     text-decoration: underline 1px;
+
+a[href]:has(> code) {
     text-underline-offset: 0.25em;
+    color: red;
 }
 
 body {

From 98b94c5e56aa86ef887730263993297ead57f7a9 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sat, 3 Feb 2024 23:32:33 +0200
Subject: [PATCH 098/175] Remove debugging

---
 python_docs_theme/static/pydoctheme.css | 1 -
 1 file changed, 1 deletion(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index dff8ee8..d404934 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -34,7 +34,6 @@ a[href] {
 
 a[href]:has(> code) {
     text-underline-offset: 0.25em;
-    color: red;
 }
 
 body {

From bd00c3da51f6a00697eefbedf8cf9cd465722561 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sat, 3 Feb 2024 23:35:39 +0200
Subject: [PATCH 099/175] =?UTF-8?q?Don't=20underline=20the=20pilcrow=20(?=
 =?UTF-8?q?=C2=B6)=20navigation=20symbol?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 python_docs_theme/static/pydoctheme.css | 1 +
 1 file changed, 1 insertion(+)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index c5e44fc..54c1616 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -34,6 +34,7 @@ a[href] {
     text-underline-offset: 0.25em;
 }
 /* No underline for navigation */
+a.headerlink,
 div.genindex-jumpbox a,
 div.modindex-jumpbox a,
 div#search-results a,

From 2dd4e77cbcf5d2f46f723a81c3938e2de22a08e2 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sat, 3 Feb 2024 23:46:30 +0200
Subject: [PATCH 100/175] Add missing bracket

---
 python_docs_theme/static/pydoctheme.css | 1 +
 1 file changed, 1 insertion(+)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index d404934..263f3f6 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -31,6 +31,7 @@ pre {
 
 a[href] {
     text-decoration: underline 1px;
+}
 
 a[href]:has(> code) {
     text-underline-offset: 0.25em;

From 14335e475448e2ec561fe650cb3c48088c91c831 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sun, 4 Feb 2024 09:16:30 -0700
Subject: [PATCH 101/175] Update .github/dependabot.yml

Co-authored-by: Ezio Melotti <ezio.melotti@gmail.com>
---
 .github/dependabot.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 5c56314..8452ef0 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -4,6 +4,8 @@ updates:
     directory: "/"
     schedule:
       interval: monthly
+    assignees:
+      - "ezio-melotti"
     groups:
       actions:
         patterns:

From 2f3f86ec603341cce76616ed2f83c8a9ee0a4b4e Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sun, 4 Feb 2024 19:20:50 +0200
Subject: [PATCH 102/175] Add comments

---
 python_docs_theme/static/pydoctheme.css | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 8112fa4..959a94e 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -29,10 +29,12 @@ pre {
     color: inherit;
 }
 
+/* Add underlines to links */
 a[href] {
     text-decoration: underline 1px;
 }
 
+/* Increase the underline offset for code to avoid obscuring underscores */
 a[href]:has(> code) {
     text-underline-offset: 0.25em;
 }

From fbf2bf896c464dcb192735f8e5d1222d5dcdc1eb Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sun, 4 Feb 2024 19:22:35 +0200
Subject: [PATCH 103/175] Whitespace between CSS blocks

---
 python_docs_theme/static/pydoctheme.css | 1 +
 1 file changed, 1 insertion(+)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 959a94e..87a0629 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -38,6 +38,7 @@ a[href] {
 a[href]:has(> code) {
     text-underline-offset: 0.25em;
 }
+
 /* No underline for navigation */
 a.headerlink,
 div.genindex-jumpbox a,

From cc1161b2bbc3d7f11e14c1eda31963cc904cbd30 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sun, 4 Feb 2024 12:56:06 -0700
Subject: [PATCH 104/175] README: Add link to preview build

---
 README.rst | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/README.rst b/README.rst
index 0a8db3f..5055bad 100644
--- a/README.rst
+++ b/README.rst
@@ -21,4 +21,11 @@ To use this theme, add the following to ``conf.py``:
 
 - ``html_theme = 'python_docs_theme'``
 
-- ``html_sidebars``, defaults taken from http://www.sphinx-doc.org/en/stable/config.html#confval-html_sidebars
+- ``html_sidebars``, defaults taken from https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_sidebars
+
+Preview
+-------
+
+See a demo of the CPython docs using this theme:
+
+- https://python-docs-theme-previews.readthedocs.io

From b3d1ae14eb0c7223b3430d42c8a085aeece3f744 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Mon, 5 Feb 2024 13:50:50 +0200
Subject: [PATCH 105/175] Prepare 2024.2 release

---
 CHANGELOG.rst  | 17 ++++++++++++-----
 pyproject.toml |  2 +-
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index f44760d..0b02c3f 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,18 +1,25 @@
-=========
 Changelog
 =========
 
+`2024.2 <https://github.com/python/python-docs-theme/releases/tag/v2024.2>`_
+----------------------------------------------------------------------------
+
+- Do not underline navigation links (#169)
+   Contributed by Hugo van Kemenade
+- Only apply underline offset to code formatting for underline visibility (#171)
+   Contributed by Hugo van Kemenade
+
 `2024.1 <https://github.com/python/python-docs-theme/releases/tag/v2024.1>`_
 ----------------------------------------------------------------------------
 
 - Underline links for readability and a11y (#160, #166)
-  Contributed by Hugo van Kemenade
+   Contributed by Hugo van Kemenade
 - Add ``hosted_on`` variable for a link in the footer (#165)
-  Contributed by Hugo van Kemenade
+   Contributed by Hugo van Kemenade
 - Consistently reference ``theme_root_icon`` (#163)
-  Contributed by Marko Budiselic
+   Contributed by Marko Budiselic
 - Dark mode: fix contrast of footer highlight (#162)
-  Contributed by Hugo van Kemenade
+   Contributed by Hugo van Kemenade
 
 `2023.9 <https://github.com/python/python-docs-theme/releases/tag/v2023.9>`_
 ----------------------------------------------------------------------------
diff --git a/pyproject.toml b/pyproject.toml
index ce22aed..dd228f4 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,7 +6,7 @@ requires = [
 
 [project]
 name = "python-docs-theme"
-version = "2024.1"
+version = "2024.2"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.rst"
 license.file = "LICENSE"

From 35e9780170330819243e43b3d88f9715a4e1801a Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 9 Feb 2024 16:39:58 +0000
Subject: [PATCH 106/175] Bump the actions group with 5 updates

Bumps the actions group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [actions/setup-python](https://github.com/actions/setup-python) | `4` | `5` |
| [pre-commit/action](https://github.com/pre-commit/action) | `3.0.0` | `3.0.1` |
| [hynek/build-and-inspect-python-package](https://github.com/hynek/build-and-inspect-python-package) | `1` | `2` |
| [actions/download-artifact](https://github.com/actions/download-artifact) | `3` | `4` |
| [actions/upload-artifact](https://github.com/actions/upload-artifact) | `3` | `4` |


Updates `actions/setup-python` from 4 to 5
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4...v5)

Updates `pre-commit/action` from 3.0.0 to 3.0.1
- [Release notes](https://github.com/pre-commit/action/releases)
- [Commits](https://github.com/pre-commit/action/compare/v3.0.0...v3.0.1)

Updates `hynek/build-and-inspect-python-package` from 1 to 2
- [Release notes](https://github.com/hynek/build-and-inspect-python-package/releases)
- [Changelog](https://github.com/hynek/build-and-inspect-python-package/blob/main/CHANGELOG.md)
- [Commits](https://github.com/hynek/build-and-inspect-python-package/compare/v1...v2)

Updates `actions/download-artifact` from 3 to 4
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v3...v4)

Updates `actions/upload-artifact` from 3 to 4
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: pre-commit/action
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
- dependency-name: hynek/build-and-inspect-python-package
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/lint.yml         | 4 ++--
 .github/workflows/pypi-package.yml | 4 ++--
 .github/workflows/tests.yml        | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 8509763..88c0c7c 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -14,7 +14,7 @@ jobs:
 
     steps:
       - uses: actions/checkout@v4
-      - uses: actions/setup-python@v4
+      - uses: actions/setup-python@v5
         with:
           python-version: "3.x"
-      - uses: pre-commit/action@v3.0.0
+      - uses: pre-commit/action@v3.0.1
diff --git a/.github/workflows/pypi-package.yml b/.github/workflows/pypi-package.yml
index bd704b5..c7acc05 100644
--- a/.github/workflows/pypi-package.yml
+++ b/.github/workflows/pypi-package.yml
@@ -20,7 +20,7 @@ jobs:
     steps:
       - uses: actions/checkout@v4
 
-      - uses: hynek/build-and-inspect-python-package@v1
+      - uses: hynek/build-and-inspect-python-package@v2
 
   # Upload to real PyPI on GitHub Releases.
   release-pypi:
@@ -38,7 +38,7 @@ jobs:
 
     steps:
       - name: Download packages built by build-and-inspect-python-package
-        uses: actions/download-artifact@v3
+        uses: actions/download-artifact@v4
         with:
           name: Packages
           path: dist
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 9407ac7..df0dc48 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -15,7 +15,7 @@ jobs:
         branch: ["origin/main", "3.12", "3.11", "3.10", "3.9", "3.8"]
     steps:
       - uses: actions/checkout@v4
-      - uses: actions/setup-python@v4
+      - uses: actions/setup-python@v5
         with:
           python-version: 3
           allow-prereleases: true
@@ -44,7 +44,7 @@ jobs:
         run: |
           cat ./logs/docsbuild.log
       - name: Upload
-        uses: actions/upload-artifact@v3
+        uses: actions/upload-artifact@v4
         with:
           name: doc-html
           path: www/

From 40e175bb1fc9b1c8df915a4d129c6473e5551498 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Fri, 9 Feb 2024 18:52:44 +0200
Subject: [PATCH 107/175] Include name in artifact name to work with
 actions/upload-artifact@v4

---
 .github/workflows/tests.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index df0dc48..2187fb1 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -46,5 +46,5 @@ jobs:
       - name: Upload
         uses: actions/upload-artifact@v4
         with:
-          name: doc-html
+          name: doc-html-${{ matrix.branch }}
           path: www/

From 21ff0a2a3d3beb3de0f9caeded87ea27a128c3df Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date: Mon, 6 Nov 2023 15:09:14 +0200
Subject: [PATCH 108/175] Use system font stack

---
 python_docs_theme/static/pydoctheme.css | 6 +++---
 python_docs_theme/theme.conf            | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 87a0629..36a6ed9 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -170,7 +170,7 @@ div.sphinxsidebar a:hover {
 form.inline-search input,
 div.sphinxsidebar input,
 div.related input {
-    font-family: 'Lucida Grande', Arial, sans-serif;
+    font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif;
     border: 1px solid #999999;
     font-size: smaller;
     border-radius: 3px;
@@ -258,7 +258,7 @@ div.body a:hover {
 }
 
 tt, code, pre {
-    font-family: ui-monospace, "Cascadia Mono", "Segoe UI Mono", "Liberation Mono", Menlo, Monaco, Consolas, monospace;
+    font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
     font-size: 96.5%;
 }
 
@@ -362,7 +362,7 @@ div.genindex-jumpbox a {
     top: 0;
     right: 0;
     text-size: 75%;
-    font-family: monospace;
+    font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
     padding-left: 0.2em;
     padding-right: 0.2em;
     border-radius: 0 3px 0 0;
diff --git a/python_docs_theme/theme.conf b/python_docs_theme/theme.conf
index 1fbcabc..5edf397 100644
--- a/python_docs_theme/theme.conf
+++ b/python_docs_theme/theme.conf
@@ -5,8 +5,8 @@ pygments_style = default
 pygments_dark_style = monokai
 
 [options]
-bodyfont = 'Lucida Grande', Arial, sans-serif
-headfont = 'Lucida Grande', Arial, sans-serif
+bodyfont = -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif
+headfont = -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif
 footerbgcolor = white
 footertextcolor = #555555
 relbarbgcolor = white

From 6f35188e577d26e1a4e937e2dbc28c19eba36065 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sat, 16 Mar 2024 11:49:00 +0200
Subject: [PATCH 109/175] Don't test theme on 3.8 and 3.9 branches

---
 .github/workflows/tests.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 2187fb1..1b58d3e 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -12,7 +12,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        branch: ["origin/main", "3.12", "3.11", "3.10", "3.9", "3.8"]
+        branch: ["origin/main", "3.12", "3.11", "3.10"]
     steps:
       - uses: actions/checkout@v4
       - uses: actions/setup-python@v5

From 10918c3463dad7fab22d3ad6237166e7d53aa973 Mon Sep 17 00:00:00 2001
From: Kerim Kabirov <the.privat33r+gh@pm.me>
Date: Sun, 17 Mar 2024 19:39:19 +0100
Subject: [PATCH 110/175] Remove incorrect CSS property

---
 python_docs_theme/static/pydoctheme.css | 1 -
 1 file changed, 1 deletion(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 36a6ed9..39c4e33 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -361,7 +361,6 @@ div.genindex-jumpbox a {
     position: absolute;
     top: 0;
     right: 0;
-    text-size: 75%;
     font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
     padding-left: 0.2em;
     padding-right: 0.2em;

From d9136c620f90fbbb990d50c4ac8ad122fb54b2c8 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Thu, 21 Mar 2024 12:27:07 +0200
Subject: [PATCH 111/175] Prepare 2024.3 release

---
 CHANGELOG.rst  | 10 +++++++++-
 pyproject.toml |  2 +-
 2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 0b02c3f..07f7d4c 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,14 @@
 Changelog
 =========
 
+`2024.3 <https://github.com/python/python-docs-theme/releases/tag/v2024.3>`_
+----------------------------------------------------------------------------
+
+- Modernise font: use system font stack to improve text readability and webpage performance (#174)
+    Contributed by Hugo van Kemenade
+- Remove incorrect CSS property (#178)
+    Contributed by Kerim Kabirov
+
 `2024.2 <https://github.com/python/python-docs-theme/releases/tag/v2024.2>`_
 ----------------------------------------------------------------------------
 
@@ -40,7 +48,7 @@ Changelog
 `2023.7 <https://github.com/python/python-docs-theme/releases/tag/v2023.7>`_
 ----------------------------------------------------------------------------
 
-- Fix compatability with Sphinx 7.1 (#137)
+- Fix compatibility with Sphinx 7.1 (#137)
    Contributed by Pradyun Gedam
 - Enable the slash keypress to focus the search field (#141)
    Contributed by Mike Fiedler
diff --git a/pyproject.toml b/pyproject.toml
index 8fd838f..fc5f551 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,7 +6,7 @@ requires = [
 
 [project]
 name = "python-docs-theme"
-version = "2024.2"
+version = "2024.3"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.rst"
 license.file = "LICENSE"

From 95134919673c13112574ac50c1bc96ad1e6f2b33 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Fri, 22 Mar 2024 13:40:05 +0200
Subject: [PATCH 112/175] Exclude bots from generated release notes

---
 .github/release.yml | 5 +++++
 1 file changed, 5 insertions(+)
 create mode 100644 .github/release.yml

diff --git a/.github/release.yml b/.github/release.yml
new file mode 100644
index 0000000..9d1e098
--- /dev/null
+++ b/.github/release.yml
@@ -0,0 +1,5 @@
+changelog:
+  exclude:
+    authors:
+      - dependabot
+      - pre-commit-ci

From fe6a24363611175387dab379b6125d9190ffd7d4 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Mon, 25 Mar 2024 15:43:38 +0200
Subject: [PATCH 113/175] Only show 'Last updated on ...' when last_updated
 defined

---
 python_docs_theme/layout.html | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index d387ef3..a661961 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -149,7 +149,9 @@ <h3>{{ _('Navigation') }}</h3>
     {% include "footerdonate.html" %}
     <br />
 
-    {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
+    {%- if last_updated %}
+      {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
+    {%- endif %}
     {% if theme_issues_url %}{% trans %}<a href="{{ theme_issues_url }}">Found a bug</a>?{% endtrans %}{% endif %}
     <br />
 

From 5c6c0b4856b6c344591c6cb97a004e5db68f0b01 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Mon, 25 Mar 2024 15:51:05 +0200
Subject: [PATCH 114/175] Add newlines to make if blocks clear

---
 python_docs_theme/layout.html | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index a661961..9762b06 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -136,14 +136,24 @@ <h3>{{ _('Navigation') }}</h3>
 
 {% block footer %}
     <div class="footer">
-    &copy; {% if theme_copyright_url or hasdoc('copyright') %}<a href="{% if theme_copyright_url %}{{ theme_copyright_url }}{% else %}{{ pathto('copyright') }}{% endif %}">{% endif %}{% trans %}Copyright{% endtrans %}{% if theme_copyright_url or hasdoc('copyright') %}</a>{% endif %} {{ copyright|e }}.
+    &copy; {% if theme_copyright_url or hasdoc('copyright') %}
+      <a href="{% if theme_copyright_url %}{{ theme_copyright_url }}{% else %}{{ pathto('copyright') }}{% endif %}">
+    {% endif %}
+    {% trans %}Copyright{% endtrans %}
+    {% if theme_copyright_url or hasdoc('copyright') %}
+      </a>
+    {% endif %} {{ copyright|e }}.
     <br />
     {% trans %}This page is licensed under the Python Software Foundation License Version 2.{% endtrans %}
     <br />
     {% trans %}Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.{% endtrans %}
     <br />
-    {% if theme_license_url %}{% trans license_file=theme_license_url %}See <a href="{{ license_file }}">History and License</a> for more information.{% endtrans %}<br />{% endif %}
-    {% if theme_hosted_on %}{% trans hosted_on=theme_hosted_on %}Hosted on {{ hosted_on }}.{% endtrans %}<br />{% endif %}
+    {% if theme_license_url %}
+      {% trans license_file=theme_license_url %}See <a href="{{ license_file }}">History and License</a> for more information.{% endtrans %}<br />
+    {% endif %}
+    {% if theme_hosted_on %}
+      {% trans hosted_on=theme_hosted_on %}Hosted on {{ hosted_on }}.{% endtrans %}<br />
+    {% endif %}
     <br />
 
     {% include "footerdonate.html" %}
@@ -152,7 +162,9 @@ <h3>{{ _('Navigation') }}</h3>
     {%- if last_updated %}
       {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
     {%- endif %}
-    {% if theme_issues_url %}{% trans %}<a href="{{ theme_issues_url }}">Found a bug</a>?{% endtrans %}{% endif %}
+    {% if theme_issues_url %}
+      {% trans %}<a href="{{ theme_issues_url }}">Found a bug</a>?{% endtrans %}
+    {% endif %}
     <br />
 
     {% trans sphinx_version=sphinx_version|e %}Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %}

From 7d6728357b1a80b616f65054ad105eb7e2bd9048 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Tue, 26 Mar 2024 15:07:01 +0200
Subject: [PATCH 115/175] Link to kitchen sink demo in README

---
 README.rst | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/README.rst b/README.rst
index 5055bad..3d78430 100644
--- a/README.rst
+++ b/README.rst
@@ -29,3 +29,7 @@ Preview
 See a demo of the CPython docs using this theme:
 
 - https://python-docs-theme-previews.readthedocs.io
+
+The kitchen sink is a showcase of every Sphinx feature:
+
+- https://sphinx-themes.org/sample-sites/python-docs-theme/kitchen-sink/

From 6e87b15170662ecf21ee2955cc916f2c3785489d Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Tue, 26 Mar 2024 15:09:26 +0200
Subject: [PATCH 116/175] Convert README to Markdown

---
 README.rst => README.md | 17 +++++++----------
 pyproject.toml          |  2 +-
 2 files changed, 8 insertions(+), 11 deletions(-)
 rename README.rst => README.md (69%)

diff --git a/README.rst b/README.md
similarity index 69%
rename from README.rst
rename to README.md
index 3d78430..f77b491 100644
--- a/README.rst
+++ b/README.md
@@ -1,5 +1,4 @@
-Python Docs Sphinx Theme
-=========================
+# Python Docs Sphinx Theme
 
 This is the theme for the Python documentation.
 
@@ -10,21 +9,19 @@ projects if you so choose, but please keep in mind that in doing so you're also
 choosing to accept some of the responsibility for maintaining that collective
 trust.
 
-To use the theme, install it into your docs build environment via ``pip``
+To use the theme, install it into your docs build environment via `pip`
 (preferably in a virtual environment).
 
 
-Configuration options
----------------------
+## Configuration options
 
-To use this theme, add the following to ``conf.py``:
+To use this theme, add the following to `conf.py`:
 
-- ``html_theme = 'python_docs_theme'``
+- `html_theme = 'python_docs_theme'`
 
-- ``html_sidebars``, defaults taken from https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_sidebars
+- `html_sidebars`, defaults taken from https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-html_sidebars
 
-Preview
--------
+## Preview
 
 See a demo of the CPython docs using this theme:
 
diff --git a/pyproject.toml b/pyproject.toml
index fc5f551..c376bbd 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -8,7 +8,7 @@ requires = [
 name = "python-docs-theme"
 version = "2024.3"
 description = "The Sphinx theme for the CPython docs and related projects"
-readme = "README.rst"
+readme = "README.md"
 license.file = "LICENSE"
 authors = [{name = "PyPA", email = "distutils-sig@python.org"}]
 requires-python = ">=3.8"

From 30bd94ff6985256f5bfef03c7f76e1e95cceace6 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Fri, 29 Mar 2024 00:19:50 +0200
Subject: [PATCH 117/175] Add coloured sidebars to
 versionadded/changed/deprecated

---
 python_docs_theme/static/pydoctheme.css      | 47 ++++++++++++++++++++
 python_docs_theme/static/pydoctheme_dark.css |  7 +++
 2 files changed, 54 insertions(+)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 39c4e33..5ca6d3e 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -622,3 +622,50 @@ div.genindex-jumpbox a {
         margin-top: -2em;
     }
 }
+
+/* Version change directives */
+:root {
+    --versionadded: rgb(41 100 51);
+    --versionchanged: rgb(133 72 38);
+    --deprecated: rgb(159 49 51);
+
+    --versionadded-border: rgb(79 196 100);
+    --versionchanged-border: rgb(244, 227, 76);
+    --deprecated-border: rgb(244, 76, 78);
+}
+
+div.versionadded,
+div.versionchanged,
+div.deprecated,
+div.deprecated-removed {
+    border-left: 3px solid;
+    padding: 0 1rem;
+}
+
+div.versionadded {
+    border-left-color: var(--versionadded-border);
+}
+
+div.versionchanged {
+    border-left-color: var(--versionchanged-border);
+}
+
+div.deprecated,
+div.deprecated-removed,
+div.versionremoved {
+    border-left-color: var(--deprecated-border);
+}
+
+div.versionadded .versionmodified {
+    color: var(--versionadded);
+}
+
+div.versionchanged .versionmodified {
+    color: var(--versionchanged);
+}
+
+div.deprecated .versionmodified,
+div.deprecated-removed .versionmodified,
+div.versionremoved .versionmodified {
+    color: var(--deprecated);
+}
diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index 758d3de..cae6eae 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -140,3 +140,10 @@ img.invert-in-dark-mode {
 .sig.cpp .k, .sig.cpp .kt {
     color: #5283ff;
 }
+
+/* Version change directives */
+:root {
+    --versionadded: rgb(79 196 100);
+    --versionchanged: rgb(244, 227, 76);
+    --deprecated: rgb(244, 76, 78);
+}

From 059b2c7503ae946e7649d85a9b10c2a42cb21be9 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Tue, 9 Apr 2024 00:54:22 +0300
Subject: [PATCH 118/175] Use system font stack

---
 python_docs_theme/static/pydoctheme.css | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 5ca6d3e..0d7840c 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -333,7 +333,7 @@ div.footer a:hover {
 
 dl > dt span ~ em,
 .sig {
-    font-family: ui-monospace, "Cascadia Mono", "Segoe UI Mono", "Liberation Mono", Menlo, Monaco, Consolas, monospace;
+    font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
 }
 
 .toctree-wrapper ul {

From ab06c27dd08dd3e4206987bf996516eb97bb7245 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Tue, 9 Apr 2024 10:46:27 +0300
Subject: [PATCH 119/175] Prepare 2024.4 release

---
 CHANGELOG.rst  | 10 ++++++++++
 pyproject.toml |  2 +-
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 07f7d4c..6ba1903 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,16 @@
 Changelog
 =========
 
+`2024.4 <https://github.com/python/python-docs-theme/releases/tag/v2024.4>`_
+----------------------------------------------------------------------------
+
+- Add colour to version change directives (#185)
+    Contributed by Hugo van Kemenade
+- Only show 'Last updated on ...' when ``last_updated`` defined (#183)
+    Contributed by Hugo van Kemenade
+- Use system font stack for all code (#186)
+    Contributed by Hugo van Kemenade
+
 `2024.3 <https://github.com/python/python-docs-theme/releases/tag/v2024.3>`_
 ----------------------------------------------------------------------------
 
diff --git a/pyproject.toml b/pyproject.toml
index c376bbd..9e46db6 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,7 +6,7 @@ requires = [
 
 [project]
 name = "python-docs-theme"
-version = "2024.3"
+version = "2024.4"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.md"
 license.file = "LICENSE"

From ade62ae0ffa98b09fb08a3c5566fce6cb6df63c8 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Wed, 17 Apr 2024 21:20:34 +0300
Subject: [PATCH 120/175] Use different colour for 'Return value: Borrowed
 reference'

---
 python_docs_theme/static/pydoctheme.css      | 12 +++++++++++-
 python_docs_theme/static/pydoctheme_dark.css |  7 +++++--
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 0d7840c..58993a1 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -323,8 +323,18 @@ div.footer a:hover {
     color: #0095c4;
 }
 
+/* C API return value annotations */
+:root {
+    --refcount: #060;
+    --refcount-return-borrowed-ref: rgb(133 72 38);
+}
+
 .refcount {
-    color: #060;
+    color: var(--refcount);
+}
+
+.refcount.return_borrowed_ref {
+    color: var(--refcount-return-borrowed-ref)
 }
 
 .stableabi {
diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index cae6eae..0601808 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -79,8 +79,11 @@ table.docutils th {
     background-color: #424242;
 }
 
-.refcount {
-    color: #afa;
+/* C API return value annotations */
+
+:root {
+    --refcount: #afa;
+    --refcount-return-borrowed-ref: rgb(244, 227, 76);
 }
 
 .stableabi {

From 1b90d930db31ded3b025087ece8779f06c4d63a5 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Wed, 17 Apr 2024 14:05:14 +0300
Subject: [PATCH 121/175] Replace Flake8 with Ruff

---
 .flake8                       |  2 --
 .pre-commit-config.yaml       | 31 +++++++------------------------
 pyproject.toml                | 32 +++++++++++++++++++++++++++++---
 python_docs_theme/__init__.py |  2 +-
 4 files changed, 37 insertions(+), 30 deletions(-)
 delete mode 100644 .flake8

diff --git a/.flake8 b/.flake8
deleted file mode 100644
index 2bcd70e..0000000
--- a/.flake8
+++ /dev/null
@@ -1,2 +0,0 @@
-[flake8]
-max-line-length = 88
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 70b4e19..4837461 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,34 +1,17 @@
 repos:
-  - repo: https://github.com/asottile/pyupgrade
-    rev: v3.15.0
+  - repo: https://github.com/astral-sh/ruff-pre-commit
+    rev: v0.4.0
     hooks:
-      - id: pyupgrade
-        args: [--py38-plus]
+      - id: ruff
+        args: [--exit-non-zero-on-fix]
 
   - repo: https://github.com/psf/black-pre-commit-mirror
-    rev: 24.1.1
+    rev: 24.4.0
     hooks:
       - id: black
 
-  - repo: https://github.com/PyCQA/isort
-    rev: 5.13.2
-    hooks:
-      - id: isort
-
-  - repo: https://github.com/PyCQA/flake8
-    rev: 7.0.0
-    hooks:
-      - id: flake8
-        additional_dependencies:
-          [flake8-2020, flake8-implicit-str-concat, flake8-logging]
-
-  - repo: https://github.com/pre-commit/pygrep-hooks
-    rev: v1.10.0
-    hooks:
-      - id: python-check-blanket-noqa
-
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v4.5.0
+    rev: v4.6.0
     hooks:
       - id: check-case-conflict
       - id: check-merge-conflict
@@ -39,7 +22,7 @@ repos:
       - id: trailing-whitespace
 
   - repo: https://github.com/tox-dev/pyproject-fmt
-    rev: 1.7.0
+    rev: 1.8.0
     hooks:
       - id: pyproject-fmt
         args: [--max-supported-python=3.13]
diff --git a/pyproject.toml b/pyproject.toml
index 9e46db6..9e0a47f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -44,6 +44,32 @@ include = [
     "python_docs_theme/",
 ]
 
-[tool.isort]
-add_imports = "from __future__ import annotations"
-profile = "black"
+[tool.ruff]
+fix = true
+
+[tool.ruff.lint]
+select = [
+  "C4",     # flake8-comprehensions
+  "E",      # pycodestyle errors
+  "F",      # pyflakes errors
+  "I",      # isort
+  "ISC",    # flake8-implicit-str-concat
+  "LOG",    # flake8-logging
+  "PGH",    # pygrep-hooks
+  "PYI",    # flake8-pyi
+  "RUF100", # unused noqa (yesqa)
+  "RUF022", # unsorted-dunder-all
+  "UP",     # pyupgrade
+  "W",      # pycodestyle warnings
+  "YTT",    # flake8-2020
+]
+ignore = [
+  "E203",   # Whitespace before ':'
+  "E221",   # Multiple spaces before operator
+  "E226",   # Missing whitespace around arithmetic operator
+  "E241",   # Multiple spaces after ','
+]
+
+
+[tool.ruff.lint.isort]
+required-imports = ["from __future__ import annotations"]
diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py
index 7747675..7b9df30 100644
--- a/python_docs_theme/__init__.py
+++ b/python_docs_theme/__init__.py
@@ -24,7 +24,7 @@ def _asset_hash(path: str) -> str:
 def _add_asset_hashes(static: list[str], add_digest_to: list[str]) -> None:
     for asset in add_digest_to:
         index = static.index(asset)
-        static[index].filename = _asset_hash(asset)  # type: ignore
+        static[index].filename = _asset_hash(asset)  # type: ignore[attr-defined]
 
 
 def _html_page_context(

From 2f1bf7c966a09e06f20415657be417f6b1e3d2c7 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Wed, 17 Apr 2024 14:08:48 +0300
Subject: [PATCH 122/175] Add check-jsonschema to lint YAML and actionlint for
 GitHub Actions

---
 .pre-commit-config.yaml | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 4837461..42cd35e 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -21,6 +21,17 @@ repos:
       - id: end-of-file-fixer
       - id: trailing-whitespace
 
+  - repo: https://github.com/python-jsonschema/check-jsonschema
+    rev: 0.28.2
+    hooks:
+      - id: check-dependabot
+      - id: check-github-workflows
+
+  - repo: https://github.com/rhysd/actionlint
+    rev: v1.6.27
+    hooks:
+      - id: actionlint
+
   - repo: https://github.com/tox-dev/pyproject-fmt
     rev: 1.8.0
     hooks:

From fce4eb415c5f3de7ebebfeed872616180f936632 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Wed, 17 Apr 2024 14:09:27 +0300
Subject: [PATCH 123/175] Fix shellcheck SC2046: Quote this to prevent word
 splitting

---
 .github/workflows/tests.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 1b58d3e..70182f0 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -34,9 +34,9 @@ jobs:
           --build-root ./build_root
           --www-root ./www
           --log-directory ./logs
-          --group $(id -g)
+          --group "$(id -g)"
           --skip-cache-invalidation
-          --theme $(pwd)
+          --theme "$(pwd)"
           --language en
           --branch ${{ matrix.branch }}
       - name: Show logs

From 8b3ec0b508c91dcd69a1b38dd4b4f7e10e12eef8 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Wed, 24 Apr 2024 12:40:21 +0300
Subject: [PATCH 124/175] Refactor version change colours into variables, also
 use for refcounts

---
 python_docs_theme/static/pydoctheme.css      | 26 ++++++++++++++------
 python_docs_theme/static/pydoctheme_dark.css | 23 +++++++++--------
 2 files changed, 31 insertions(+), 18 deletions(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 58993a1..09e4b3f 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -1,5 +1,15 @@
 @import url('classic.css');
 
+/* Common colours */
+:root {
+    --good-color: rgb(41 100 51);
+    --good-border: rgb(79 196 100);
+    --middle-color: rgb(133 72 38);
+    --middle-border: rgb(244, 227, 76);
+    --bad-color: rgb(159 49 51);
+    --bad-border: rgb(244, 76, 78);
+}
+
 /* unset some styles from the classic stylesheet */
 div.document,
 div.body,
@@ -325,8 +335,8 @@ div.footer a:hover {
 
 /* C API return value annotations */
 :root {
-    --refcount: #060;
-    --refcount-return-borrowed-ref: rgb(133 72 38);
+    --refcount: var(--good-color);
+    --refcount-return-borrowed-ref: var(--middle-color);
 }
 
 .refcount {
@@ -635,13 +645,13 @@ div.genindex-jumpbox a {
 
 /* Version change directives */
 :root {
-    --versionadded: rgb(41 100 51);
-    --versionchanged: rgb(133 72 38);
-    --deprecated: rgb(159 49 51);
+    --versionadded: var(--good-color);
+    --versionchanged: var(--middle-color);
+    --deprecated: var(--bad-color);
 
-    --versionadded-border: rgb(79 196 100);
-    --versionchanged-border: rgb(244, 227, 76);
-    --deprecated-border: rgb(244, 76, 78);
+    --versionadded-border: var(--good-border);
+    --versionchanged-border: var(--middle-border);
+    --deprecated-border: var(--bad-border);
 }
 
 div.versionadded,
diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index 0601808..ea2a256 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -1,3 +1,13 @@
+/* Common colours */
+:root {
+    --good-color: rgb(79 196 100);
+    --good-border: var(--good-color);
+    --middle-color: rgb(244, 227, 76);
+    --middle-border: var(--middle-color);
+    --bad-color: rgb(244, 76, 78);
+    --bad-border: var(--bad-color);
+}
+
 
 /* Browser elements */
 :root {
@@ -79,13 +89,6 @@ table.docutils th {
     background-color: #424242;
 }
 
-/* C API return value annotations */
-
-:root {
-    --refcount: #afa;
-    --refcount-return-borrowed-ref: rgb(244, 227, 76);
-}
-
 .stableabi {
     color: #bbf;
 }
@@ -146,7 +149,7 @@ img.invert-in-dark-mode {
 
 /* Version change directives */
 :root {
-    --versionadded: rgb(79 196 100);
-    --versionchanged: rgb(244, 227, 76);
-    --deprecated: rgb(244, 76, 78);
+    --versionadded: var(--good-color);
+    --versionchanged: var(--middle-color);
+    --deprecated: var(--bad-color);
 }

From 20af5ec11f8b09e8a3d73a380da2678e8da35542 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sun, 9 Jun 2024 21:46:47 +0300
Subject: [PATCH 125/175] Add backgrounds and borders to admonitions

---
 python_docs_theme/static/pydoctheme.css      | 73 ++++++++++++++++++--
 python_docs_theme/static/pydoctheme_dark.css | 22 ++++++
 2 files changed, 90 insertions(+), 5 deletions(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 09e4b3f..a908372 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -242,7 +242,74 @@ div.body pre {
     border: 1px solid #ac9;
 }
 
-div.body div.admonition,
+/* Admonitions */
+:root {
+    --admonition-background: #eee;
+    --admonition-border: #ccc;
+    --attention-background: #bbddff5c;
+    --attention-border: #0000ff36;
+    --caution-background: #ffc;
+    --caution-border: #dddd66;
+    --danger-background: #ffe4e4;
+    --danger-border: red;
+    --error-background: #ffe4e4;
+    --error-border: red;
+    --hint-background: #bfc;
+    --hint-border: green;
+    --seealso-background: #ffc;
+    --seealso-border: #dddd66;
+    --tip-background: #bfc;
+    --tip-border: green;
+    --warning-background: #ffe4e4;
+    --warning-border: red;
+}
+
+div.body div.admonition {
+    background-color: var(--admonition-background);
+    border-radius: 3px;
+    border: 1px solid var(--admonition-border);
+}
+
+div.body div.admonition.attention {
+    background-color: var(--attention-background);
+    border-color: var(--attention-border);
+}
+
+div.body div.admonition.caution {
+    background-color: var(--caution-background);
+    border-color: var(--caution-border);
+}
+
+div.body div.admonition.danger {
+    background-color: var(--danger-background);
+    border-color: var(--danger-border);
+}
+
+div.body div.admonition.error {
+    background-color: var(--error-background);
+    border-color: var(--error-border);
+}
+
+div.body div.admonition.hint {
+    background-color: var(--hint-background);
+    border-color: var(--hint-border);
+}
+
+div.body div.admonition.seealso {
+    background-color: var(--seealso-background);
+    border-color: var(--seealso-border);
+}
+
+div.body div.admonition.tip {
+    background-color: var(--tip-background);
+    border-color: var(--tip-border);
+}
+
+div.body div.admonition.warning {
+    background-color: var(--warning-background);
+    border-color: var(--warning-border);
+}
+
 div.body div.impl-detail {
     border-radius: 3px;
 }
@@ -251,10 +318,6 @@ div.body div.impl-detail > p {
     margin: 0;
 }
 
-div.body div.seealso {
-    border: 1px solid #dddd66;
-}
-
 div.body a {
     color: #0072aa;
 }
diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index ea2a256..91c0c19 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -113,6 +113,28 @@ div.warning {
     background-color: rgba(255, 0, 0, 0.5);
 }
 
+/* Admonitions */
+:root {
+    --admonition-background: rgba(255, 255, 255, 0.1);
+    --admonition-border: currentColor;
+    --attention-background: rgba(255, 255, 255, 0.1);
+    --attention-border: currentColor;
+    --caution-background: rgba(255, 255, 0, 0.1);
+    --caution-border: #dd6;
+    --danger-background: rgba(255, 0, 0, 0.2);
+    --danger-border: #f66;
+    --error-background: rgba(255, 0, 0, 0.2);
+    --error-border: #f66;
+    --hint-background: #0044117a;
+    --hint-border: green;
+    --seealso-background: rgba(255, 255, 0, 0.1);
+    --seealso-border: #dd6;
+    --tip-background: #0044117a;
+    --tip-border: green;
+    --warning-background: rgba(255, 0, 0, 0.2);
+    --warning-border: #f66;
+}
+
 aside.topic,
 div.topic,
 div.note,

From 5e08e29029bf69eedcf88a78881a8d7b8957c115 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Mon, 10 Jun 2024 14:37:18 +0300
Subject: [PATCH 126/175] #dfd instead of #bfc for tip background

---
 python_docs_theme/static/pydoctheme.css | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index a908372..2425ae8 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -254,11 +254,11 @@ div.body pre {
     --danger-border: red;
     --error-background: #ffe4e4;
     --error-border: red;
-    --hint-background: #bfc;
+    --hint-background: #dfd;
     --hint-border: green;
     --seealso-background: #ffc;
     --seealso-border: #dddd66;
-    --tip-background: #bfc;
+    --tip-background: #dfd;
     --tip-border: green;
     --warning-background: #ffe4e4;
     --warning-border: red;

From 887784591e505b2efdacc25e093f4ebfe5b10ed6 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Mon, 10 Jun 2024 14:37:47 +0300
Subject: [PATCH 127/175] Re-order to keep colours together

---
 python_docs_theme/static/pydoctheme.css | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 2425ae8..b0bc688 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -266,8 +266,8 @@ div.body pre {
 
 div.body div.admonition {
     background-color: var(--admonition-background);
-    border-radius: 3px;
     border: 1px solid var(--admonition-border);
+    border-radius: 3px;
 }
 
 div.body div.admonition.attention {

From 93453ad35ade74a61b327a0c5c38c45e4fe568fb Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Thu, 13 Jun 2024 18:36:36 +0300
Subject: [PATCH 128/175] Specify both color and background-color in case
 inherited colour changes and conflicts with background-color

---
 python_docs_theme/static/pydoctheme.css      | 2 ++
 python_docs_theme/static/pydoctheme_dark.css | 1 +
 2 files changed, 3 insertions(+)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index b0bc688..78794e8 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -246,6 +246,7 @@ div.body pre {
 :root {
     --admonition-background: #eee;
     --admonition-border: #ccc;
+    --admonition-color: black;
     --attention-background: #bbddff5c;
     --attention-border: #0000ff36;
     --caution-background: #ffc;
@@ -268,6 +269,7 @@ div.body div.admonition {
     background-color: var(--admonition-background);
     border: 1px solid var(--admonition-border);
     border-radius: 3px;
+    color: var(--admonition-color);
 }
 
 div.body div.admonition.attention {
diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index 91c0c19..20bbd32 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -117,6 +117,7 @@ div.warning {
 :root {
     --admonition-background: rgba(255, 255, 255, 0.1);
     --admonition-border: currentColor;
+    --admonition-color: rgba(255, 255, 255, 0.87);
     --attention-background: rgba(255, 255, 255, 0.1);
     --attention-border: currentColor;
     --caution-background: rgba(255, 255, 0, 0.1);

From 338ed557b78a19a4f2cf080093dd7b6ee2aa17dc Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Thu, 13 Jun 2024 18:41:25 +0300
Subject: [PATCH 129/175] Replace rgba with hex, prefer short hex

---
 python_docs_theme/static/pydoctheme.css      |  4 ++--
 python_docs_theme/static/pydoctheme_dark.css | 18 +++++++++---------
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 78794e8..662d987 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -250,7 +250,7 @@ div.body pre {
     --attention-background: #bbddff5c;
     --attention-border: #0000ff36;
     --caution-background: #ffc;
-    --caution-border: #dddd66;
+    --caution-border: #dd6;
     --danger-background: #ffe4e4;
     --danger-border: red;
     --error-background: #ffe4e4;
@@ -258,7 +258,7 @@ div.body pre {
     --hint-background: #dfd;
     --hint-border: green;
     --seealso-background: #ffc;
-    --seealso-border: #dddd66;
+    --seealso-border: #dd6;
     --tip-background: #dfd;
     --tip-border: green;
     --warning-background: #ffe4e4;
diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index 20bbd32..4509960 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -115,25 +115,25 @@ div.warning {
 
 /* Admonitions */
 :root {
-    --admonition-background: rgba(255, 255, 255, 0.1);
+    --admonition-background: #ffffff1a;
     --admonition-border: currentColor;
-    --admonition-color: rgba(255, 255, 255, 0.87);
-    --attention-background: rgba(255, 255, 255, 0.1);
+    --admonition-color: #ffffffde;
+    --attention-background: #ffffff1a;
     --attention-border: currentColor;
-    --caution-background: rgba(255, 255, 0, 0.1);
+    --caution-background: #ffff001a;
     --caution-border: #dd6;
-    --danger-background: rgba(255, 0, 0, 0.2);
+    --danger-background: #f003;
     --danger-border: #f66;
-    --error-background: rgba(255, 0, 0, 0.2);
+    --error-background: #f003;
     --error-border: #f66;
     --hint-background: #0044117a;
     --hint-border: green;
-    --seealso-background: rgba(255, 255, 0, 0.1);
+    --seealso-background: #ffff001a;
     --seealso-border: #dd6;
     --tip-background: #0044117a;
     --tip-border: green;
-    --warning-background: rgba(255, 0, 0, 0.2);
-    --warning-border: #f66;
+    --warning-background: #ff000033;
+    --warning-border: #ff6666;
 }
 
 aside.topic,

From 781573ea77b35c9fc2f98c25da04da6902e75bc8 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Mon, 24 Jun 2024 16:11:50 +0300
Subject: [PATCH 130/175] Prepare 2024.6 release

---
 CHANGELOG.rst  | 8 ++++++++
 pyproject.toml | 2 +-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 6ba1903..0ed7628 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,14 @@
 Changelog
 =========
 
+`2024.6 <https://github.com/python/python-docs-theme/releases/tag/v2024.6>`_
+----------------------------------------------------------------------------
+
+- Add backgrounds and borders to admonitions (#190)
+    Contributed by Hugo van Kemenade
+- Use different colour for 'Return value: Borrowed reference' (#188)
+    Contributed by Hugo van Kemenade
+
 `2024.4 <https://github.com/python/python-docs-theme/releases/tag/v2024.4>`_
 ----------------------------------------------------------------------------
 
diff --git a/pyproject.toml b/pyproject.toml
index 9e0a47f..4571a41 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,7 +6,7 @@ requires = [
 
 [project]
 name = "python-docs-theme"
-version = "2024.4"
+version = "2024.6"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.md"
 license.file = "LICENSE"

From d271fac02cae550e8b051ac358465ad0894ec9fd Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@gmail.com>
Date: Thu, 1 Aug 2024 18:10:26 -0300
Subject: [PATCH 131/175] Add script for handling translations

---
 babel.cfg       |   1 +
 babel_runner.py | 108 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 109 insertions(+)
 create mode 100644 babel.cfg
 create mode 100755 babel_runner.py

diff --git a/babel.cfg b/babel.cfg
new file mode 100644
index 0000000..692580d
--- /dev/null
+++ b/babel.cfg
@@ -0,0 +1 @@
+[jinja2: **.html]
diff --git a/babel_runner.py b/babel_runner.py
new file mode 100755
index 0000000..a6359af
--- /dev/null
+++ b/babel_runner.py
@@ -0,0 +1,108 @@
+#!/usr/bin/venv python3
+"""Script for handling translations with Babel"""
+
+import argparse
+import os
+import subprocess
+import tomllib
+
+PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))
+
+# Global variables used by pybabel below
+DOMAIN = "messages"
+COPYRIGHT_HOLDER = "Python Software Foundation"
+LOCALES_DIR = os.path.relpath(os.path.join(PROJECT_DIR, "locales"))
+POT_FILE = os.path.relpath(os.path.join(LOCALES_DIR, f"{DOMAIN}.pot"), PROJECT_DIR)
+SOURCE_DIR = os.path.relpath(
+    os.path.join(PROJECT_DIR, "python_docs_theme"), PROJECT_DIR
+)
+MAPPING_FILE = os.path.relpath(os.path.join(PROJECT_DIR, "babel.cfg"), PROJECT_DIR)
+
+
+def get_project_info() -> dict:
+    """Retrieve project's info to populate the message catalog template"""
+    with open(os.path.join(PROJECT_DIR, "pyproject.toml"), "rb") as f:
+        data = tomllib.load(f)
+    return data["project"]
+
+
+def extract_messages():
+    """Extract messages from all source files into template file"""
+    os.makedirs(LOCALES_DIR, exist_ok=True)
+    project_data = get_project_info()
+    subprocess.run(
+        [
+            "pybabel",
+            "extract",
+            "-F",
+            MAPPING_FILE,
+            "--copyright-holder",
+            COPYRIGHT_HOLDER,
+            "--project",
+            project_data["name"],
+            "--version",
+            project_data["version"],
+            "--msgid-bugs-address",
+            project_data["urls"]["Issue tracker"],
+            "-o",
+            POT_FILE,
+            SOURCE_DIR,
+        ],
+        check=True,
+    )
+
+
+def init_locale(locale: str):
+    """Initialize a new locale based on existing"""
+    cmd = ["pybabel", "init", "-i", POT_FILE, "-d", LOCALES_DIR, "-l", locale]
+    subprocess.run(cmd, check=True)
+
+
+def update_catalogs(locale: str):
+    """Update translations from existing message catalogs"""
+    cmd = ["pybabel", "update", "-i", POT_FILE, "-d", LOCALES_DIR]
+    if locale != "":
+        cmd.append(["-l", locale])
+    subprocess.run(cmd, check=True)
+
+
+def compile_catalogs(locale: str):
+    """Compile existing message catalogs"""
+    cmd = ["pybabel", "compile", "-d", LOCALES_DIR]
+    if locale != "":
+        cmd.append(["-l", locale])
+    subprocess.run(cmd, check=True)
+
+
+def main():
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument(
+        "command",
+        choices=["init", "extract", "update", "compile"],
+        help="command to be executed",
+    )
+    parser.add_argument(
+        "-l",
+        "--locale",
+        help="language code (needed for init, optional for update and compile)",
+    )
+
+    args = parser.parse_args()
+    locale = args.locale if args.locale else ""
+
+    os.chdir(PROJECT_DIR)
+
+    if args.command == "extract":
+        extract_messages()
+    elif args.command == "init":
+        if locale == "":
+            parser.error("init requires passing the --locale option")
+        init_locale(locale)
+    elif args.command == "update":
+        update_catalogs(locale)
+    elif args.command == "compile":
+        compile_catalogs(locale)
+
+
+if __name__ == "__main__":
+    main()

From 634a20c0dc9d80f63f41352e74c4994cd6b47dfc Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@gmail.com>
Date: Fri, 2 Aug 2024 13:31:25 -0300
Subject: [PATCH 132/175] Make ruff tests happy

---
 babel_runner.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/babel_runner.py b/babel_runner.py
index a6359af..d447a16 100755
--- a/babel_runner.py
+++ b/babel_runner.py
@@ -1,9 +1,11 @@
 #!/usr/bin/venv python3
 """Script for handling translations with Babel"""
+from __future__ import annotations
 
 import argparse
 import os
 import subprocess
+
 import tomllib
 
 PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))

From a809821c3fd5b06a081188c5c50f542da1676716 Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@gmail.com>
Date: Fri, 2 Aug 2024 15:29:19 -0300
Subject: [PATCH 133/175] Rename mapping file to .babel.cfg

---
 babel.cfg => .babel.cfg | 0
 babel_runner.py         | 2 +-
 2 files changed, 1 insertion(+), 1 deletion(-)
 rename babel.cfg => .babel.cfg (100%)

diff --git a/babel.cfg b/.babel.cfg
similarity index 100%
rename from babel.cfg
rename to .babel.cfg
diff --git a/babel_runner.py b/babel_runner.py
index d447a16..039522f 100755
--- a/babel_runner.py
+++ b/babel_runner.py
@@ -18,7 +18,7 @@
 SOURCE_DIR = os.path.relpath(
     os.path.join(PROJECT_DIR, "python_docs_theme"), PROJECT_DIR
 )
-MAPPING_FILE = os.path.relpath(os.path.join(PROJECT_DIR, "babel.cfg"), PROJECT_DIR)
+MAPPING_FILE = os.path.relpath(os.path.join(PROJECT_DIR, ".babel.cfg"), PROJECT_DIR)
 
 
 def get_project_info() -> dict:

From adf715c41dec595f51de89d752c21511f5ad7a6d Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@gmail.com>
Date: Fri, 2 Aug 2024 17:19:10 -0300
Subject: [PATCH 134/175] Forbid initializing existent po

---
 babel_runner.py | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/babel_runner.py b/babel_runner.py
index 039522f..ba5e351 100755
--- a/babel_runner.py
+++ b/babel_runner.py
@@ -29,7 +29,7 @@ def get_project_info() -> dict:
 
 
 def extract_messages():
-    """Extract messages from all source files into template file"""
+    """Extract messages from all source files into message catalog template"""
     os.makedirs(LOCALES_DIR, exist_ok=True)
     project_data = get_project_info()
     subprocess.run(
@@ -55,7 +55,11 @@ def extract_messages():
 
 
 def init_locale(locale: str):
-    """Initialize a new locale based on existing"""
+    """Initialize a new locale based on existing message catalog template"""
+    pofile = os.path.join(LOCALES_DIR, locale, "LC_MESSAGES", f"{DOMAIN}.po")
+    if os.path.exists(pofile):
+        print(f"There is already a message catalog for locale {locale}, skipping.")
+        return
     cmd = ["pybabel", "init", "-i", POT_FILE, "-d", LOCALES_DIR, "-l", locale]
     subprocess.run(cmd, check=True)
 

From 66820a55a24cc6188f52ca1f79c2272833e84f32 Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@gmail.com>
Date: Fri, 2 Aug 2024 17:21:13 -0300
Subject: [PATCH 135/175] Extend instead of append list for locale arg

---
 babel_runner.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/babel_runner.py b/babel_runner.py
index ba5e351..386f34b 100755
--- a/babel_runner.py
+++ b/babel_runner.py
@@ -68,7 +68,7 @@ def update_catalogs(locale: str):
     """Update translations from existing message catalogs"""
     cmd = ["pybabel", "update", "-i", POT_FILE, "-d", LOCALES_DIR]
     if locale != "":
-        cmd.append(["-l", locale])
+        cmd.extend(["-l", locale])
     subprocess.run(cmd, check=True)
 
 
@@ -76,7 +76,7 @@ def compile_catalogs(locale: str):
     """Compile existing message catalogs"""
     cmd = ["pybabel", "compile", "-d", LOCALES_DIR]
     if locale != "":
-        cmd.append(["-l", locale])
+        cmd.extend(["-l", locale])
     subprocess.run(cmd, check=True)
 
 

From 6b6f0d2787d30670a00ef4552d24ad1ebe5c7d3a Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@gmail.com>
Date: Fri, 2 Aug 2024 17:22:24 -0300
Subject: [PATCH 136/175] Add translation tests to tests.yml

---
 .github/workflows/tests.yml | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 70182f0..c551104 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -48,3 +48,36 @@ jobs:
         with:
           name: doc-html-${{ matrix.branch }}
           path: www/
+
+  translations:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        os: ["ubuntu-latest", "windows-latest"]
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/setup-python@v5
+        with:
+          python-version: 3
+          allow-prereleases: true
+          cache: pip
+      - name: Install dependencies
+        run: |
+          pip install -U pip setuptools
+          pip install Babel jinja2
+      - run: python3 babel_runner.py extract
+      - run: python3 babel_runner.py init -l pt_BR
+      - run: python3 babel_runner.py update
+      - run: python3 babel_runner.py update -l pt_BR
+      - run: python3 babel_runner.py compile
+      - run: python3 babel_runner.py compile -l pt_BR
+      - name: Print .pot file
+        shell: bash
+        run: cat locales/messages.pot
+      - name: Print .po file
+        shell: bash
+        run: cat locales/pt_BR/LC_MESSAGES/messages.po
+      - name: list files in locales dir
+        shell: bash
+        run: ls -R locales/

From 2d84c4befd1a6acb2840b603f42cb56a2ef367ab Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sat, 3 Aug 2024 19:00:53 +0300
Subject: [PATCH 137/175] Test Python 3.13

---
 .github/workflows/tests.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 70182f0..5f50a1f 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -12,7 +12,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        branch: ["origin/main", "3.12", "3.11", "3.10"]
+        branch: ["origin/main", "3.13", "3.12", "3.11", "3.10"]
     steps:
       - uses: actions/checkout@v4
       - uses: actions/setup-python@v5

From 7878f4e51fbd79310a1cf7d8653ea5c20817fa11 Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@users.noreply.github.com>
Date: Sat, 3 Aug 2024 14:45:45 -0300
Subject: [PATCH 138/175] Use python instead of python3 to run babel_runner.py

Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
---
 .github/workflows/tests.yml | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index c551104..62b1f3c 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -64,14 +64,14 @@ jobs:
           cache: pip
       - name: Install dependencies
         run: |
-          pip install -U pip setuptools
-          pip install Babel jinja2
-      - run: python3 babel_runner.py extract
-      - run: python3 babel_runner.py init -l pt_BR
-      - run: python3 babel_runner.py update
-      - run: python3 babel_runner.py update -l pt_BR
-      - run: python3 babel_runner.py compile
-      - run: python3 babel_runner.py compile -l pt_BR
+          pip install --upgrade pip
+          pip install Babel jinja2 setuptools
+      - run: python babel_runner.py extract
+      - run: python babel_runner.py init -l pt_BR
+      - run: python babel_runner.py update
+      - run: python babel_runner.py update -l pt_BR
+      - run: python babel_runner.py compile
+      - run: python babel_runner.py compile -l pt_BR
       - name: Print .pot file
         shell: bash
         run: cat locales/messages.pot

From 1fbd5d07695a6b6b58fd114c8de6d5133e9073a8 Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@gmail.com>
Date: Sat, 3 Aug 2024 15:25:06 -0300
Subject: [PATCH 139/175] Replace os with pahlib in babe_runner.py

---
 babel_runner.py | 33 +++++++++++++++------------------
 1 file changed, 15 insertions(+), 18 deletions(-)

diff --git a/babel_runner.py b/babel_runner.py
index 386f34b..ede0657 100755
--- a/babel_runner.py
+++ b/babel_runner.py
@@ -3,34 +3,32 @@
 from __future__ import annotations
 
 import argparse
-import os
 import subprocess
+from pathlib import Path
 
 import tomllib
 
-PROJECT_DIR = os.path.dirname(os.path.abspath(__file__))
+PROJECT_DIR = Path(__file__).resolve().parent
 
-# Global variables used by pybabel below
+# Global variables used by pybabel below (paths relative to PROJECT_DIR)
 DOMAIN = "messages"
 COPYRIGHT_HOLDER = "Python Software Foundation"
-LOCALES_DIR = os.path.relpath(os.path.join(PROJECT_DIR, "locales"))
-POT_FILE = os.path.relpath(os.path.join(LOCALES_DIR, f"{DOMAIN}.pot"), PROJECT_DIR)
-SOURCE_DIR = os.path.relpath(
-    os.path.join(PROJECT_DIR, "python_docs_theme"), PROJECT_DIR
-)
-MAPPING_FILE = os.path.relpath(os.path.join(PROJECT_DIR, ".babel.cfg"), PROJECT_DIR)
+LOCALES_DIR = "locales"
+POT_FILE = Path(LOCALES_DIR, f"{DOMAIN}.pot")
+SOURCE_DIR = "python_docs_theme"
+MAPPING_FILE = ".babel.cfg"
 
 
 def get_project_info() -> dict:
     """Retrieve project's info to populate the message catalog template"""
-    with open(os.path.join(PROJECT_DIR, "pyproject.toml"), "rb") as f:
+    with open(Path(PROJECT_DIR / "pyproject.toml"), "rb") as f:
         data = tomllib.load(f)
     return data["project"]
 
 
 def extract_messages():
     """Extract messages from all source files into message catalog template"""
-    os.makedirs(LOCALES_DIR, exist_ok=True)
+    Path(PROJECT_DIR, LOCALES_DIR).mkdir(parents=True, exist_ok=True)
     project_data = get_project_info()
     subprocess.run(
         [
@@ -50,18 +48,19 @@ def extract_messages():
             POT_FILE,
             SOURCE_DIR,
         ],
+        cwd=PROJECT_DIR,
         check=True,
     )
 
 
 def init_locale(locale: str):
     """Initialize a new locale based on existing message catalog template"""
-    pofile = os.path.join(LOCALES_DIR, locale, "LC_MESSAGES", f"{DOMAIN}.po")
-    if os.path.exists(pofile):
+    pofile = PROJECT_DIR / LOCALES_DIR / locale / "LC_MESSAGES" / f"{DOMAIN}.po"
+    if pofile.exists():
         print(f"There is already a message catalog for locale {locale}, skipping.")
         return
     cmd = ["pybabel", "init", "-i", POT_FILE, "-d", LOCALES_DIR, "-l", locale]
-    subprocess.run(cmd, check=True)
+    subprocess.run(cmd, cwd=PROJECT_DIR, check=True)
 
 
 def update_catalogs(locale: str):
@@ -69,7 +68,7 @@ def update_catalogs(locale: str):
     cmd = ["pybabel", "update", "-i", POT_FILE, "-d", LOCALES_DIR]
     if locale != "":
         cmd.extend(["-l", locale])
-    subprocess.run(cmd, check=True)
+    subprocess.run(cmd, cwd=PROJECT_DIR, check=True)
 
 
 def compile_catalogs(locale: str):
@@ -77,7 +76,7 @@ def compile_catalogs(locale: str):
     cmd = ["pybabel", "compile", "-d", LOCALES_DIR]
     if locale != "":
         cmd.extend(["-l", locale])
-    subprocess.run(cmd, check=True)
+    subprocess.run(cmd, cwd=PROJECT_DIR, check=True)
 
 
 def main():
@@ -96,8 +95,6 @@ def main():
     args = parser.parse_args()
     locale = args.locale if args.locale else ""
 
-    os.chdir(PROJECT_DIR)
-
     if args.command == "extract":
         extract_messages()
     elif args.command == "init":

From e3e08ebcc6c1201302d73808c7fd8d324501af55 Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@gmail.com>
Date: Sat, 3 Aug 2024 15:58:51 -0300
Subject: [PATCH 140/175] Add tomli import to support python<3.11

---
 babel_runner.py  | 10 +++++++++-
 requirements.txt |  5 +++++
 2 files changed, 14 insertions(+), 1 deletion(-)
 create mode 100644 requirements.txt

diff --git a/babel_runner.py b/babel_runner.py
index ede0657..4d51b64 100755
--- a/babel_runner.py
+++ b/babel_runner.py
@@ -6,7 +6,15 @@
 import subprocess
 from pathlib import Path
 
-import tomllib
+try:
+    import tomllib
+except ImportError:
+    try:
+        import tomli as tomllib
+    except ImportError as ie:
+        raise ImportError(
+            "tomli or tomllib is required to parse pyproject.toml"
+        ) from ie
 
 PROJECT_DIR = Path(__file__).resolve().parent
 
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..18e6c17
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,5 @@
+# for babel_runner.py
+setuptools
+Babel
+Jinja2
+tomli; python_version < "3.10"

From a845398dc335c9cc37113caee4952d7f47e0913f Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@gmail.com>
Date: Sat, 3 Aug 2024 16:01:18 -0300
Subject: [PATCH 141/175] CI test for minimum supported python version

---
 .github/workflows/tests.yml | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 62b1f3c..e79a125 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -55,17 +55,19 @@ jobs:
       fail-fast: false
       matrix:
         os: ["ubuntu-latest", "windows-latest"]
+        # Test minimum supported and latest stable from 3.x series
+        python-version: ["3.8", "3"]
     steps:
       - uses: actions/checkout@v4
       - uses: actions/setup-python@v5
         with:
-          python-version: 3
+          python-version: ${{ matrix.python-version }}
           allow-prereleases: true
           cache: pip
       - name: Install dependencies
         run: |
           pip install --upgrade pip
-          pip install Babel jinja2 setuptools
+          pip install -r requirements.txt
       - run: python babel_runner.py extract
       - run: python babel_runner.py init -l pt_BR
       - run: python babel_runner.py update

From 7919df824437a82a42401bb05e0b76ccfa2516e6 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Mon, 23 Sep 2024 11:47:40 -0700
Subject: [PATCH 142/175] Drop support for Python 3.8 (#197)

---
 pyproject.toml                | 3 +--
 python_docs_theme/__init__.py | 4 ++--
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/pyproject.toml b/pyproject.toml
index 4571a41..09e9bc3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -11,7 +11,7 @@ description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.md"
 license.file = "LICENSE"
 authors = [{name = "PyPA", email = "distutils-sig@python.org"}]
-requires-python = ">=3.8"
+requires-python = ">=3.9"
 classifiers = [
   "Development Status :: 5 - Production/Stable",
   "Framework :: Sphinx :: Theme",
@@ -20,7 +20,6 @@ classifiers = [
   "Operating System :: OS Independent",
   "Programming Language :: Python",
   "Programming Language :: Python :: 3 :: Only",
-  "Programming Language :: Python :: 3.8",
   "Programming Language :: Python :: 3.9",
   "Programming Language :: Python :: 3.10",
   "Programming Language :: Python :: 3.11",
diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py
index 7b9df30..0ee7d25 100644
--- a/python_docs_theme/__init__.py
+++ b/python_docs_theme/__init__.py
@@ -2,7 +2,7 @@
 
 import hashlib
 import os
-from functools import lru_cache
+from functools import cache
 from pathlib import Path
 from typing import Any
 
@@ -12,7 +12,7 @@
 THEME_PATH = Path(__file__).parent.resolve()
 
 
-@lru_cache(maxsize=None)
+@cache
 def _asset_hash(path: str) -> str:
     """Append a `?digest=` to an url based on the file content."""
     full_path = THEME_PATH / path.replace("_static/", "static/")

From beb9aab7089a2a5b6667d3ba9a6f9d2064a55464 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Fri, 27 Sep 2024 14:21:55 -0700
Subject: [PATCH 143/175] Generate digital attestations for PyPI (PEP 740)

---
 .github/workflows/pypi-package.yml | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/.github/workflows/pypi-package.yml b/.github/workflows/pypi-package.yml
index c7acc05..744d49b 100644
--- a/.github/workflows/pypi-package.yml
+++ b/.github/workflows/pypi-package.yml
@@ -11,6 +11,9 @@ on:
 permissions:
   contents: read
 
+env:
+  FORCE_COLOR: 1
+
 jobs:
   # Always build & lint package.
   build-package:
@@ -45,3 +48,5 @@ jobs:
 
       - name: Upload package to PyPI
         uses: pypa/gh-action-pypi-publish@release/v1
+        with:
+          attestations: true

From 7d634de6e440729c5823affb06644de0c61dda19 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Fri, 27 Sep 2024 14:18:00 -0700
Subject: [PATCH 144/175] Update pre-commit

---
 .pre-commit-config.yaml | 12 ++++++------
 pyproject.toml          | 31 ++++++++++++-------------------
 2 files changed, 18 insertions(+), 25 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 42cd35e..071ad40 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,12 +1,12 @@
 repos:
   - repo: https://github.com/astral-sh/ruff-pre-commit
-    rev: v0.4.0
+    rev: v0.6.8
     hooks:
       - id: ruff
         args: [--exit-non-zero-on-fix]
 
   - repo: https://github.com/psf/black-pre-commit-mirror
-    rev: 24.4.0
+    rev: 24.8.0
     hooks:
       - id: black
 
@@ -22,24 +22,24 @@ repos:
       - id: trailing-whitespace
 
   - repo: https://github.com/python-jsonschema/check-jsonschema
-    rev: 0.28.2
+    rev: 0.29.2
     hooks:
       - id: check-dependabot
       - id: check-github-workflows
 
   - repo: https://github.com/rhysd/actionlint
-    rev: v1.6.27
+    rev: v1.7.2
     hooks:
       - id: actionlint
 
   - repo: https://github.com/tox-dev/pyproject-fmt
-    rev: 1.8.0
+    rev: 2.2.4
     hooks:
       - id: pyproject-fmt
         args: [--max-supported-python=3.13]
 
   - repo: https://github.com/abravalheri/validate-pyproject
-    rev: v0.16
+    rev: v0.20.2
     hooks:
       - id: validate-pyproject
 
diff --git a/pyproject.toml b/pyproject.toml
index 09e9bc3..d7c764d 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,7 +1,7 @@
 [build-system]
 build-backend = "flit_core.buildapi"
 requires = [
-  "flit_core>=3.7",
+  "flit-core>=3.7",
 ]
 
 [project]
@@ -10,7 +10,7 @@ version = "2024.6"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.md"
 license.file = "LICENSE"
-authors = [{name = "PyPA", email = "distutils-sig@python.org"}]
+authors = [ { name = "PyPA", email = "distutils-sig@python.org" } ]
 requires-python = ">=3.9"
 classifiers = [
   "Development Status :: 5 - Production/Stable",
@@ -32,22 +32,18 @@ urls.Code = "https://github.com/python/python-docs-theme"
 urls.Download = "https://pypi.org/project/python-docs-theme/"
 urls.Homepage = "https://github.com/python/python-docs-theme/"
 urls."Issue tracker" = "https://github.com/python/python-docs-theme/issues"
-[project.entry-points."sphinx.html_themes"]
-python_docs_theme = 'python_docs_theme'
+entry-points."sphinx.html_themes".python_docs_theme = "python_docs_theme"
 
 [tool.flit.module]
 name = "python_docs_theme"
 
 [tool.flit.sdist]
-include = [
-    "python_docs_theme/",
-]
+include = [ "python_docs_theme/" ]
 
 [tool.ruff]
 fix = true
 
-[tool.ruff.lint]
-select = [
+lint.select = [
   "C4",     # flake8-comprehensions
   "E",      # pycodestyle errors
   "F",      # pyflakes errors
@@ -56,19 +52,16 @@ select = [
   "LOG",    # flake8-logging
   "PGH",    # pygrep-hooks
   "PYI",    # flake8-pyi
-  "RUF100", # unused noqa (yesqa)
   "RUF022", # unsorted-dunder-all
+  "RUF100", # unused noqa (yesqa)
   "UP",     # pyupgrade
   "W",      # pycodestyle warnings
   "YTT",    # flake8-2020
 ]
-ignore = [
-  "E203",   # Whitespace before ':'
-  "E221",   # Multiple spaces before operator
-  "E226",   # Missing whitespace around arithmetic operator
-  "E241",   # Multiple spaces after ','
+lint.ignore = [
+  "E203", # Whitespace before ':'
+  "E221", # Multiple spaces before operator
+  "E226", # Missing whitespace around arithmetic operator
+  "E241", # Multiple spaces after ','
 ]
-
-
-[tool.ruff.lint.isort]
-required-imports = ["from __future__ import annotations"]
+lint.isort.required-imports = [ "from __future__ import annotations" ]

From bd7c059d3f233b7e4c7035aba798135dcdf816e8 Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@users.noreply.github.com>
Date: Mon, 28 Oct 2024 08:23:22 -0300
Subject: [PATCH 145/175] Apply suggestions from code review

Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Co-authored-by: Ezio Melotti <ezio.melotti@gmail.com>
---
 .github/workflows/tests.yml |  2 +-
 babel_runner.py             | 19 ++++++++++---------
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 1c77087..a4dd522 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -56,7 +56,7 @@ jobs:
       matrix:
         os: ["ubuntu-latest", "windows-latest"]
         # Test minimum supported and latest stable from 3.x series
-        python-version: ["3.8", "3"]
+        python-version: ["3.9", "3"]
     steps:
       - uses: actions/checkout@v4
       - uses: actions/setup-python@v5
diff --git a/babel_runner.py b/babel_runner.py
index 4d51b64..b90b57b 100755
--- a/babel_runner.py
+++ b/babel_runner.py
@@ -34,7 +34,7 @@ def get_project_info() -> dict:
     return data["project"]
 
 
-def extract_messages():
+def extract_messages() -> None:
     """Extract messages from all source files into message catalog template"""
     Path(PROJECT_DIR, LOCALES_DIR).mkdir(parents=True, exist_ok=True)
     project_data = get_project_info()
@@ -61,7 +61,7 @@ def extract_messages():
     )
 
 
-def init_locale(locale: str):
+def init_locale(locale: str) -> None:
     """Initialize a new locale based on existing message catalog template"""
     pofile = PROJECT_DIR / LOCALES_DIR / locale / "LC_MESSAGES" / f"{DOMAIN}.po"
     if pofile.exists():
@@ -71,23 +71,23 @@ def init_locale(locale: str):
     subprocess.run(cmd, cwd=PROJECT_DIR, check=True)
 
 
-def update_catalogs(locale: str):
+def update_catalogs(locale: str) -> None:
     """Update translations from existing message catalogs"""
     cmd = ["pybabel", "update", "-i", POT_FILE, "-d", LOCALES_DIR]
-    if locale != "":
+    if locale:
         cmd.extend(["-l", locale])
     subprocess.run(cmd, cwd=PROJECT_DIR, check=True)
 
 
-def compile_catalogs(locale: str):
+def compile_catalogs(locale: str) -> None:
     """Compile existing message catalogs"""
     cmd = ["pybabel", "compile", "-d", LOCALES_DIR]
-    if locale != "":
+    if locale:
         cmd.extend(["-l", locale])
     subprocess.run(cmd, cwd=PROJECT_DIR, check=True)
 
 
-def main():
+def main() -> None:
     parser = argparse.ArgumentParser(description=__doc__)
     parser.add_argument(
         "command",
@@ -97,16 +97,17 @@ def main():
     parser.add_argument(
         "-l",
         "--locale",
+        default="",
         help="language code (needed for init, optional for update and compile)",
     )
 
     args = parser.parse_args()
-    locale = args.locale if args.locale else ""
+    locale = args.locale
 
     if args.command == "extract":
         extract_messages()
     elif args.command == "init":
-        if locale == "":
+        if not locale:
             parser.error("init requires passing the --locale option")
         init_locale(locale)
     elif args.command == "update":

From 65a0360a32bce266ff8b9db49507347c5dbe3d1c Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@users.noreply.github.com>
Date: Mon, 28 Oct 2024 08:51:19 -0300
Subject: [PATCH 146/175] Remove possibly existing translation file

Otherwise init command will be skipped
---
 .github/workflows/tests.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index a4dd522..b0ce07c 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -68,6 +68,8 @@ jobs:
         run: |
           pip install --upgrade pip
           pip install -r requirements.txt
+      - name: Remove locale file for testing
+        run: rm -rf locales/pt_BR/
       - run: python babel_runner.py extract
       - run: python babel_runner.py init -l pt_BR
       - run: python babel_runner.py update

From 69ab91731e63dc625ff1f7405391ac4b6354dc35 Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@users.noreply.github.com>
Date: Mon, 28 Oct 2024 09:25:07 -0300
Subject: [PATCH 147/175] Add shell bash to success in Windows

---
 .github/workflows/tests.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index b0ce07c..ace177e 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -69,6 +69,7 @@ jobs:
           pip install --upgrade pip
           pip install -r requirements.txt
       - name: Remove locale file for testing
+        shell: bash
         run: rm -rf locales/pt_BR/
       - run: python babel_runner.py extract
       - run: python babel_runner.py init -l pt_BR

From 2aa3a04d209e7496e2c3f08d5a2db68b83fbf9fb Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle <rffontenelle@users.noreply.github.com>
Date: Mon, 28 Oct 2024 09:37:18 -0300
Subject: [PATCH 148/175] Swap init and extract to be didactic

As one need to have POT before initializing PO
---
 babel_runner.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/babel_runner.py b/babel_runner.py
index b90b57b..da4001c 100755
--- a/babel_runner.py
+++ b/babel_runner.py
@@ -91,7 +91,7 @@ def main() -> None:
     parser = argparse.ArgumentParser(description=__doc__)
     parser.add_argument(
         "command",
-        choices=["init", "extract", "update", "compile"],
+        choices=["extract", "init", "update", "compile"],
         help="command to be executed",
     )
     parser.add_argument(

From 782f57ee5a4f98f0c46d70c83735d381c069217f Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Mon, 28 Oct 2024 17:50:38 +0200
Subject: [PATCH 149/175] Prepare 2024.10 release

---
 CHANGELOG.rst  | 12 ++++++++++++
 pyproject.toml |  2 +-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 0ed7628..2f4ac84 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,18 @@
 Changelog
 =========
 
+`2024.10 <https://github.com/python/python-docs-theme/releases/tag/v2024.10>`_
+------------------------------------------------------------------------------
+
+- Add support for Python 3.13 (#196)
+    Contributed by Hugo van Kemenade
+- Drop support for Python 3.8 (#197)
+    Contributed by Hugo van Kemenade
+- Add script for handling translations (#195)
+    Contributed by Rafael Fontenelle
+- Generate digital attestations for PyPI (PEP 740) (#198)
+    Contributed by Hugo van Kemenade
+
 `2024.6 <https://github.com/python/python-docs-theme/releases/tag/v2024.6>`_
 ----------------------------------------------------------------------------
 
diff --git a/pyproject.toml b/pyproject.toml
index d7c764d..a39131e 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,7 +6,7 @@ requires = [
 
 [project]
 name = "python-docs-theme"
-version = "2024.6"
+version = "2024.10"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.md"
 license.file = "LICENSE"

From 4716bf7843b528c43f4d6a2b1528eea09d80aefb Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Tue, 29 Oct 2024 04:19:47 +0200
Subject: [PATCH 150/175] Use org CoC instead of repo copy (#200)

---
 code_of_conduct.rst | 13 -------------
 1 file changed, 13 deletions(-)
 delete mode 100644 code_of_conduct.rst

diff --git a/code_of_conduct.rst b/code_of_conduct.rst
deleted file mode 100644
index 4bc6630..0000000
--- a/code_of_conduct.rst
+++ /dev/null
@@ -1,13 +0,0 @@
-Code of Conduct
-===============
-
-Please note that all interactions on
-`Python Software Foundation <https://www.python.org/psf-landing/>`__-supported
-infrastructure is `covered
-<https://www.python.org/psf/records/board/minutes/2014-01-06/#management-of-the-psfs-web-properties>`__
-by the `PSF Code of Conduct <https://www.python.org/psf/codeofconduct/>`__,
-which includes all infrastructure used in the development of Python itself
-(e.g. mailing lists, issue trackers, GitHub, etc.).
-
-In general this means everyone is expected to be open, considerate, and
-respectful of others no matter what their position is within the project.

From 44e4813d04ff9306493304d3e734f09ed843f328 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Tue, 29 Oct 2024 16:37:46 +0200
Subject: [PATCH 151/175] Fix tag links

---
 CHANGELOG.rst | 68 +++++++++++++++++++++++++--------------------------
 1 file changed, 34 insertions(+), 34 deletions(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 2f4ac84..17d4f42 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,8 +1,8 @@
 Changelog
 =========
 
-`2024.10 <https://github.com/python/python-docs-theme/releases/tag/v2024.10>`_
-------------------------------------------------------------------------------
+`2024.10 <https://github.com/python/python-docs-theme/releases/tag/2024.10>`_
+-----------------------------------------------------------------------------
 
 - Add support for Python 3.13 (#196)
     Contributed by Hugo van Kemenade
@@ -13,16 +13,16 @@ Changelog
 - Generate digital attestations for PyPI (PEP 740) (#198)
     Contributed by Hugo van Kemenade
 
-`2024.6 <https://github.com/python/python-docs-theme/releases/tag/v2024.6>`_
-----------------------------------------------------------------------------
+`2024.6 <https://github.com/python/python-docs-theme/releases/tag/2024.6>`_
+---------------------------------------------------------------------------
 
 - Add backgrounds and borders to admonitions (#190)
     Contributed by Hugo van Kemenade
 - Use different colour for 'Return value: Borrowed reference' (#188)
     Contributed by Hugo van Kemenade
 
-`2024.4 <https://github.com/python/python-docs-theme/releases/tag/v2024.4>`_
-----------------------------------------------------------------------------
+`2024.4 <https://github.com/python/python-docs-theme/releases/tag/2024.4>`_
+---------------------------------------------------------------------------
 
 - Add colour to version change directives (#185)
     Contributed by Hugo van Kemenade
@@ -31,24 +31,24 @@ Changelog
 - Use system font stack for all code (#186)
     Contributed by Hugo van Kemenade
 
-`2024.3 <https://github.com/python/python-docs-theme/releases/tag/v2024.3>`_
-----------------------------------------------------------------------------
+`2024.3 <https://github.com/python/python-docs-theme/releases/tag/2024.3>`_
+---------------------------------------------------------------------------
 
 - Modernise font: use system font stack to improve text readability and webpage performance (#174)
     Contributed by Hugo van Kemenade
 - Remove incorrect CSS property (#178)
     Contributed by Kerim Kabirov
 
-`2024.2 <https://github.com/python/python-docs-theme/releases/tag/v2024.2>`_
-----------------------------------------------------------------------------
+`2024.2 <https://github.com/python/python-docs-theme/releases/tag/2024.2>`_
+---------------------------------------------------------------------------
 
 - Do not underline navigation links (#169)
    Contributed by Hugo van Kemenade
 - Only apply underline offset to code formatting for underline visibility (#171)
    Contributed by Hugo van Kemenade
 
-`2024.1 <https://github.com/python/python-docs-theme/releases/tag/v2024.1>`_
-----------------------------------------------------------------------------
+`2024.1 <https://github.com/python/python-docs-theme/releases/tag/2024.1>`_
+---------------------------------------------------------------------------
 
 - Underline links for readability and a11y (#160, #166)
    Contributed by Hugo van Kemenade
@@ -59,14 +59,14 @@ Changelog
 - Dark mode: fix contrast of footer highlight (#162)
    Contributed by Hugo van Kemenade
 
-`2023.9 <https://github.com/python/python-docs-theme/releases/tag/v2023.9>`_
-----------------------------------------------------------------------------
+`2023.9 <https://github.com/python/python-docs-theme/releases/tag/2023.9>`_
+---------------------------------------------------------------------------
 
 - Focus search box when pressing slash (#153)
    Contributed by Hugo van Kemenade
 
-`2023.8 <https://github.com/python/python-docs-theme/releases/tag/v2023.8>`_
-----------------------------------------------------------------------------
+`2023.8 <https://github.com/python/python-docs-theme/releases/tag/2023.8>`_
+---------------------------------------------------------------------------
 
 - Add Python 3.12 and 3.13 classifiers (#147)
    Contributed by Hugo van Kemenade
@@ -75,8 +75,8 @@ Changelog
 - Restore the menu on mobile devices (inadvertently broken in 2023.7) (#146)
    Contributed by Hugo van Kemenade
 
-`2023.7 <https://github.com/python/python-docs-theme/releases/tag/v2023.7>`_
-----------------------------------------------------------------------------
+`2023.7 <https://github.com/python/python-docs-theme/releases/tag/2023.7>`_
+---------------------------------------------------------------------------
 
 - Fix compatibility with Sphinx 7.1 (#137)
    Contributed by Pradyun Gedam
@@ -91,8 +91,8 @@ Changelog
 - Test with Python 3.12 (#140)
    Contributed by Hugo van Kemenade
 
-`2023.5 <https://github.com/python/python-docs-theme/releases/tag/v2023.5>`_
-----------------------------------------------------------------------------
+`2023.5 <https://github.com/python/python-docs-theme/releases/tag/2023.5>`_
+---------------------------------------------------------------------------
 
 - Add a dark theme. (#44)
    Contributed by Nils K
@@ -106,14 +106,14 @@ Changelog
    Contributed by Hugo van Kemenade
 
 
-`2023.3.1 <https://github.com/python/python-docs-theme/releases/tag/v2023.3.1>`_
---------------------------------------------------------------------------------
+`2023.3.1 <https://github.com/python/python-docs-theme/releases/tag/2023.3.1>`_
+-------------------------------------------------------------------------------
 
 - Skip cache-busting for old Sphinx #113
 
 
-`2023.3 <https://github.com/python/python-docs-theme/releases/tag/v2023.3>`_
-----------------------------------------------------------------------------
+`2023.3 <https://github.com/python/python-docs-theme/releases/tag/2023.3>`_
+---------------------------------------------------------------------------
 
 - Fix problem with monospace rendering in Vivaldi #104
 - Fix mobile nav obstructing content #96
@@ -121,30 +121,30 @@ Changelog
 - Append a hash ?digest to CSS files for cache-busting #108
 
 
-`2022.1 <https://github.com/python/python-docs-theme/releases/tag/v2022.1>`_
-----------------------------------------------------------------------------------
+`2022.1 <https://github.com/python/python-docs-theme/releases/tag/2022.1>`_
+----------------------------------------------------------------------------
 
 - Add a configuration for license URL. (#90)
 - Exclude the floating navbar from CHM help. (#84)
 - Make sidebar scrollable and sticky (on modern browsers) (#91)
 
 
-`2021.11.1 <https://github.com/python/python-docs-theme/releases/tag/v2021.11.1>`_
------------------------------------------------------------------------------------
+`2021.11.1 <https://github.com/python/python-docs-theme/releases/tag/2021.11.1>`_
+----------------------------------------------------------------------------------
 
 - Fix monospace again, on buggy Google Chrome (#87)
    Contributed by Tushar Sadhwani
 
 
-`2021.11 <https://github.com/python/python-docs-theme/releases/tag/v2021.11>`_
--------------------------------------------------------------------------------
+`2021.11 <https://github.com/python/python-docs-theme/releases/tag/2021.11>`_
+------------------------------------------------------------------------------
 
 - Fix monospace on buggy Google Chrome (#85)
    Contributed by Tushar Sadhwani
 
 
-`2021.8 <https://github.com/python/python-docs-theme/releases/tag/v2021.8>`_
-------------------------------------------------------------------------------
+`2021.8 <https://github.com/python/python-docs-theme/releases/tag/2021.8>`_
+-----------------------------------------------------------------------------
 
 - Add the copyright_url variable in the theme (#67)
    Contributed by jablonskidev
@@ -156,8 +156,8 @@ Changelog
    Contributed by Olga Bulat
 
 
-`2021.5 <https://github.com/python/python-docs-theme/releases/tag/v2021.5>`_
-------------------------------------------------------------------------------
+`2021.5 <https://github.com/python/python-docs-theme/releases/tag/2021.5>`_
+-----------------------------------------------------------------------------
 
 - Make the theme responsive (#46)
    Contributed by Olga Bulat.

From b53f3a4c42f41c6618fa1f710805a14c2fa7f07f Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Thu, 31 Oct 2024 22:45:26 +0200
Subject: [PATCH 152/175] Hide header and search bar when printing

---
 python_docs_theme/static/pydoctheme.css | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 662d987..0f6f8d3 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -754,3 +754,10 @@ div.deprecated-removed .versionmodified,
 div.versionremoved .versionmodified {
     color: var(--deprecated);
 }
+
+/* Hide header when printing */
+@media print {
+    div.mobile-nav {
+        display: none;
+    }
+}

From 55754b66086bec518ca2c7f5d33fcb58b0525100 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sun, 15 Dec 2024 16:20:36 +0200
Subject: [PATCH 153/175] Prepare 2024.12 release (#207)

---
 CHANGELOG.rst  | 6 ++++++
 pyproject.toml | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 17d4f42..47eef33 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,12 @@
 Changelog
 =========
 
+`2024.12 <https://github.com/python/python-docs-theme/releases/tag/2024.12>`_
+-----------------------------------------------------------------------------
+
+- Hide header and search bar when printing (#204)
+    Contributed by Hugo van Kemenade
+
 `2024.10 <https://github.com/python/python-docs-theme/releases/tag/2024.10>`_
 -----------------------------------------------------------------------------
 
diff --git a/pyproject.toml b/pyproject.toml
index a39131e..9b7c60f 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,7 +6,7 @@ requires = [
 
 [project]
 name = "python-docs-theme"
-version = "2024.10"
+version = "2024.12"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.md"
 license.file = "LICENSE"

From 3d34296b29435c82ec370532345336c4bedf1453 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sun, 26 Jan 2025 20:53:15 +0200
Subject: [PATCH 154/175] Fix PR preview links (#215)

---
 .github/workflows/documentation-links.yml | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/.github/workflows/documentation-links.yml b/.github/workflows/documentation-links.yml
index f05df37..a4de7dc 100644
--- a/.github/workflows/documentation-links.yml
+++ b/.github/workflows/documentation-links.yml
@@ -6,9 +6,6 @@ on:
   pull_request_target:
     types:
       - opened
-    paths:
-    - 'Doc/**'
-    - '.github/workflows/doc.yml'
 
 permissions:
   pull-requests: write

From 01d5bcf0524663037ae68bbcea1248ce5238ce00 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Date: Tue, 28 Jan 2025 01:40:31 +0000
Subject: [PATCH 155/175] Note minimum requirements for Sphinx (#216)

---
 .pre-commit-config.yaml       | 14 +++++++-------
 README.md                     |  1 +
 pyproject.toml                |  4 ++++
 python_docs_theme/__init__.py |  2 ++
 4 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 071ad40..f964364 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,17 +1,17 @@
 repos:
   - repo: https://github.com/astral-sh/ruff-pre-commit
-    rev: v0.6.8
+    rev: v0.9.3
     hooks:
       - id: ruff
         args: [--exit-non-zero-on-fix]
 
   - repo: https://github.com/psf/black-pre-commit-mirror
-    rev: 24.8.0
+    rev: 24.10.0
     hooks:
       - id: black
 
   - repo: https://github.com/pre-commit/pre-commit-hooks
-    rev: v4.6.0
+    rev: v5.0.0
     hooks:
       - id: check-case-conflict
       - id: check-merge-conflict
@@ -22,24 +22,24 @@ repos:
       - id: trailing-whitespace
 
   - repo: https://github.com/python-jsonschema/check-jsonschema
-    rev: 0.29.2
+    rev: 0.31.0
     hooks:
       - id: check-dependabot
       - id: check-github-workflows
 
   - repo: https://github.com/rhysd/actionlint
-    rev: v1.7.2
+    rev: v1.7.7
     hooks:
       - id: actionlint
 
   - repo: https://github.com/tox-dev/pyproject-fmt
-    rev: 2.2.4
+    rev: v2.5.0
     hooks:
       - id: pyproject-fmt
         args: [--max-supported-python=3.13]
 
   - repo: https://github.com/abravalheri/validate-pyproject
-    rev: v0.20.2
+    rev: v0.23
     hooks:
       - id: validate-pyproject
 
diff --git a/README.md b/README.md
index f77b491..24308f7 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
 # Python Docs Sphinx Theme
 
 This is the theme for the Python documentation.
+It requires Python 3.9 or newer and Sphinx 3.4 or newer.
 
 Note that when adopting this theme, you're also borrowing an element of the
 trust and credibility established by the CPython core developers over the
diff --git a/pyproject.toml b/pyproject.toml
index 9b7c60f..1b34d90 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -28,6 +28,10 @@ classifiers = [
   "Topic :: Documentation",
   "Topic :: Software Development :: Documentation",
 ]
+dependencies = [
+  "sphinx>=3.4",
+]
+
 urls.Code = "https://github.com/python/python-docs-theme"
 urls.Download = "https://pypi.org/project/python-docs-theme/"
 urls.Homepage = "https://github.com/python/python-docs-theme/"
diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py
index 0ee7d25..295c1c5 100644
--- a/python_docs_theme/__init__.py
+++ b/python_docs_theme/__init__.py
@@ -53,6 +53,8 @@ def _html_page_context(
 
 
 def setup(app):
+    app.require_sphinx("3.4")
+
     current_dir = os.path.abspath(os.path.dirname(__file__))
     app.add_html_theme("python_docs_theme", current_dir)
 

From 2f15ba657cba97c078a2b2869f1b387bfa24618e Mon Sep 17 00:00:00 2001
From: "Tomas R." <tomas.roun8@gmail.com>
Date: Mon, 3 Feb 2025 19:32:00 +0100
Subject: [PATCH 156/175] Horizontally centre the sidebar collapse button
 (#219)

---
 python_docs_theme/static/pydoctheme.css | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 0f6f8d3..bf92e92 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -191,6 +191,9 @@ div.sphinxsidebar input[type='text'] {
 }
 
 #sidebarbutton {
+    display: flex;
+    justify-content: center;
+    align-items: center;
     /* Sphinx 4.x and earlier compat */
     height: 100%;
     background-color: #CCCCCC;
@@ -200,19 +203,12 @@ div.sphinxsidebar input[type='text'] {
     cursor: pointer;
     padding-top: 1px;
     float: right;
-    display: table;
     /* after Sphinx 4.x and earlier is dropped, only the below is needed */
     width: 12px;
     border-radius: 0 5px 5px 0;
     border-left: none;
 }
 
-#sidebarbutton span {
-    /* Sphinx 4.x and earlier compat */
-    display: table-cell;
-    vertical-align: middle;
-}
-
 #sidebarbutton:hover {
     background-color: #AAAAAA;
 }

From b6a1724264c4b4937d973eb73a0472ce9023e291 Mon Sep 17 00:00:00 2001
From: "Tomas R." <tomas.roun8@gmail.com>
Date: Tue, 4 Feb 2025 13:50:41 +0100
Subject: [PATCH 157/175] Make sidebar width more flexible (#218)

---
 python_docs_theme/static/pydoctheme.css | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index bf92e92..8b7b2cf 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -140,6 +140,8 @@ span.pre {
 }
 
 div.sphinxsidebar {
+    display: flex;
+    width: min(25vw, 350px);
     float: none;
     position: sticky;
     top: 0;
@@ -156,13 +158,17 @@ div.sphinxsidebar h4 {
     margin-top: 1.5em;
 }
 
+div.bodywrapper {
+    margin-left: min(25vw, 350px);
+}
+
 div.sphinxsidebarwrapper {
-    width: 217px;
     box-sizing: border-box;
     height: 100%;
     overflow-x: hidden;
     overflow-y: auto;
-    float: left;
+    float: none;
+    flex-grow: 1;
 }
 
 div.sphinxsidebarwrapper > h3:first-child {
@@ -202,9 +208,10 @@ div.sphinxsidebar input[type='text'] {
     font-size: 1.2em;
     cursor: pointer;
     padding-top: 1px;
-    float: right;
+    float: none;
     /* after Sphinx 4.x and earlier is dropped, only the below is needed */
     width: 12px;
+    min-width: 12px;
     border-radius: 0 5px 5px 0;
     border-left: none;
 }
@@ -485,7 +492,7 @@ div.genindex-jumpbox a {
         margin-inline-end: 0;
     }
     /* Remove sidebar and top related bar */
-    div.related, .sphinxsidebar {
+    div.related, div.sphinxsidebar {
         display: none;
     }
     /* Anchorlinks are not hidden by fixed-positioned navbar when scrolled to */

From 482321225e574a6c09770a48196a9e4dd99f0b0b Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Date: Tue, 4 Feb 2025 13:42:07 +0000
Subject: [PATCH 158/175] Set ``__version__`` in the runtime package (#222)

* Set ``__version__`` in the runtime package
* Return the version key in ``setup()``
* Add static type annotations to ``setup()``
* Fix the Python version for ``tomli``
* read ``__version__`` from ``__init__.py``

Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
---
 CONTRIBUTING.rst              |  2 +-
 babel_runner.py               | 23 ++++++++++++++++++++---
 pyproject.toml                |  3 ++-
 python_docs_theme/__init__.py | 19 +++++++++++++------
 requirements.txt              |  2 +-
 5 files changed, 37 insertions(+), 12 deletions(-)

diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 2533e96..c85b77c 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -2,7 +2,7 @@ How to release
 --------------
 
 - Update ``CHANGELOG.rst``
-- Bump version (YYYY.MM) in ``pyproject.toml``
+- Bump version (YYYY.MM) in ``python_docs_theme/__init__.py``
 - Commit
 - Push to check tests pass on
   `GitHub Actions <https://github.com/python/python-docs-theme/actions>`__
diff --git a/babel_runner.py b/babel_runner.py
index da4001c..ee5af16 100755
--- a/babel_runner.py
+++ b/babel_runner.py
@@ -3,6 +3,7 @@
 from __future__ import annotations
 
 import argparse
+import ast
 import subprocess
 from pathlib import Path
 
@@ -17,6 +18,8 @@
         ) from ie
 
 PROJECT_DIR = Path(__file__).resolve().parent
+PYPROJECT_TOML = PROJECT_DIR / "pyproject.toml"
+INIT_PY = PROJECT_DIR / "python_docs_theme" / "__init__.py"
 
 # Global variables used by pybabel below (paths relative to PROJECT_DIR)
 DOMAIN = "messages"
@@ -29,9 +32,23 @@
 
 def get_project_info() -> dict:
     """Retrieve project's info to populate the message catalog template"""
-    with open(Path(PROJECT_DIR / "pyproject.toml"), "rb") as f:
-        data = tomllib.load(f)
-    return data["project"]
+    pyproject_text = PYPROJECT_TOML.read_text(encoding="utf-8")
+    project_data = tomllib.loads(pyproject_text)["project"]
+
+    # read __version__ from __init__.py
+    for child in ast.parse(INIT_PY.read_bytes()).body:
+        if not isinstance(child, ast.Assign):
+            continue
+        target = child.targets[0]
+        if not isinstance(target, ast.Name) or target.id != "__version__":
+            continue
+        version_node = child.value
+        if not isinstance(version_node, ast.Constant):
+            continue
+        project_data["version"] = version_node.value
+        break
+
+    return project_data
 
 
 def extract_messages() -> None:
diff --git a/pyproject.toml b/pyproject.toml
index 1b34d90..7eb1cc2 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -6,7 +6,6 @@ requires = [
 
 [project]
 name = "python-docs-theme"
-version = "2024.12"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.md"
 license.file = "LICENSE"
@@ -28,6 +27,8 @@ classifiers = [
   "Topic :: Documentation",
   "Topic :: Software Development :: Documentation",
 ]
+dynamic = [ "version" ]
+
 dependencies = [
   "sphinx>=3.4",
 ]
diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py
index 295c1c5..d8dd2c7 100644
--- a/python_docs_theme/__init__.py
+++ b/python_docs_theme/__init__.py
@@ -1,15 +1,22 @@
 from __future__ import annotations
 
 import hashlib
-import os
 from functools import cache
 from pathlib import Path
-from typing import Any
 
 import sphinx.application
 from sphinx.builders.html import StandaloneHTMLBuilder
 
-THEME_PATH = Path(__file__).parent.resolve()
+TYPE_CHECKING = False
+if TYPE_CHECKING:
+    from typing import Any
+
+    from sphinx.application import Sphinx
+    from sphinx.util.typing import ExtensionMetadata
+
+__version__ = "2024.12"
+
+THEME_PATH = Path(__file__).resolve().parent
 
 
 @cache
@@ -52,15 +59,15 @@ def _html_page_context(
         )
 
 
-def setup(app):
+def setup(app: Sphinx) -> ExtensionMetadata:
     app.require_sphinx("3.4")
 
-    current_dir = os.path.abspath(os.path.dirname(__file__))
-    app.add_html_theme("python_docs_theme", current_dir)
+    app.add_html_theme("python_docs_theme", str(THEME_PATH))
 
     app.connect("html-page-context", _html_page_context)
 
     return {
+        "version": __version__,
         "parallel_read_safe": True,
         "parallel_write_safe": True,
     }
diff --git a/requirements.txt b/requirements.txt
index 18e6c17..ad829d4 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,4 +2,4 @@
 setuptools
 Babel
 Jinja2
-tomli; python_version < "3.10"
+tomli; python_version < "3.11"

From 24ed1541324a8d94e5113b4116943aec0ec43681 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Date: Tue, 4 Feb 2025 14:55:00 +0000
Subject: [PATCH 159/175] Prepare 2025.2 release (#223)

---
 CHANGELOG.rst                 | 12 ++++++++++++
 python_docs_theme/__init__.py |  2 +-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 47eef33..74b09ca 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,18 @@
 Changelog
 =========
 
+`2025.2 <https://github.com/python/python-docs-theme/releases/tag/2025.2>`_
+---------------------------------------------------------------------------
+
+- Note minimum requirements for Sphinx (#216)
+    Contributed by Adam Turner
+- Horizontally centre the sidebar collapse button (#219)
+    Contributed by Tomas Roun
+- Make sidebar width more flexible (#218)
+    Contributed by Tomas Roun
+- Set ``__version__`` in the runtime package (#222)
+    Contributed by Adam Turner
+
 `2024.12 <https://github.com/python/python-docs-theme/releases/tag/2024.12>`_
 -----------------------------------------------------------------------------
 
diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py
index d8dd2c7..5a84c84 100644
--- a/python_docs_theme/__init__.py
+++ b/python_docs_theme/__init__.py
@@ -14,7 +14,7 @@
     from sphinx.application import Sphinx
     from sphinx.util.typing import ExtensionMetadata
 
-__version__ = "2024.12"
+__version__ = "2025.2"
 
 THEME_PATH = Path(__file__).resolve().parent
 

From f5d080f2ae0318db0c93f5afff79d27482ef7b4d Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Date: Thu, 13 Feb 2025 01:42:59 +0000
Subject: [PATCH 160/175] Require Python 3.10 and Sphinx 7.3 (#221)

---
 .github/workflows/tests.yml             |  2 +-
 README.md                               |  2 +-
 pyproject.toml                          |  5 +-
 python_docs_theme/__init__.py           | 51 +------------
 python_docs_theme/static/pydoctheme.css | 12 ----
 python_docs_theme/static/sidebar.js_t   | 95 -------------------------
 python_docs_theme/theme.conf            | 37 ----------
 python_docs_theme/theme.toml            | 39 ++++++++++
 8 files changed, 44 insertions(+), 199 deletions(-)
 delete mode 100644 python_docs_theme/static/sidebar.js_t
 delete mode 100644 python_docs_theme/theme.conf
 create mode 100644 python_docs_theme/theme.toml

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index ace177e..90e4b63 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -56,7 +56,7 @@ jobs:
       matrix:
         os: ["ubuntu-latest", "windows-latest"]
         # Test minimum supported and latest stable from 3.x series
-        python-version: ["3.9", "3"]
+        python-version: ["3.10", "3"]
     steps:
       - uses: actions/checkout@v4
       - uses: actions/setup-python@v5
diff --git a/README.md b/README.md
index 24308f7..133daa0 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # Python Docs Sphinx Theme
 
 This is the theme for the Python documentation.
-It requires Python 3.9 or newer and Sphinx 3.4 or newer.
+It requires Python 3.10 or newer and Sphinx 7.3 or newer.
 
 Note that when adopting this theme, you're also borrowing an element of the
 trust and credibility established by the CPython core developers over the
diff --git a/pyproject.toml b/pyproject.toml
index 7eb1cc2..e03e2be 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -10,7 +10,7 @@ description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.md"
 license.file = "LICENSE"
 authors = [ { name = "PyPA", email = "distutils-sig@python.org" } ]
-requires-python = ">=3.9"
+requires-python = ">=3.10"
 classifiers = [
   "Development Status :: 5 - Production/Stable",
   "Framework :: Sphinx :: Theme",
@@ -19,7 +19,6 @@ classifiers = [
   "Operating System :: OS Independent",
   "Programming Language :: Python",
   "Programming Language :: Python :: 3 :: Only",
-  "Programming Language :: Python :: 3.9",
   "Programming Language :: Python :: 3.10",
   "Programming Language :: Python :: 3.11",
   "Programming Language :: Python :: 3.12",
@@ -30,7 +29,7 @@ classifiers = [
 dynamic = [ "version" ]
 
 dependencies = [
-  "sphinx>=3.4",
+  "sphinx>=7.3",
 ]
 
 urls.Code = "https://github.com/python/python-docs-theme"
diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py
index 5a84c84..c5b5fe7 100644
--- a/python_docs_theme/__init__.py
+++ b/python_docs_theme/__init__.py
@@ -1,16 +1,9 @@
 from __future__ import annotations
 
-import hashlib
-from functools import cache
 from pathlib import Path
 
-import sphinx.application
-from sphinx.builders.html import StandaloneHTMLBuilder
-
 TYPE_CHECKING = False
 if TYPE_CHECKING:
-    from typing import Any
-
     from sphinx.application import Sphinx
     from sphinx.util.typing import ExtensionMetadata
 
@@ -19,53 +12,11 @@
 THEME_PATH = Path(__file__).resolve().parent
 
 
-@cache
-def _asset_hash(path: str) -> str:
-    """Append a `?digest=` to an url based on the file content."""
-    full_path = THEME_PATH / path.replace("_static/", "static/")
-    digest = hashlib.sha1(full_path.read_bytes()).hexdigest()
-
-    return f"{path}?digest={digest}"
-
-
-def _add_asset_hashes(static: list[str], add_digest_to: list[str]) -> None:
-    for asset in add_digest_to:
-        index = static.index(asset)
-        static[index].filename = _asset_hash(asset)  # type: ignore[attr-defined]
-
-
-def _html_page_context(
-    app: sphinx.application.Sphinx,
-    pagename: str,
-    templatename: str,
-    context: dict[str, Any],
-    doctree: Any,
-) -> None:
-    if app.config.html_theme != "python_docs_theme":
-        return
-
-    assert isinstance(app.builder, StandaloneHTMLBuilder)
-
-    if (4,) <= sphinx.version_info < (7, 1) and "css_files" in context:
-        if "_static/pydoctheme.css" not in context["css_files"]:
-            raise ValueError(
-                "This documentation is not using `pydoctheme.css` as the stylesheet. "
-                "If you have set `html_style` in your conf.py file, remove it."
-            )
-
-        _add_asset_hashes(
-            context["css_files"],
-            ["_static/pydoctheme.css"],
-        )
-
-
 def setup(app: Sphinx) -> ExtensionMetadata:
-    app.require_sphinx("3.4")
+    app.require_sphinx("7.3")
 
     app.add_html_theme("python_docs_theme", str(THEME_PATH))
 
-    app.connect("html-page-context", _html_page_context)
-
     return {
         "version": __version__,
         "parallel_read_safe": True,
diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 8b7b2cf..da47d3e 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -1,5 +1,3 @@
-@import url('classic.css');
-
 /* Common colours */
 :root {
     --good-color: rgb(41 100 51);
@@ -200,16 +198,6 @@ div.sphinxsidebar input[type='text'] {
     display: flex;
     justify-content: center;
     align-items: center;
-    /* Sphinx 4.x and earlier compat */
-    height: 100%;
-    background-color: #CCCCCC;
-    margin-left: 0;
-    color: #444444;
-    font-size: 1.2em;
-    cursor: pointer;
-    padding-top: 1px;
-    float: none;
-    /* after Sphinx 4.x and earlier is dropped, only the below is needed */
     width: 12px;
     min-width: 12px;
     border-radius: 0 5px 5px 0;
diff --git a/python_docs_theme/static/sidebar.js_t b/python_docs_theme/static/sidebar.js_t
deleted file mode 100644
index a08aa0f..0000000
--- a/python_docs_theme/static/sidebar.js_t
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * sidebar.js
- * ~~~~~~~~~~
- *
- * This file is functionally identical to "sidebar.js" in Sphinx 5.0.
- * When support for Sphinx 4 and earlier is dropped from the theme,
- * this file can be removed.
- *
- * This script makes the Sphinx sidebar collapsible.
- *
- * .sphinxsidebar contains .sphinxsidebarwrapper.  This script adds
- * in .sphinxsidebar, after .sphinxsidebarwrapper, the #sidebarbutton
- * used to collapse and expand the sidebar.
- *
- * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden
- * and the width of the sidebar and the margin-left of the document
- * are decreased. When the sidebar is expanded the opposite happens.
- * This script saves a per-browser/per-session cookie used to
- * remember the position of the sidebar among the pages.
- * Once the browser is closed the cookie is deleted and the position
- * reset to the default (expanded).
- *
- * :copyright: Copyright 2007-2022 by the Sphinx team, see AUTHORS.
- * :license: BSD, see LICENSE for details.
- *
- */
-
-const initialiseSidebar = () => {
-  // global elements used by the functions.
-  const bodyWrapper = document.getElementsByClassName("bodywrapper")[0]
-  const sidebar = document.getElementsByClassName("sphinxsidebar")[0]
-  const sidebarWrapper = document.getElementsByClassName("sphinxsidebarwrapper")[0]
-
-  // exit early if the document has no sidebar for some reason
-  if (typeof sidebar === "undefined") {
-    return
-  }
-
-{# Check if we need to dynamically insert the sidebar button.
- # We prefer the ``sphinx_version_tuple`` variable, and if it is undefined we
- # know we are running a Sphinx version older than 4.2.
- #
- # See: https://www.sphinx-doc.org/en/master/development/templating.html#sphinx_version_tuple
- #}
-{% if sphinx_version_tuple is defined and sphinx_version_tuple[0] >= 5 %}
-  const sidebarButton = document.getElementById("sidebarbutton")
-  const sidebarArrow = sidebarButton.querySelector('span')
-{% else %}
-  // create the sidebar button element
-  const sidebarButton = document.createElement("div")
-  sidebarButton.id = "sidebarbutton"
-  // create the sidebar button arrow element
-  const sidebarArrow = document.createElement("span")
-  sidebarArrow.innerText =  "«"
-  sidebarButton.appendChild(sidebarArrow)
-  sidebar.appendChild(sidebarButton)
-{% endif %}
-
-  const collapse_sidebar = () => {
-    bodyWrapper.style.marginLeft = ".8em"
-    sidebar.style.width = ".8em"
-    sidebarWrapper.style.display = "none"
-    sidebarArrow.innerText = "»"
-    sidebarButton.title = _("Expand sidebar")
-    window.localStorage.setItem("sidebar", "collapsed")
-  }
-
-  const expand_sidebar = () => {
-    bodyWrapper.style.marginLeft = ""
-    sidebar.style.removeProperty("width")
-    sidebarWrapper.style.display = ""
-    sidebarArrow.innerText = "«"
-    sidebarButton.title = _("Collapse sidebar")
-    window.localStorage.setItem("sidebar", "expanded")
-  }
-
-  sidebarButton.addEventListener("click", () => {
-    (sidebarWrapper.style.display === "none") ? expand_sidebar() : collapse_sidebar()
-  })
-
-  const sidebar_state = window.localStorage.getItem("sidebar")
-  if (sidebar_state === "collapsed") {
-    collapse_sidebar()
-  }
-  else if (sidebar_state === "expanded") {
-    expand_sidebar()
-  }
-}
-
-if (document.readyState !== "loading") {
-  initialiseSidebar()
-}
-else {
-  document.addEventListener("DOMContentLoaded", initialiseSidebar)
-}
diff --git a/python_docs_theme/theme.conf b/python_docs_theme/theme.conf
deleted file mode 100644
index 5edf397..0000000
--- a/python_docs_theme/theme.conf
+++ /dev/null
@@ -1,37 +0,0 @@
-[theme]
-inherit = default
-stylesheet = pydoctheme.css
-pygments_style = default
-pygments_dark_style = monokai
-
-[options]
-bodyfont = -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif
-headfont = -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif
-footerbgcolor = white
-footertextcolor = #555555
-relbarbgcolor = white
-relbartextcolor = #666666
-relbarlinkcolor = #444444
-sidebarbgcolor = white
-sidebartextcolor = #444444
-sidebarlinkcolor = #444444
-sidebarbtncolor = #cccccc
-bgcolor = white
-textcolor = #222222
-linkcolor = #0090c0
-visitedlinkcolor = #00608f
-headtextcolor = #1a1a1a
-headbgcolor = white
-headlinkcolor = #aaaaaa
-codebgcolor = #eeffcc
-codetextcolor = #333333
-
-hosted_on =
-issues_url =
-license_url =
-root_name = Python
-root_url = https://www.python.org/
-root_icon = py.svg
-root_icon_alt_text = Python logo
-root_include_title = True
-copyright_url =
diff --git a/python_docs_theme/theme.toml b/python_docs_theme/theme.toml
new file mode 100644
index 0000000..1d3cdbd
--- /dev/null
+++ b/python_docs_theme/theme.toml
@@ -0,0 +1,39 @@
+[theme]
+inherit = "default"
+stylesheets = [
+    "classic.css",
+    "pydoctheme.css",
+]
+pygments_style = { default = "default", dark = "monokai" }
+
+[options]
+bodyfont = "-apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif"
+headfont = "-apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Cantarell, Ubuntu, roboto, noto, arial, sans-serif"
+footerbgcolor = "white"
+footertextcolor = "#555555"
+relbarbgcolor = "white"
+relbartextcolor = "#666666"
+relbarlinkcolor = "#444444"
+sidebarbgcolor = "white"
+sidebartextcolor = "#444444"
+sidebarlinkcolor = "#444444"
+sidebarbtncolor = "#cccccc"
+bgcolor = "white"
+textcolor = "#222222"
+linkcolor = "#0090c0"
+visitedlinkcolor = "#00608f"
+headtextcolor = "#1a1a1a"
+headbgcolor = "white"
+headlinkcolor = "#aaaaaa"
+codebgcolor = "#eeffcc"
+codetextcolor = "#333333"
+
+hosted_on = ""
+issues_url = ""
+license_url = ""
+root_name = "Python"
+root_url = "https://www.python.org/"
+root_icon = "py.svg"
+root_icon_alt_text = "Python logo"
+root_include_title = "True"
+copyright_url = ""

From 729fcc106102ebef5473e7f6b12d78f9822d530f Mon Sep 17 00:00:00 2001
From: "Tomas R." <tomas.roun8@gmail.com>
Date: Fri, 4 Apr 2025 14:37:48 +0200
Subject: [PATCH 161/175] Add missing i18n for copy button titles (#225)

Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
---
 .babel.cfg                             | 2 ++
 python_docs_theme/static/copybutton.js | 4 ++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/.babel.cfg b/.babel.cfg
index 692580d..cc4c9de 100644
--- a/.babel.cfg
+++ b/.babel.cfg
@@ -1 +1,3 @@
+[javascript: **.js]
+
 [jinja2: **.html]
diff --git a/python_docs_theme/static/copybutton.js b/python_docs_theme/static/copybutton.js
index 7367c4a..f176ff6 100644
--- a/python_docs_theme/static/copybutton.js
+++ b/python_docs_theme/static/copybutton.js
@@ -33,8 +33,8 @@ const loadCopyButton = () => {
     /* Add a [>>>] button in the top-right corner of code samples to hide
      * the >>> and ... prompts and the output and thus make the code
      * copyable. */
-    const hide_text = "Hide the prompts and output"
-    const show_text = "Show the prompts and output"
+    const hide_text = _("Hide the prompts and output")
+    const show_text = _("Show the prompts and output")
 
     const button = document.createElement("span")
     button.classList.add("copybutton")

From e0b4a3396b818d41a37e28c5631b3d1a7c27a407 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Mon, 7 Apr 2025 21:15:19 +0300
Subject: [PATCH 162/175] Remove self-closing tags (#226)

---
 python_docs_theme/footerdonate.html |  2 +-
 python_docs_theme/layout.html       | 34 ++++++++++++++---------------
 2 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/python_docs_theme/footerdonate.html b/python_docs_theme/footerdonate.html
index 2aef2ac..010014d 100644
--- a/python_docs_theme/footerdonate.html
+++ b/python_docs_theme/footerdonate.html
@@ -1,3 +1,3 @@
 {% trans %}The Python Software Foundation is a non-profit corporation.{% endtrans %}
 <a href="https://www.python.org/psf/donations/">{% trans %}Please donate.{% endtrans %}</a>
-<br />
+<br>
diff --git a/python_docs_theme/layout.html b/python_docs_theme/layout.html
index 9762b06..a74517c 100644
--- a/python_docs_theme/layout.html
+++ b/python_docs_theme/layout.html
@@ -14,7 +14,7 @@ <h3>{{ _('Navigation') }}</h3>
           </li>
           {%- endfor %}
           {%- block rootrellink %}
-          <li><img src="{{ pathto('_static/' ~ theme_root_icon, 1) }}" alt="{{ theme_root_icon_alt_text }}" style="vertical-align: middle; margin-top: -1px"/></li>
+          <li><img src="{{ pathto('_static/' ~ theme_root_icon, 1) }}" alt="{{ theme_root_icon_alt_text }}" style="vertical-align: middle; margin-top: -1px"></li>
           <li><a href="{{theme_root_url}}">{{theme_root_name}}</a>{{ reldelim1 }}</li>
           <li class="switchers">
             <div class="language_switcher_placeholder"></div>
@@ -48,8 +48,8 @@ <h3>{{ _('Navigation') }}</h3>
     {%- if builder != "htmlhelp" %}
     <div class="inline-search" role="search">
         <form class="inline-search" action="{{ pathto('search') }}" method="get">
-          <input placeholder="{{ _('Quick search') }}" aria-label="{{ _('Quick search') }}" type="search" name="q" id="search-box" />
-          <input type="submit" value="{{ _('Go') }}" />
+          <input placeholder="{{ _('Quick search') }}" aria-label="{{ _('Quick search') }}" type="search" name="q" id="search-box">
+          <input type="submit" value="{{ _('Go') }}">
         </form>
     </div>
     {%- endif %}
@@ -71,7 +71,7 @@ <h3>{{ _('Navigation') }}</h3>
 
 {%- block extrahead -%}
     <link rel="stylesheet" href="{{ pathto('_static/pydoctheme_dark.css', 1) }}" media="(prefers-color-scheme: dark)" id="pydoctheme_dark_css">
-    <link rel="shortcut icon" type="image/png" href="{{ pathto('_static/' ~ theme_root_icon, 1) }}" />
+    <link rel="shortcut icon" type="image/png" href="{{ pathto('_static/' ~ theme_root_icon, 1) }}">
     {%- if builder != "htmlhelp" %}
         {%- if not embedded %}
             <script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>
@@ -93,14 +93,14 @@ <h3>{{ _('Navigation') }}</h3>
 {%- if builder != 'htmlhelp' %}
 <div class="mobile-nav">
     <input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
-           aria-pressed="false" aria-expanded="false" role="button" aria-label="{{ _('Menu')}}" />
+           aria-pressed="false" aria-expanded="false" role="button" aria-label="{{ _('Menu')}}">
     <nav class="nav-content" role="navigation">
         <label for="menuToggler" class="toggler__label">
             <span></span>
         </label>
         <span class="nav-items-wrapper">
             <a href="{{ theme_root_url }}" class="nav-logo">
-                <img src="{{ pathto('_static/' ~ theme_root_icon, 1) }}" alt="{{ theme_root_icon_alt_text }}"/>
+                <img src="{{ pathto('_static/' ~ theme_root_icon, 1) }}" alt="{{ theme_root_icon_alt_text }}">
             </a>
             <span class="version_switcher_placeholder"></span>
             {%- if pagename != "search" and builder != "singlehtml" %}
@@ -108,8 +108,8 @@ <h3>{{ _('Navigation') }}</h3>
                 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
                     <path fill-rule="nonzero" fill="currentColor" d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"></path>
                 </svg>
-                <input placeholder="{{ _('Quick search') }}" aria-label="{{ _('Quick search') }}" type="search" name="q" />
-                <input type="submit" value="{{ _('Go') }}"/>
+                <input placeholder="{{ _('Quick search') }}" aria-label="{{ _('Quick search') }}" type="search" name="q">
+                <input type="submit" value="{{ _('Go') }}">
             </form>
             {%- endif %}
         </span>
@@ -121,7 +121,7 @@ <h3>{{ _('Navigation') }}</h3>
             {%- if logo %}
             <p class="logo">
                 <a href="{{ pathto('index') }}">
-                <img class="logo" src="{{ pathto('_static/' ~ logo, 1)|e }}" alt="Logo"/>
+                <img class="logo" src="{{ pathto('_static/' ~ logo, 1)|e }}" alt="Logo">
                 </a>
             </p>
             {%- endif %}
@@ -143,21 +143,21 @@ <h3>{{ _('Navigation') }}</h3>
     {% if theme_copyright_url or hasdoc('copyright') %}
       </a>
     {% endif %} {{ copyright|e }}.
-    <br />
+    <br>
     {% trans %}This page is licensed under the Python Software Foundation License Version 2.{% endtrans %}
-    <br />
+    <br>
     {% trans %}Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.{% endtrans %}
-    <br />
+    <br>
     {% if theme_license_url %}
-      {% trans license_file=theme_license_url %}See <a href="{{ license_file }}">History and License</a> for more information.{% endtrans %}<br />
+      {% trans license_file=theme_license_url %}See <a href="{{ license_file }}">History and License</a> for more information.{% endtrans %}<br>
     {% endif %}
     {% if theme_hosted_on %}
-      {% trans hosted_on=theme_hosted_on %}Hosted on {{ hosted_on }}.{% endtrans %}<br />
+      {% trans hosted_on=theme_hosted_on %}Hosted on {{ hosted_on }}.{% endtrans %}<br>
     {% endif %}
-    <br />
+    <br>
 
     {% include "footerdonate.html" %}
-    <br />
+    <br>
 
     {%- if last_updated %}
       {% trans last_updated=last_updated|e %}Last updated on {{ last_updated }}.{% endtrans %}
@@ -165,7 +165,7 @@ <h3>{{ _('Navigation') }}</h3>
     {% if theme_issues_url %}
       {% trans %}<a href="{{ theme_issues_url }}">Found a bug</a>?{% endtrans %}
     {% endif %}
-    <br />
+    <br>
 
     {% trans sphinx_version=sphinx_version|e %}Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> {{ sphinx_version }}.{% endtrans %}
     </div>

From 06987c260d882d92e9aa0513d04b8645c981ae39 Mon Sep 17 00:00:00 2001
From: "Tomas R." <tomas.roun8@gmail.com>
Date: Thu, 10 Apr 2025 21:18:38 +0200
Subject: [PATCH 163/175] Use consistent line-height in code blocks for light &
 dark theme (#227)

---
 python_docs_theme/static/pydoctheme.css | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index da47d3e..40d9cb0 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -328,6 +328,10 @@ tt, code, pre {
     font-size: 96.5%;
 }
 
+div.body pre {
+    line-height: 120%;
+}
+
 div.body tt,
 div.body code {
     border-radius: 3px;

From b8b2d49bed1e933e2eaee24d8822ad0e6a946591 Mon Sep 17 00:00:00 2001
From: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Date: Fri, 11 Apr 2025 15:24:17 +0100
Subject: [PATCH 164/175] Use the correct spelling of the ``--languages`` flag
 (#228)

---
 .github/workflows/tests.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 90e4b63..4054cbf 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -37,7 +37,7 @@ jobs:
           --group "$(id -g)"
           --skip-cache-invalidation
           --theme "$(pwd)"
-          --language en
+          --languages en
           --branch ${{ matrix.branch }}
       - name: Show logs
         if: failure()

From 6ac5c06d13fa22e25f39ebf95642d00b64f7a895 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sun, 13 Apr 2025 13:33:26 +0300
Subject: [PATCH 165/175] Use --branches for docsbuild-scripts (#232)

---
 .github/workflows/tests.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 4054cbf..875123c 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -38,7 +38,7 @@ jobs:
           --skip-cache-invalidation
           --theme "$(pwd)"
           --languages en
-          --branch ${{ matrix.branch }}
+          --branches ${{ matrix.branch }}
       - name: Show logs
         if: failure()
         run: |

From d528dbca5dcaf28f19aa1e2ced645320882f1203 Mon Sep 17 00:00:00 2001
From: "Tomas R." <tomas.roun8@gmail.com>
Date: Fri, 18 Apr 2025 11:46:36 +0200
Subject: [PATCH 166/175] Add a copy button to code samples (#231)

Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
---
 python_docs_theme/static/copybutton.js       | 106 +++++++++----------
 python_docs_theme/static/pydoctheme.css      |  22 ++--
 python_docs_theme/static/pydoctheme_dark.css |  13 +++
 3 files changed, 76 insertions(+), 65 deletions(-)

diff --git a/python_docs_theme/static/copybutton.js b/python_docs_theme/static/copybutton.js
index f176ff6..9df468e 100644
--- a/python_docs_theme/static/copybutton.js
+++ b/python_docs_theme/static/copybutton.js
@@ -1,65 +1,59 @@
-// ``function*`` denotes a generator in JavaScript, see
-// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
-function* getHideableCopyButtonElements(rootElement) {
-    // yield all elements with the "go" (Generic.Output),
-    // "gp" (Generic.Prompt), or "gt" (Generic.Traceback) CSS class
-    for (const el of rootElement.querySelectorAll('.go, .gp, .gt')) {
-        yield el
-    }
-    // tracebacks (.gt) contain bare text elements that need to be
-    // wrapped in a span to hide or show the element
-    for (let el of rootElement.querySelectorAll('.gt')) {
-        while ((el = el.nextSibling) && el.nodeType !== Node.DOCUMENT_NODE) {
-            // stop wrapping text nodes when we hit the next output or
-            // prompt element
-            if (el.nodeType === Node.ELEMENT_NODE && el.matches(".gp, .go")) {
-                break
-            }
-            // if the node is a text node with content, wrap it in a
-            // span element so that we can control visibility
-            if (el.nodeType === Node.TEXT_NODE && el.textContent.trim()) {
-                const wrapper = document.createElement("span")
-                el.after(wrapper)
-                wrapper.appendChild(el)
-                el = wrapper
-            }
-            yield el
+// Extract copyable text from the code block ignoring the
+// prompts and output.
+function getCopyableText(rootElement) {
+    rootElement = rootElement.cloneNode(true)
+    // tracebacks (.gt) contain bare text elements that
+    // need to be removed
+    const tracebacks = rootElement.querySelectorAll(".gt")
+    for (const el of tracebacks) {
+        while (
+            el.nextSibling &&
+            (el.nextSibling.nodeType !== Node.DOCUMENT_NODE ||
+                !el.nextSibling.matches(".gp, .go"))
+        ) {
+            el.nextSibling.remove()
         }
     }
+    // Remove all elements with the "go" (Generic.Output),
+    // "gp" (Generic.Prompt), or "gt" (Generic.Traceback) CSS class
+    const elements = rootElement.querySelectorAll(".gp, .go, .gt")
+    for (const el of elements) {
+        el.remove()
+    }
+    return rootElement.innerText.trim()
 }
 
-
 const loadCopyButton = () => {
-    /* Add a [>>>] button in the top-right corner of code samples to hide
-     * the >>> and ... prompts and the output and thus make the code
-     * copyable. */
-    const hide_text = _("Hide the prompts and output")
-    const show_text = _("Show the prompts and output")
-
-    const button = document.createElement("span")
+    const button = document.createElement("button")
     button.classList.add("copybutton")
-    button.innerText = ">>>"
-    button.title = hide_text
-    button.dataset.hidden = "false"
-    const buttonClick = event => {
+    button.type = "button"
+    button.innerText = _("Copy")
+    button.title = _("Copy to clipboard")
+
+    const makeOnButtonClick = () => {
+        let timeout = null
         // define the behavior of the button when it's clicked
-        event.preventDefault()
-        const buttonEl = event.currentTarget
-        const codeEl = buttonEl.nextElementSibling
-        if (buttonEl.dataset.hidden === "false") {
-            // hide the code output
-            for (const el of getHideableCopyButtonElements(codeEl)) {
-                el.hidden = true
+        return async event => {
+            // check if the clipboard is available
+            if (!navigator.clipboard || !navigator.clipboard.writeText) {
+                return;
             }
-            buttonEl.title = show_text
-            buttonEl.dataset.hidden = "true"
-        } else {
-            // show the code output
-            for (const el of getHideableCopyButtonElements(codeEl)) {
-                el.hidden = false
+
+            clearTimeout(timeout)
+            const buttonEl = event.currentTarget
+            const codeEl = buttonEl.nextElementSibling
+
+            try {
+                await navigator.clipboard.writeText(getCopyableText(codeEl))
+            } catch (e) {
+                console.error(e.message)
+                return
             }
-            buttonEl.title = hide_text
-            buttonEl.dataset.hidden = "false"
+
+            buttonEl.innerText = _("Copied!")
+            timeout = setTimeout(() => {
+                buttonEl.innerText = _("Copy")
+            }, 1500)
         }
     }
 
@@ -78,10 +72,8 @@ const loadCopyButton = () => {
         // if we find a console prompt (.gp), prepend the (deeply cloned) button
         const clonedButton = button.cloneNode(true)
         // the onclick attribute is not cloned, set it on the new element
-        clonedButton.onclick = buttonClick
-        if (el.querySelector(".gp") !== null) {
-            el.prepend(clonedButton)
-        }
+        clonedButton.onclick = makeOnButtonClick()
+        el.prepend(clonedButton)
     })
 }
 
diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 40d9cb0..6d50092 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -442,17 +442,23 @@ div.genindex-jumpbox a {
     top: 0;
     right: 0;
     font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace;
-    padding-left: 0.2em;
-    padding-right: 0.2em;
+    font-size: 80%;
+    padding-left: .5em;
+    padding-right: .5em;
+    height: 100%;
+    max-height: min(100%, 2.4em);
     border-radius: 0 3px 0 0;
-    color: #ac9; /* follows div.body pre */
-    border-color: #ac9; /* follows div.body pre */
-    border-style: solid; /* follows div.body pre */
-    border-width: 1px; /* follows div.body pre */
+    color: #000;
+    background-color: #fff;
+    border: 1px solid #ac9; /* follows div.body pre */
+}
+
+.copybutton:hover {
+    background-color: #eee;
 }
 
-.copybutton[data-hidden='true'] {
-    text-decoration: line-through;
+.copybutton:active {
+    background-color: #ddd;
 }
 
 @media (max-width: 1023px) {
diff --git a/python_docs_theme/static/pydoctheme_dark.css b/python_docs_theme/static/pydoctheme_dark.css
index 4509960..582e4dd 100644
--- a/python_docs_theme/static/pydoctheme_dark.css
+++ b/python_docs_theme/static/pydoctheme_dark.css
@@ -176,3 +176,16 @@ img.invert-in-dark-mode {
     --versionchanged: var(--middle-color);
     --deprecated: var(--bad-color);
 }
+
+.copybutton {
+    color: #ac9; /* follows div.body pre */
+    background-color: #222222; /* follows body */
+}
+
+.copybutton:hover {
+    background-color: #434343;
+}
+
+.copybutton:active {
+    background-color: #656565;
+}

From 5b795101f57a47ac8113bd08294f3b7e176f3ff9 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sat, 19 Apr 2025 01:10:06 +0300
Subject: [PATCH 167/175] Drop support for Python 3.10 and 3.11 (#234)

---
 .github/workflows/tests.yml |  4 ++--
 babel_runner.py             | 11 +----------
 pyproject.toml              |  4 +---
 requirements.txt            |  2 --
 4 files changed, 4 insertions(+), 17 deletions(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 875123c..5a8ec72 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -12,7 +12,7 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        branch: ["origin/main", "3.13", "3.12", "3.11", "3.10"]
+        branch: ["origin/main", "3.13", "3.12"]
     steps:
       - uses: actions/checkout@v4
       - uses: actions/setup-python@v5
@@ -56,7 +56,7 @@ jobs:
       matrix:
         os: ["ubuntu-latest", "windows-latest"]
         # Test minimum supported and latest stable from 3.x series
-        python-version: ["3.10", "3"]
+        python-version: ["3.12", "3"]
     steps:
       - uses: actions/checkout@v4
       - uses: actions/setup-python@v5
diff --git a/babel_runner.py b/babel_runner.py
index ee5af16..0785ae2 100755
--- a/babel_runner.py
+++ b/babel_runner.py
@@ -5,18 +5,9 @@
 import argparse
 import ast
 import subprocess
+import tomllib
 from pathlib import Path
 
-try:
-    import tomllib
-except ImportError:
-    try:
-        import tomli as tomllib
-    except ImportError as ie:
-        raise ImportError(
-            "tomli or tomllib is required to parse pyproject.toml"
-        ) from ie
-
 PROJECT_DIR = Path(__file__).resolve().parent
 PYPROJECT_TOML = PROJECT_DIR / "pyproject.toml"
 INIT_PY = PROJECT_DIR / "python_docs_theme" / "__init__.py"
diff --git a/pyproject.toml b/pyproject.toml
index e03e2be..f312f8b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -10,7 +10,7 @@ description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.md"
 license.file = "LICENSE"
 authors = [ { name = "PyPA", email = "distutils-sig@python.org" } ]
-requires-python = ">=3.10"
+requires-python = ">=3.12"
 classifiers = [
   "Development Status :: 5 - Production/Stable",
   "Framework :: Sphinx :: Theme",
@@ -19,8 +19,6 @@ classifiers = [
   "Operating System :: OS Independent",
   "Programming Language :: Python",
   "Programming Language :: Python :: 3 :: Only",
-  "Programming Language :: Python :: 3.10",
-  "Programming Language :: Python :: 3.11",
   "Programming Language :: Python :: 3.12",
   "Programming Language :: Python :: 3.13",
   "Topic :: Documentation",
diff --git a/requirements.txt b/requirements.txt
index ad829d4..bb631b5 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,3 @@
 # for babel_runner.py
-setuptools
 Babel
 Jinja2
-tomli; python_version < "3.11"

From d0b0a152185d8cfe7ec4af57316808fc9b39eb65 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Sat, 26 Apr 2025 12:42:29 +0300
Subject: [PATCH 168/175] Replace deprecated classifier with licence expression
 (PEP 639) (#237)

---
 pyproject.toml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pyproject.toml b/pyproject.toml
index f312f8b..11e66cb 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -8,14 +8,14 @@ requires = [
 name = "python-docs-theme"
 description = "The Sphinx theme for the CPython docs and related projects"
 readme = "README.md"
-license.file = "LICENSE"
+license = "PSF-2.0"
+license-files = [ "LICENSE" ]
 authors = [ { name = "PyPA", email = "distutils-sig@python.org" } ]
 requires-python = ">=3.12"
 classifiers = [
   "Development Status :: 5 - Production/Stable",
   "Framework :: Sphinx :: Theme",
   "Intended Audience :: Developers",
-  "License :: OSI Approved :: Python Software Foundation License",
   "Operating System :: OS Independent",
   "Programming Language :: Python",
   "Programming Language :: Python :: 3 :: Only",

From 7253ffc89738d2e96deacda61c84cbb66d7eb69b Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Mon, 28 Apr 2025 19:05:17 +0300
Subject: [PATCH 169/175] Add support for Python 3.14 (#236)

---
 .github/workflows/tests.yml | 5 +++--
 .pre-commit-config.yaml     | 1 -
 pyproject.toml              | 4 ++++
 3 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 5a8ec72..23e6c7e 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -12,12 +12,12 @@ jobs:
     strategy:
       fail-fast: false
       matrix:
-        branch: ["origin/main", "3.13", "3.12"]
+        branch: ["3.14", "3.13", "3.12"]
     steps:
       - uses: actions/checkout@v4
       - uses: actions/setup-python@v5
         with:
-          python-version: 3
+          python-version: ${{ matrix.branch }}
           allow-prereleases: true
           cache: pip
       - name: Clone docsbuild scripts
@@ -39,6 +39,7 @@ jobs:
           --theme "$(pwd)"
           --languages en
           --branches ${{ matrix.branch }}
+          ${{ matrix.branch == '3.14' && '--select-output no-html' || '' }}
       - name: Show logs
         if: failure()
         run: |
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index f964364..9a7e83b 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -36,7 +36,6 @@ repos:
     rev: v2.5.0
     hooks:
       - id: pyproject-fmt
-        args: [--max-supported-python=3.13]
 
   - repo: https://github.com/abravalheri/validate-pyproject
     rev: v0.23
diff --git a/pyproject.toml b/pyproject.toml
index 11e66cb..a614351 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -21,6 +21,7 @@ classifiers = [
   "Programming Language :: Python :: 3 :: Only",
   "Programming Language :: Python :: 3.12",
   "Programming Language :: Python :: 3.13",
+  "Programming Language :: Python :: 3.14",
   "Topic :: Documentation",
   "Topic :: Software Development :: Documentation",
 ]
@@ -67,3 +68,6 @@ lint.ignore = [
   "E241", # Multiple spaces after ','
 ]
 lint.isort.required-imports = [ "from __future__ import annotations" ]
+
+[tool.pyproject-fmt]
+max_supported_python = "3.14"

From 4c59313d66516cc8614cad05dc0bf62d44828269 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Tue, 29 Apr 2025 15:09:46 +0300
Subject: [PATCH 170/175] Prepare 2025.4 release (#238)

---
 CHANGELOG.rst                 | 11 +++++++++++
 README.md                     |  2 +-
 python_docs_theme/__init__.py |  2 +-
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 74b09ca..e50c32b 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,17 @@
 Changelog
 =========
 
+`2025.4 <https://github.com/python/python-docs-theme/releases/tag/2025.4>`_
+---------------------------------------------------------------------------
+
+* Require Sphinx 7.3 by @AA-Turner in https://github.com/python/python-docs-theme/pull/221
+* Add support for Python 3.14 by @hugovk https://github.com/python/python-docs-theme/pull/236
+* Drop support for Python 3.10 and 3.11 by @hugovk in https://github.com/python/python-docs-theme/pull/234
+* Add a copy button to code samples by @tomasr8 in https://github.com/python/python-docs-theme/pull/231
+* Add missing i18n for copy button titles by @tomasr8 in https://github.com/python/python-docs-theme/pull/225
+* Use consistent line-height for light & dark theme by @tomasr8 in https://github.com/python/python-docs-theme/pull/227
+* Remove self-closing tags by @hugovk in https://github.com/python/python-docs-theme/pull/226
+
 `2025.2 <https://github.com/python/python-docs-theme/releases/tag/2025.2>`_
 ---------------------------------------------------------------------------
 
diff --git a/README.md b/README.md
index 133daa0..fedd7f7 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # Python Docs Sphinx Theme
 
 This is the theme for the Python documentation.
-It requires Python 3.10 or newer and Sphinx 7.3 or newer.
+It requires Python 3.12 or newer and Sphinx 7.3 or newer.
 
 Note that when adopting this theme, you're also borrowing an element of the
 trust and credibility established by the CPython core developers over the
diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py
index c5b5fe7..e4d06be 100644
--- a/python_docs_theme/__init__.py
+++ b/python_docs_theme/__init__.py
@@ -7,7 +7,7 @@
     from sphinx.application import Sphinx
     from sphinx.util.typing import ExtensionMetadata
 
-__version__ = "2025.2"
+__version__ = "2025.4"
 
 THEME_PATH = Path(__file__).resolve().parent
 

From 14e4606a2ffcb8bdde6f9b61cb27642ec5482555 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Tue, 29 Apr 2025 15:18:52 +0300
Subject: [PATCH 171/175] Add licence metadata change to changelog (#239)

---
 CHANGELOG.rst | 1 +
 1 file changed, 1 insertion(+)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index e50c32b..ec2ef10 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -11,6 +11,7 @@ Changelog
 * Add missing i18n for copy button titles by @tomasr8 in https://github.com/python/python-docs-theme/pull/225
 * Use consistent line-height for light & dark theme by @tomasr8 in https://github.com/python/python-docs-theme/pull/227
 * Remove self-closing tags by @hugovk in https://github.com/python/python-docs-theme/pull/226
+* Replace deprecated classifier with licence expression (PEP 639) by @hugovk in https://github.com/python/python-docs-theme/pull/237
 
 `2025.2 <https://github.com/python/python-docs-theme/releases/tag/2025.2>`_
 ---------------------------------------------------------------------------

From d0eaa5e0aadb43167d1f24c805bf58bbf4811042 Mon Sep 17 00:00:00 2001
From: "Tomas R." <tomas.roun8@gmail.com>
Date: Wed, 30 Apr 2025 14:05:37 +0200
Subject: [PATCH 172/175] Fix copy button with multiple tracebacks (#240)

---
 python_docs_theme/static/copybutton.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/python_docs_theme/static/copybutton.js b/python_docs_theme/static/copybutton.js
index 9df468e..de071f4 100644
--- a/python_docs_theme/static/copybutton.js
+++ b/python_docs_theme/static/copybutton.js
@@ -8,7 +8,7 @@ function getCopyableText(rootElement) {
     for (const el of tracebacks) {
         while (
             el.nextSibling &&
-            (el.nextSibling.nodeType !== Node.DOCUMENT_NODE ||
+            (el.nextSibling.nodeType !== Node.ELEMENT_NODE ||
                 !el.nextSibling.matches(".gp, .go"))
         ) {
             el.nextSibling.remove()

From 5d0782523024d488e8a1126852f26d118a82b4b3 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Wed, 30 Apr 2025 15:14:26 +0300
Subject: [PATCH 173/175] Prepare 2025.4.1 release (#241)

---
 CHANGELOG.rst                 | 5 +++++
 python_docs_theme/__init__.py | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index ec2ef10..fb43a9f 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,11 @@
 Changelog
 =========
 
+`2025.4.1 <https://github.com/python/python-docs-theme/releases/tag/2025.4.1>`_
+-------------------------------------------------------------------------------
+
+* Fix copy button with multiple tracebacks by @tomasr8 in https://github.com/python/python-docs-theme/pull/240
+
 `2025.4 <https://github.com/python/python-docs-theme/releases/tag/2025.4>`_
 ---------------------------------------------------------------------------
 
diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py
index e4d06be..75459e1 100644
--- a/python_docs_theme/__init__.py
+++ b/python_docs_theme/__init__.py
@@ -7,7 +7,7 @@
     from sphinx.application import Sphinx
     from sphinx.util.typing import ExtensionMetadata
 
-__version__ = "2025.4"
+__version__ = "2025.4.1"
 
 THEME_PATH = Path(__file__).resolve().parent
 

From 42ade08824a02904332cea9b53886ddd2d4740c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Kevin=20Hern=C3=A1ndez?= <kevin.hernandez@unet.edu.ve>
Date: Fri, 23 May 2025 08:33:50 -0400
Subject: [PATCH 174/175] Make copy button appear when hovered (#243)

---
 python_docs_theme/static/pydoctheme.css | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/python_docs_theme/static/pydoctheme.css b/python_docs_theme/static/pydoctheme.css
index 6d50092..4873116 100644
--- a/python_docs_theme/static/pydoctheme.css
+++ b/python_docs_theme/static/pydoctheme.css
@@ -451,6 +451,7 @@ div.genindex-jumpbox a {
     color: #000;
     background-color: #fff;
     border: 1px solid #ac9; /* follows div.body pre */
+    display: none;
 }
 
 .copybutton:hover {
@@ -461,6 +462,14 @@ div.genindex-jumpbox a {
     background-color: #ddd;
 }
 
+.highlight:active .copybutton {
+    display: block;
+}
+
+.highlight:hover .copybutton {
+    display: block;
+}
+
 @media (max-width: 1023px) {
     /* Body layout */
     div.body {

From 8e361585ca0aeb491353252af2a8fd91c4c55316 Mon Sep 17 00:00:00 2001
From: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
Date: Tue, 27 May 2025 16:29:51 +0300
Subject: [PATCH 175/175] Prepare 2025.5 release (#244)

---
 CHANGELOG.rst                 | 5 +++++
 python_docs_theme/__init__.py | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index fb43a9f..07b2735 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,11 @@
 Changelog
 =========
 
+`2025.5 <https://github.com/python/python-docs-theme/releases/tag/2025.5>`_
+---------------------------------------------------------------------------
+
+* Make the copy button only appear when hovered over or clicked on by @kevteg in https://github.com/python/python-docs-theme/pull/243
+
 `2025.4.1 <https://github.com/python/python-docs-theme/releases/tag/2025.4.1>`_
 -------------------------------------------------------------------------------
 
diff --git a/python_docs_theme/__init__.py b/python_docs_theme/__init__.py
index 75459e1..2336dc1 100644
--- a/python_docs_theme/__init__.py
+++ b/python_docs_theme/__init__.py
@@ -7,7 +7,7 @@
     from sphinx.application import Sphinx
     from sphinx.util.typing import ExtensionMetadata
 
-__version__ = "2025.4.1"
+__version__ = "2025.5"
 
 THEME_PATH = Path(__file__).resolve().parent
 
