From eda94712e8960a4d065a42300dba02b636b68bea Mon Sep 17 00:00:00 2001
From: Chris Sewell
Date: Fri, 28 Nov 2025 09:47:32 +0100
Subject: [PATCH 1/4] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20Drop=20python=203.11?=
=?UTF-8?q?=20and=20sphinx=207?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
In preparation for sphinx 9
---
.github/workflows/tests.yml | 12 +++----
.pre-commit-config.yaml | 2 +-
docs/conf.py | 2 +-
myst_parser/inventory.py | 2 +-
myst_parser/sphinx_ext/main.py | 10 ------
pyproject.toml | 7 ++--
.../fixtures/sphinx_directives.md | 12 +++----
tests/test_renderers/test_fixtures_sphinx.py | 24 -------------
tests/test_sphinx/conftest.py | 2 --
tests/test_sphinx/test_sphinx_builds.py | 36 ++-----------------
.../test_sphinx_builds/test_basic.html | 6 ++--
.../test_basic.resolved.xml | 2 +-
.../test_sphinx_builds/test_basic.xml | 2 +-
.../test_commonmark_only.html | 2 +-
.../test_extended_syntaxes.html | 8 ++---
.../test_extended_syntaxes.xml | 2 +-
.../test_fieldlist_extension.html | 4 +--
.../test_fieldlist_extension.xml | 4 +--
.../test_sphinx_builds/test_footnotes.html | 2 +-
.../test_heading_slug_func.html | 4 +--
.../test_sphinx_builds/test_includes.html | 14 ++++----
.../test_sphinx_builds/test_references.html | 8 ++---
.../test_references_singlehtml.html | 12 +++----
.../test_references_singlehtml.resolved.xml | 8 ++---
tox.ini | 5 ++-
25 files changed, 62 insertions(+), 130 deletions(-)
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index f668ed51..114b8269 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -25,16 +25,16 @@ jobs:
strategy:
fail-fast: false
matrix:
- python-version: ["3.10", "3.11", "3.12", "3.13"]
+ python-version: ["3.11", "3.12", "3.13"]
sphinx: [">=8,<8.2"]
os: [ubuntu-latest]
include:
- - os: ubuntu-latest
- python-version: "3.10"
- sphinx: ">=7,<8"
+ # - os: ubuntu-latest
+ # python-version: "3.11"
+ # sphinx: ">=7,<8"
- os: windows-latest
- python-version: "3.10"
- sphinx: ">=7,<8"
+ python-version: "3.11"
+ sphinx: ">=8,<8.2"
runs-on: ${{ matrix.os }}
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 8097ec15..d83d53d5 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -34,7 +34,7 @@ repos:
args: [--config-file=pyproject.toml]
additional_dependencies:
- types-urllib3
- - sphinx~=7.4
+ - sphinx~=8.2
- markdown-it-py~=3.0
- mdit-py-plugins~=0.4.0
files: >
diff --git a/docs/conf.py b/docs/conf.py
index 2fc9589d..748bec75 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -54,7 +54,7 @@
suppress_warnings = ["myst.strikethrough"]
intersphinx_mapping = {
- "python": ("https://docs.python.org/3.10", None),
+ "python": ("https://docs.python.org/3.11", None),
"sphinx": ("https://www.sphinx-doc.org/en/master", None),
"markdown_it": ("https://markdown-it-py.readthedocs.io/en/latest", None),
}
diff --git a/myst_parser/inventory.py b/myst_parser/inventory.py
index 0782752c..5ece7b6e 100644
--- a/myst_parser/inventory.py
+++ b/myst_parser/inventory.py
@@ -80,7 +80,7 @@ def to_sphinx(inv: InventoryType) -> SphinxInventoryType:
for domain_name, obj_types in inv["objects"].items():
for obj_type, refs in obj_types.items():
for refname, refdata in refs.items():
- objs.setdefault(f"{domain_name}:{obj_type}", {})[refname] = (
+ objs.setdefault(f"{domain_name}:{obj_type}", {})[refname] = ( # type: ignore[assignment]
inv["name"],
inv["version"],
refdata["loc"],
diff --git a/myst_parser/sphinx_ext/main.py b/myst_parser/sphinx_ext/main.py
index f3fe0f4a..3788a5a2 100644
--- a/myst_parser/sphinx_ext/main.py
+++ b/myst_parser/sphinx_ext/main.py
@@ -2,7 +2,6 @@
from typing import Any
-import sphinx
from docutils import nodes
from sphinx.application import Sphinx
from sphinx.transforms import (
@@ -12,9 +11,7 @@
from myst_parser.mdit_to_docutils.transforms import UnreferencedFootnotesDetector
from myst_parser.parsers.docutils_ import (
depart_container_html,
- depart_rubric_html,
visit_container_html,
- visit_rubric_html,
)
from myst_parser.warnings_ import MystWarnings
@@ -51,13 +48,6 @@ def setup_sphinx(app: Sphinx, load_parser: bool = False) -> None:
app.add_post_transform(MystReferenceResolver)
- # override only the html writer visit methods for rubric, to use the "level" attribute
- # this allows for nested headers to be correctly rendered
- if sphinx.version_info < (7, 4):
- # This is now added in sphinx: https://github.com/sphinx-doc/sphinx/pull/12506
- app.add_node(
- nodes.rubric, override=True, html=(visit_rubric_html, depart_rubric_html)
- )
# override only the html writer visit methods for container,
# to remove the "container" class for divs
# this avoids CSS clashes with the bootstrap theme
diff --git a/pyproject.toml b/pyproject.toml
index e97dff7f..c8d53761 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -15,7 +15,6 @@ classifiers = [
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"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",
@@ -32,14 +31,14 @@ keywords = [
"docutils",
"sphinx",
]
-requires-python = ">=3.10"
+requires-python = ">=3.11"
dependencies = [
"docutils>=0.19,<0.22",
"jinja2", # required for substitutions, but let sphinx choose version
"markdown-it-py~=3.0",
"mdit-py-plugins~=0.4,>=0.4.1",
"pyyaml",
- "sphinx>=7,<9",
+ "sphinx>=8,<9",
]
[project.urls]
@@ -52,7 +51,7 @@ code_style = ["pre-commit~=4.0"]
linkify = ["linkify-it-py~=2.0"]
# Note: This is only required for internal use
rtd = [
- "sphinx>=7",
+ "sphinx>=8",
"ipython",
"sphinx-book-theme~=1.1",
"sphinx-design",
diff --git a/tests/test_renderers/fixtures/sphinx_directives.md b/tests/test_renderers/fixtures/sphinx_directives.md
index bb2ba2df..357ba114 100644
--- a/tests/test_renderers/fixtures/sphinx_directives.md
+++ b/tests/test_renderers/fixtures/sphinx_directives.md
@@ -21,7 +21,7 @@ object (`sphinx.directives.ObjectDescription`):
.
-
+
something
@@ -323,7 +323,7 @@ math (`sphinx.directives.patches.MathDirective`):
```
.
-
+
.
deprecated (`sphinx.domains.changeset.VersionChange`):
@@ -347,7 +347,7 @@ versionadded (`sphinx.domains.changeset.VersionChange`):
- New in version 0.2.
+ Added in version 0.2.
.
versionchanged (`sphinx.domains.changeset.VersionChange`):
@@ -372,7 +372,7 @@ term 2 : B
```
.
-
+
@@ -404,7 +404,7 @@ cmdoption (`sphinx.domains.std.Cmdoption`):
.
-
+
a
@@ -419,7 +419,7 @@ rst:directive (`sphinx.domains.rst.ReSTDirective`):
.
-
+
.. a::
diff --git a/tests/test_renderers/test_fixtures_sphinx.py b/tests/test_renderers/test_fixtures_sphinx.py
index f763251a..32e3c189 100644
--- a/tests/test_renderers/test_fixtures_sphinx.py
+++ b/tests/test_renderers/test_fixtures_sphinx.py
@@ -96,33 +96,9 @@ def test_sphinx_directives(
sphinx_doctree_no_tr.set_conf({"extensions": ["myst_parser"]})
pformat = sphinx_doctree_no_tr(file_params.content, "index.md").pformat("index")
- # see https://github.com/sphinx-doc/sphinx/issues/9827
- pformat = pformat.replace('', "")
# see https://github.com/executablebooks/MyST-Parser/issues/522
if sys.maxsize == 2147483647:
pformat = pformat.replace('"2147483647"', '"9223372036854775807"')
- # changed in sphinx 7.1 (but fixed in 7.2)
- pformat = pformat.replace(
- 'classes="sig sig-object sig sig-object"', 'classes="sig sig-object"'
- )
- pformat = pformat.replace(
- 'classes="sig-name descname sig-name descname"', 'classes="sig-name descname"'
- )
- pformat = pformat.replace(
- 'classes="sig-prename descclassname sig-prename descclassname"',
- 'classes="sig-prename descclassname"',
- )
- # changed in sphinx 7.2 (#11533)
- pformat = pformat.replace(
- (
- 'no-contents-entry="False" no-index="False" '
- 'no-index-entry="False" no-typesetting="False" '
- ),
- "",
- )
- # changed in sphinx 7.3
- pformat = pformat.replace("Added in version 0.2", "New in version 0.2")
-
file_params.assert_expected(pformat, rstrip_lines=True)
diff --git a/tests/test_sphinx/conftest.py b/tests/test_sphinx/conftest.py
index cdb2d999..83d2c01f 100644
--- a/tests/test_sphinx/conftest.py
+++ b/tests/test_sphinx/conftest.py
@@ -84,8 +84,6 @@ def read(
for clearer_div in doc_div.findAll("div", {"class": "clearer"}):
clearer_div.decompose()
text = doc_div.prettify()
- # changed in sphinx 7.2
- text = text.replace('"Link to this', '"Permalink to this')
for find, rep in (replace or {}).items():
text = text.replace(find, rep)
file_regression.check(text, extension=regress_ext, encoding="utf8")
diff --git a/tests/test_sphinx/test_sphinx_builds.py b/tests/test_sphinx/test_sphinx_builds.py
index 8beb8748..59673db3 100644
--- a/tests/test_sphinx/test_sphinx_builds.py
+++ b/tests/test_sphinx/test_sphinx_builds.py
@@ -10,7 +10,6 @@
from pathlib import Path
import pytest
-import sphinx
from sphinx.util.console import strip_colors
SOURCE_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), "sourcedirs"))
@@ -41,10 +40,7 @@ def test_basic(
app,
docname="content",
regress=True,
- replace={
- # changed in sphinx 7.1
- '': '',
- },
+ replace={},
)
finally:
get_sphinx_app_doctree(
@@ -52,10 +48,7 @@ def test_basic(
docname="content",
resolve=True,
regress=True,
- replace={
- # changed in sphinx 7.1
- '': '',
- },
+ replace={},
)
get_sphinx_app_output(
app,
@@ -162,9 +155,6 @@ def test_references_singlehtml(
regress=True,
replace={
"other\\other.md": "other/other.md",
- # changed in sphinx 7.3
- '="#document-index': '="index.html#document-index',
- '="#document-other': '="index.html#document-other',
},
)
@@ -444,8 +434,6 @@ def test_gettext(
output = re.sub(r"POT-Creation-Date: [0-9: +-]+", "POT-Creation-Date: ", output)
output = re.sub(r"Copyright \(C\) [0-9]{4}", "Copyright (C) XXXX", output)
- if sphinx.version_info < (7, 4):
- output = output.replace("Python ", "Project name not set ")
file_regression.check(output, extension=".pot")
@@ -528,8 +516,6 @@ def test_gettext_additional_targets(
output = re.sub(r"POT-Creation-Date: [0-9: +-]+", "POT-Creation-Date: ", output)
output = re.sub(r"Copyright \(C\) [0-9]{4}", "Copyright (C) XXXX", output)
- if sphinx.version_info < (7, 4):
- output = output.replace("Python ", "Project name not set ")
file_regression.check(output, extension=".pot")
@@ -577,20 +563,7 @@ def test_fieldlist_extension(
app,
docname="index",
regress=True,
- replace={
- # changed in sphinx 7.2 for desc_sig_name node
- 'classes="n n"': 'classes="n"',
- # changed in sphinx 7.2 for desc_parameterlist node
- 'multi_line_parameter_list="False" ': "",
- # changed in sphinx 7.1 (but fixed in 7.2) for desc_signature/desc_name nodes
- 'classes="sig sig-object sig sig-object"': 'classes="sig sig-object"',
- 'classes="sig-name descname sig-name descname"': 'classes="sig-name descname"',
- # changed in sphinx 7.2 (#11533)
- (
- 'no-contents-entry="False" no-index="False" '
- 'no-index-entry="False" no-typesetting="False" '
- ): "",
- },
+ replace={},
)
finally:
get_sphinx_app_output(
@@ -614,9 +587,6 @@ def test_texinfo(app, status, warning):
assert warnings == ""
-@pytest.mark.skipif(
- sphinx.version_info < (7, 2, 5), reason="include-read event added in sphinx 7.2.5"
-)
@pytest.mark.sphinx(
buildername="html",
srcdir=os.path.join(SOURCE_DIR, "includes"),
diff --git a/tests/test_sphinx/test_sphinx_builds/test_basic.html b/tests/test_sphinx/test_sphinx_builds/test_basic.html
index b3e99c79..a87ea38a 100644
--- a/tests/test_sphinx/test_sphinx_builds/test_basic.html
+++ b/tests/test_sphinx/test_sphinx_builds/test_basic.html
@@ -29,7 +29,7 @@
Header
-
@@ -79,7 +79,7 @@
Caption
-
@@ -120,7 +120,7 @@
(1)
-
diff --git a/tests/test_sphinx/test_sphinx_builds/test_basic.resolved.xml b/tests/test_sphinx/test_sphinx_builds/test_basic.resolved.xml
index 18605dc4..8e548702 100644
--- a/tests/test_sphinx/test_sphinx_builds/test_basic.resolved.xml
+++ b/tests/test_sphinx/test_sphinx_builds/test_basic.resolved.xml
@@ -53,7 +53,7 @@
https://www.google.com
-
+
a=1{`}