Drop support for Python 3.10 (#13000)

This commit is contained in:
Adam Turner authored and GitHub committed 2024-10-17 20:59:41 +01:00
1 parent 90db3e1b89
commit 541bf7bc67
23 files changed
+45 -169

No files matched your search

-1
View File
@@ -33,7 +33,6 @@ jobs:
fail-fast: false
matrix:
python:
- "3.10"
- "3.11"
- "3.12"
- "3.13"
+1 -1
View File
@@ -1,4 +1,4 @@
target-version = "py310" # Pin Ruff to Python 3.10
target-version = "py311" # Pin Ruff to Python 3.11
line-length = 88
output-format = "full"
+2
View File
@@ -4,6 +4,8 @@ Release 8.2.0 (in development)
Dependencies
------------
* #13000: Drop Python 3.10 support.
Incompatible changes
--------------------
+3 -3
View File
@@ -188,18 +188,18 @@ of targets and allows testing against multiple different Python environments:
tox -av
* To run unit tests for a specific Python version, such as Python 3.12:
* To run unit tests for a specific Python version, such as Python 3.13:
.. code-block:: shell
tox -e py312
tox -e py313
* Arguments to :program:`pytest` can be passed via :program:`tox`,
e.g., in order to run a particular test:
.. code-block:: shell
tox -e py312 tests/test_module.py::test_new_feature
tox -e py313 tests/test_module.py::test_new_feature
You can also test by installing dependencies in your local environment:
+4 -4
View File
@@ -152,18 +152,18 @@ Install either ``python3x-sphinx`` using :command:`port`:
::
$ sudo port install py312-sphinx
$ sudo port install py313-sphinx
To set up the executable paths, use the ``port select`` command:
::
$ sudo port select --set python python312
$ sudo port select --set sphinx py312-sphinx
$ sudo port select --set python python313
$ sudo port select --set sphinx py313-sphinx
For more information, refer to the `package overview`__.
__ https://www.macports.org/ports.php?by=library&substr=py312-sphinx
__ https://www.macports.org/ports.php?by=library&substr=py313-sphinx
Windows
~~~~~~~
+2 -5
View File
@@ -14,7 +14,7 @@ urls.Download = "https://pypi.org/project/Sphinx/"
urls.Homepage = "https://www.sphinx-doc.org/"
urls."Issue tracker" = "https://github.com/sphinx-doc/sphinx/issues"
license.text = "BSD-2-Clause"
requires-python = ">=3.10"
requires-python = ">=3.11"
# Classifiers list: https://pypi.org/classifiers/
classifiers = [
@@ -31,7 +31,6 @@ classifiers = [
"Programming Language :: Python",
"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",
@@ -71,7 +70,6 @@ dependencies = [
"imagesize>=1.3",
"requests>=2.30.0",
"packaging>=23.0",
"tomli>=2; python_version < '3.11'",
"colorama>=0.4.6; sys_platform == 'win32'",
]
dynamic = ["version"]
@@ -92,7 +90,6 @@ lint = [
"types-Pygments==2.18.0.20240506",
"types-requests==2.32.0.20240914", # align with requests
"types-urllib3==1.26.25.14",
"tomli>=2", # for mypy (Python<=3.10)
"pyright==1.1.384",
"pytest>=6.0",
]
@@ -204,7 +201,7 @@ exclude = [
# tests/test_writers
"^utils/convert_attestations\\.py$",
]
python_version = "3.10"
python_version = "3.11"
strict = true
show_column_numbers = true
show_error_context = true
+1 -5
View File
@@ -12,6 +12,7 @@ from __future__ import annotations
import os
import subprocess
import sys
from contextlib import chdir
from os import path
from typing import TYPE_CHECKING
@@ -20,11 +21,6 @@ from sphinx.cmd.build import build_main
from sphinx.util.console import blue, bold, color_terminal, nocolor
from sphinx.util.osutil import rmtree
if sys.version_info >= (3, 11):
from contextlib import chdir
else:
from sphinx.util.osutil import _chdir as chdir
if TYPE_CHECKING:
from collections.abc import Sequence
+1 -6
View File
@@ -2,11 +2,11 @@
from __future__ import annotations
import sys
import time
import traceback
import types
import warnings
from contextlib import chdir
from os import getenv, path
from typing import TYPE_CHECKING, Any, Literal, NamedTuple
@@ -16,11 +16,6 @@ from sphinx.locale import _, __
from sphinx.util import logging
from sphinx.util.osutil import fs_encoding
if sys.version_info >= (3, 11):
from contextlib import chdir
else:
from sphinx.util.osutil import _chdir as chdir
if TYPE_CHECKING:
import os
from collections.abc import Collection, Iterable, Iterator, Sequence, Set
+1 -2
View File
@@ -4,10 +4,9 @@ from typing import TYPE_CHECKING, overload
if TYPE_CHECKING:
from collections.abc import Iterable, Iterator, Mapping, Set
from typing import Any, Final, Literal, NoReturn
from typing import Any, Final, Literal, NoReturn, Self
from docutils import nodes
from typing_extensions import Self
from sphinx.domains import Domain
from sphinx.domains.c import CDomain
+1 -2
View File
@@ -12,8 +12,7 @@ from sphinx.util import logging
if TYPE_CHECKING:
from collections.abc import Callable, Iterable, Iterator, Sequence
from typing_extensions import Self
from typing import Self
from sphinx.environment import BuildEnvironment
+2 -9
View File
@@ -10,6 +10,7 @@ import os
import shutil
import sys
import tempfile
import tomllib
from importlib.metadata import entry_points
from os import path
from typing import TYPE_CHECKING, Any
@@ -22,17 +23,9 @@ from sphinx.locale import __
from sphinx.util import logging
from sphinx.util.osutil import ensuredir
if sys.version_info >= (3, 11):
import tomllib
else:
import tomli as tomllib
if TYPE_CHECKING:
from collections.abc import Callable
from typing import TypedDict
from typing_extensions import Required
from typing import Required, TypedDict
from sphinx.application import Sphinx
+2 -6
View File
@@ -4,8 +4,7 @@ from __future__ import annotations
import os
import re
import sys
from datetime import datetime, timezone
from datetime import datetime
from os import path
from typing import TYPE_CHECKING, NamedTuple
@@ -60,10 +59,7 @@ if TYPE_CHECKING:
Formatter: TypeAlias = DateFormatter | TimeFormatter | DatetimeFormatter
if sys.version_info[:2] >= (3, 11):
from datetime import UTC
else:
UTC = timezone.utc
from datetime import UTC
logger = logging.getLogger(__name__)
-26
View File
@@ -17,7 +17,6 @@ from typing import TYPE_CHECKING
from sphinx.locale import __
if TYPE_CHECKING:
from types import TracebackType
from typing import Any
# SEP separates path elements in the canonical file names
@@ -173,31 +172,6 @@ fs_encoding = sys.getfilesystemencoding() or sys.getdefaultencoding()
abspath = path.abspath
class _chdir:
"""Remove this fall-back once support for Python 3.10 is removed."""
def __init__(self, target_dir: str, /) -> None:
self.path = target_dir
self._dirs: list[str] = []
def __enter__(self) -> None:
self._dirs.append(os.getcwd())
os.chdir(self.path)
def __exit__(
self,
type: type[BaseException] | None,
value: BaseException | None,
traceback: TracebackType | None,
/,
) -> None:
os.chdir(self._dirs.pop())
if sys.version_info[:2] < (3, 11):
cd = _chdir
class FileAvoidWrite:
"""File-like object that buffers output and only writes if content changed.
+4 -16
View File
@@ -18,6 +18,7 @@ from typing import (
TypedDict,
TypeVar,
Union,
Unpack,
)
from docutils import nodes
@@ -121,8 +122,7 @@ TitleGetter: TypeAlias = Callable[[nodes.Node], str]
# Readable file stream for inventory loading
if TYPE_CHECKING:
from types import TracebackType
from typing_extensions import Self
from typing import Self
_T_co = TypeVar('_T_co', str, bytes, covariant=True)
@@ -221,19 +221,7 @@ def _is_annotated_form(obj: Any) -> TypeIs[Annotated[Any, ...]]:
def _is_unpack_form(obj: Any) -> bool:
"""Check if the object is :class:`typing.Unpack` or equivalent."""
if sys.version_info >= (3, 11):
from typing import Unpack
# typing_extensions.Unpack != typing.Unpack for 3.11, but we assume
# that typing_extensions.Unpack should not be used in that case
return typing.get_origin(obj) is Unpack
# Python 3.10 requires typing_extensions.Unpack
origin = typing.get_origin(obj)
return (
getattr(origin, '__module__', None) == 'typing_extensions'
and origin.__name__ == 'Unpack'
)
return typing.get_origin(obj) is Unpack
def restify(cls: Any, mode: _RestifyMode = 'fully-qualified-except-typing') -> str:
@@ -361,7 +349,7 @@ def restify(cls: Any, mode: _RestifyMode = 'fully-qualified-except-typing') -> s
return rf'{text}\ [{args}]'
elif isinstance(cls, typing._SpecialForm):
return f':py:obj:`~{cls.__module__}.{cls.__name__}`' # type: ignore[attr-defined]
elif sys.version_info[:2] >= (3, 11) and cls is typing.Any:
elif cls is typing.Any:
# handle bpo-46998
return f':py:obj:`~{cls.__module__}.{cls.__name__}`'
elif hasattr(cls, '__qualname__'):
+1 -6
View File
@@ -4,18 +4,13 @@ import gettext
import os
import re
import subprocess
import sys
from contextlib import chdir
from subprocess import CalledProcessError
import pytest
from sphinx.builders.gettext import Catalog, MsgOrigin
if sys.version_info[:2] >= (3, 11):
from contextlib import chdir
else:
from sphinx.util.osutil import _chdir as chdir
_MSGID_PATTERN = re.compile(r'msgid "((?:\n|.)*?)"\nmsgstr', re.MULTILINE)
+1 -5
View File
@@ -4,6 +4,7 @@ import http.server
import os
import re
import subprocess
from contextlib import chdir
from pathlib import Path
from shutil import copyfile
from subprocess import CalledProcessError
@@ -20,11 +21,6 @@ from sphinx.writers.latex import LaTeXTranslator
from tests.utils import http_server
try:
from contextlib import chdir
except ImportError:
from sphinx.util.osutil import _chdir as chdir
STYLEFILES = [
'article.cls',
'fancyhdr.sty',
+1 -3
View File
@@ -1571,13 +1571,11 @@ class _EnumFormatter:
'(value, names=None, *values, module=None, '
'qualname=None, type=None, start=1, boundary=None)'
)
elif sys.version_info[:2] >= (3, 11):
else:
args = (
'(value, names=None, *, module=None, qualname=None, '
'type=None, start=1, boundary=None)'
)
else:
args = '(value)'
return self._node('class', self.name, doc, args=args, indent=indent, **options)
@@ -692,10 +692,6 @@ def test_mocked_module_imports(app):
confoverrides={'autodoc_typehints': 'signature'},
)
def test_autodoc_typehints_signature(app):
if sys.version_info[:2] <= (3, 10):
type_o = '~typing.Any | None'
else:
type_o = '~typing.Any'
if sys.version_info[:2] >= (3, 13):
type_ppp = 'pathlib._local.PurePosixPath'
else:
@@ -732,7 +728,7 @@ def test_autodoc_typehints_signature(app):
' docstring',
'',
'',
'.. py:class:: Math(s: str, o: %s = None)' % type_o,
'.. py:class:: Math(s: str, o: ~typing.Any = None)',
' :module: target.typehints',
'',
'',
@@ -1511,10 +1507,6 @@ def test_autodoc_typehints_description_and_type_aliases(app):
confoverrides={'autodoc_typehints_format': 'fully-qualified'},
)
def test_autodoc_typehints_format_fully_qualified(app):
if sys.version_info[:2] <= (3, 10):
type_o = 'typing.Any | None'
else:
type_o = 'typing.Any'
if sys.version_info[:2] >= (3, 13):
type_ppp = 'pathlib._local.PurePosixPath'
else:
@@ -1550,7 +1542,7 @@ def test_autodoc_typehints_format_fully_qualified(app):
' docstring',
'',
'',
'.. py:class:: Math(s: str, o: %s = None)' % type_o,
'.. py:class:: Math(s: str, o: typing.Any = None)',
' :module: target.typehints',
'',
'',
@@ -1,6 +1,7 @@
"""Test the autosummary extension."""
import sys
from contextlib import chdir
from io import StringIO
from unittest.mock import Mock, patch
from xml.etree.ElementTree import Element
@@ -25,11 +26,6 @@ from sphinx.ext.autosummary.generate import main as autogen_main
from sphinx.testing.util import assert_node, etree_parse
from sphinx.util.docutils import new_document
try:
from contextlib import chdir
except ImportError:
from sphinx.util.osutil import _chdir as chdir
html_warnfile = StringIO()
+1 -1
View File
@@ -95,7 +95,7 @@ def test_format_date():
def test_format_date_timezone():
dt = datetime.datetime(2016, 8, 7, 5, 11, 17, 0, tzinfo=datetime.timezone.utc)
dt = datetime.datetime(2016, 8, 7, 5, 11, 17, 0, tzinfo=datetime.UTC)
if time.localtime(dt.timestamp()).tm_gmtoff == 0:
raise pytest.skip('Local time zone is GMT') # NoQA: EM101
+3 -13
View File
@@ -6,7 +6,6 @@ import ast
import datetime
import enum
import functools
import sys
import types
from inspect import Parameter
from typing import Callable, List, Optional, Union # NoQA: UP035
@@ -272,10 +271,7 @@ def test_signature_annotations():
# Space around '=' for defaults
sig = inspect.signature(mod.f7)
sig_str = stringify_signature(sig)
if sys.version_info[:2] <= (3, 10):
assert sig_str == '(x: int | None = None, y: dict = {}) -> None'
else:
assert sig_str == '(x: int = None, y: dict = {}) -> None'
assert sig_str == '(x: int = None, y: dict = {}) -> None'
# Callable types
sig = inspect.signature(mod.f8)
@@ -355,18 +351,12 @@ def test_signature_annotations():
# show_return_annotation is False
sig = inspect.signature(mod.f7)
sig_str = stringify_signature(sig, show_return_annotation=False)
if sys.version_info[:2] <= (3, 10):
assert sig_str == '(x: int | None = None, y: dict = {})'
else:
assert sig_str == '(x: int = None, y: dict = {})'
assert sig_str == '(x: int = None, y: dict = {})'
# unqualified_typehints is True
sig = inspect.signature(mod.f7)
sig_str = stringify_signature(sig, unqualified_typehints=True)
if sys.version_info[:2] <= (3, 10):
assert sig_str == '(x: int | None = None, y: dict = {}) -> None'
else:
assert sig_str == '(x: int = None, y: dict = {}) -> None'
assert sig_str == '(x: int = None, y: dict = {}) -> None'
# case: separator at head
sig = inspect.signature(mod.f22)
+9 -38
View File
@@ -173,10 +173,7 @@ def test_restify_type_hints_containers():
ann_rst = restify(Tuple[str, ...])
assert ann_rst == ':py:class:`~typing.Tuple`\\ [:py:class:`str`, ...]'
if sys.version_info[:2] <= (3, 10):
assert restify(Tuple[()]) == ':py:class:`~typing.Tuple`\\ [()]'
else:
assert restify(Tuple[()]) == ':py:class:`~typing.Tuple`'
assert restify(Tuple[()]) == ':py:class:`~typing.Tuple`'
assert restify(List[Dict[str, Tuple]]) == (
':py:class:`~typing.List`\\ '
@@ -423,10 +420,9 @@ def test_restify_Unpack():
assert restify(UnpackCompat['X'], 'fully-qualified-except-typing') == expect
assert restify(UnpackCompat['X'], 'smart') == expect
if sys.version_info[:2] >= (3, 11):
expect = r':py:obj:`~typing.Unpack`\ [:py:class:`X`]'
assert restify(t.Unpack['X'], 'fully-qualified-except-typing') == expect
assert restify(t.Unpack['X'], 'smart') == expect
expect = r':py:obj:`~typing.Unpack`\ [:py:class:`X`]'
assert restify(t.Unpack['X'], 'fully-qualified-except-typing') == expect
assert restify(t.Unpack['X'], 'smart') == expect
def test_restify_type_union_operator():
@@ -534,17 +530,9 @@ def test_stringify_type_hints_containers():
assert ann_str == 'typing.Tuple[str, ...]'
assert stringify_annotation(Tuple[str, ...], 'smart') == '~typing.Tuple[str, ...]'
if sys.version_info[:2] <= (3, 10):
ann_str = stringify_annotation(Tuple[()], 'fully-qualified-except-typing')
assert ann_str == 'Tuple[()]'
assert stringify_annotation(Tuple[()], 'fully-qualified') == 'typing.Tuple[()]'
assert stringify_annotation(Tuple[()], 'smart') == '~typing.Tuple[()]'
else:
assert (
stringify_annotation(Tuple[()], 'fully-qualified-except-typing') == 'Tuple'
)
assert stringify_annotation(Tuple[()], 'fully-qualified') == 'typing.Tuple'
assert stringify_annotation(Tuple[()], 'smart') == '~typing.Tuple'
assert stringify_annotation(Tuple[()], 'fully-qualified-except-typing') == 'Tuple'
assert stringify_annotation(Tuple[()], 'fully-qualified') == 'typing.Tuple'
assert stringify_annotation(Tuple[()], 'smart') == '~typing.Tuple'
ann_str = stringify_annotation(
List[Dict[str, Tuple]], 'fully-qualified-except-typing'
@@ -677,30 +665,13 @@ def test_stringify_Annotated():
def test_stringify_Unpack():
from typing_extensions import Unpack as UnpackCompat
class X(t.TypedDict):
x: int
y: int
label: str
if sys.version_info[:2] >= (3, 11):
# typing.Unpack is introduced in 3.11 but typing_extensions.Unpack only
# uses typing.Unpack in 3.12+, so the objects are not synchronised with
# each other, but we will assume that users use typing.Unpack.
import typing
UnpackCompat = typing.Unpack # NoQA: F811
assert stringify_annotation(UnpackCompat['X']) == 'Unpack[X]'
assert stringify_annotation(UnpackCompat['X'], 'smart') == '~typing.Unpack[X]'
else:
assert stringify_annotation(UnpackCompat['X']) == 'typing_extensions.Unpack[X]'
ann_str = stringify_annotation(UnpackCompat['X'], 'smart')
assert ann_str == '~typing_extensions.Unpack[X]'
if sys.version_info[:2] >= (3, 11):
assert stringify_annotation(t.Unpack['X']) == 'Unpack[X]'
assert stringify_annotation(t.Unpack['X'], 'smart') == '~typing.Unpack[X]'
assert stringify_annotation(t.Unpack['X']) == 'Unpack[X]'
assert stringify_annotation(t.Unpack['X'], 'smart') == '~typing.Unpack[X]'
def test_stringify_type_hints_string():
+2 -2
View File
@@ -1,6 +1,6 @@
[tox]
minversion = 4.2.0
envlist = py{310,311,312,313}
envlist = py{311,312,313}
[testenv]
usedevelop = True
@@ -19,7 +19,7 @@ passenv =
BUILDER
READTHEDOCS
description =
py{310,311,312,313}: Run unit tests against {envname}.
py{311,312,313}: Run unit tests against {envname}.
extras =
test
setenv =