Skip to content

Commit 0a695b0

Browse files
committed
DEP: drop support for CPython 3.10
1 parent 7f4fbad commit 0a695b0

12 files changed

Lines changed: 55 additions & 249 deletions

File tree

.github/workflows/cd.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ jobs:
5656
persist-credentials: false
5757
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
5858
with:
59-
python-version: '3.10'
59+
python-version: '3.11'
6060
enable-cache: true
6161
prune-cache: false
6262
cache-suffix: test-sdist

.github/workflows/check-pre-commit-hooks.yml

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ jobs:
3333
os:
3434
- ubuntu-latest
3535
python-version:
36-
- 3.10.0
37-
- '3.13'
36+
- 3.11.0
37+
- '3.14'
3838
pre-commit-version:
3939
- 3.8.0 # minimal requirement for pre-commit-uv
4040
- latest
@@ -54,9 +54,13 @@ jobs:
5454
path: downstream
5555
repository: ${{ matrix.downstream }}
5656
persist-credentials: false
57-
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
57+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
58+
# 3.11.0 isn't available through setup-uv
5859
with:
5960
python-version: ${{ matrix.python-version }}
61+
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
62+
with:
63+
enable-cache: false
6064
- name: Run pre-commit hooks
6165
# we use pre-commit-uv to ensure that the workspace configuration is read from
6266
# the root pyproject.toml, so that we run against the dev branch of inifix

.github/workflows/ci.yml

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,17 @@ jobs:
2929
python-jit: [null]
3030
include:
3131
- os: ubuntu-22.04
32-
python-version: 3.10.0
32+
python-version: 3.11.0
3333
label: oldestdeps
3434
- os: macos-latest
35-
python-version: 3.10.0
35+
python-version: 3.11.0
3636
- os: macos-latest
3737
python-version: '3.14'
3838
- os: windows-latest
39-
python-version: 3.10.0
39+
# 3.11.0 and 3.11.1 have a platform-specific self-triggered warning
40+
# breaking pytest at collection time, and that I don't want to just
41+
# ignore unconditionally
42+
python-version: 3.11.2
4043
- os: windows-latest
4144
python-version: '3.14'
4245
- os: ubuntu-latest
@@ -54,9 +57,13 @@ jobs:
5457
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
5558
with:
5659
persist-credentials: false
57-
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
60+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
61+
# 3.11.0 isn't available through setup-uv
5862
with:
5963
python-version: ${{ matrix.python-version }}
64+
allow-prereleases: true
65+
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
66+
with:
6067
enable-cache: true
6168
prune-cache: false
6269
cache-suffix: covcheck
@@ -98,7 +105,7 @@ jobs:
98105
os:
99106
- ubuntu-latest
100107
python-version:
101-
- 3.10.0
108+
- 3.11.0
102109
- '3.14'
103110
- 3.14t
104111

@@ -107,9 +114,12 @@ jobs:
107114
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
108115
with:
109116
persist-credentials: false
110-
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
117+
- uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
118+
# 3.11.0 isn't available through setup-uv
111119
with:
112120
python-version: ${{ matrix.python-version }}
121+
- uses: astral-sh/setup-uv@681c641aba71e4a1c380be3ab5e12ad51f415867 # v7.1.6
122+
with:
113123
enable-cache: true
114124
prune-cache: false
115125
cache-suffix: concurrency
@@ -159,8 +169,8 @@ jobs:
159169
strategy:
160170
matrix:
161171
python-version:
162-
- '3.10'
163-
- '3.13'
172+
- '3.11'
173+
- '3.14'
164174
typechecker:
165175
- mypy
166176
- pyright

lib/inifix/pyproject.toml

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ classifiers = [
1919
"Operating System :: MacOS",
2020
"Operating System :: Microsoft :: Windows",
2121
"Programming Language :: Python :: 3",
22-
"Programming Language :: Python :: 3.10",
2322
"Programming Language :: Python :: 3.11",
2423
"Programming Language :: Python :: 3.12",
2524
"Programming Language :: Python :: 3.13",
@@ -29,11 +28,8 @@ classifiers = [
2928
"Topic :: Scientific/Engineering",
3029
"Typing :: Typed",
3130
]
32-
requires-python = ">=3.10"
33-
dependencies = [
34-
"exceptiongroup>=1.0.0 ; python_full_version < '3.11'",
35-
"typing-extensions>=4.2.0 ; python_full_version < '3.11'",
36-
]
31+
requires-python = ">=3.11"
32+
dependencies = []
3733

3834
[project.readme]
3935
file = "README.md"

lib/inifix/src/inifix/_floatencoder.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
import re
2-
import sys
32
from enum import Enum, auto
4-
5-
if sys.version_info >= (3, 11):
6-
from typing import assert_never
7-
else:
8-
from typing_extensions import assert_never
3+
from typing import assert_never
94

105
__all__ = ["FloatEncoder"]
116

lib/inifix/src/inifix/_validation.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
11
import re
2-
import sys
32
from enum import Enum, auto
4-
from typing import Literal
3+
from typing import Literal, assert_never
54

65
from inifix._typing import AnyConfig
76

8-
if sys.version_info >= (3, 11):
9-
from typing import assert_never
10-
else:
11-
from exceptiongroup import ExceptionGroup
12-
from typing_extensions import assert_never
13-
147
_PARAM_NAME_REGEXP = re.compile(r"[-\.\w]+")
158
SCALAR_TYPES = (int, float, bool, str)
169

lib/inifix/tests/test_schema_validation.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
1-
import sys
2-
31
import pytest
42
from pytest import RaisesExc, RaisesGroup
53

64
from inifix import dump, dumps, load, loads, validate_inifile_schema
75

86
from .utils import assert_dict_equal
97

10-
if sys.version_info < (3, 11):
11-
from exceptiongroup import ExceptionGroup
12-
138

149
def test_validate_known_files(inifile):
1510
conf = load(inifile)

pyproject.toml

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,9 @@ description = "A command line interface for inifix."
99
authors = [
1010
{ name = "C.M.T. Robert" },
1111
]
12-
requires-python = ">=3.10"
12+
requires-python = ">=3.11"
1313
dependencies = [
1414
"click>=8.3.1",
15-
"exceptiongroup>=1.0.0", # TODO: remove when support for Python 3.10 is dropped
1615
"inifix==6.1.2",
1716
"typing-extensions>=4.4.0 ; python_full_version < '3.12'",
1817
]
@@ -36,7 +35,6 @@ concurrency = [
3635
]
3736
covcheck = [
3837
{include-group = "test"},
39-
"coverage[toml] ; python_version == '3.10'",
4038
"coverage>=7.10.0",
4139
]
4240
typecheck = [
@@ -51,12 +49,6 @@ members = ["lib/inifix"]
5149
[tool.uv.sources]
5250
inifix = { workspace = true }
5351

54-
[tool.uv]
55-
constraint-dependencies = [
56-
# https://github.com/HypothesisWorks/hypothesis/issues/4602
57-
"hypothesis <= 6.144.1; python_full_version < '3.10.2'",
58-
]
59-
6052
[tool.ruff.lint]
6153
exclude = ["*__init__.py"]
6254
ignore = ["E501"]
@@ -108,15 +100,8 @@ reportUnreachable = false
108100
reportUnnecessaryIsInstance = false
109101
reportUnnecessaryComparison = false
110102

111-
# in some instances, pyright and basedpyright may conflict over a single line,
112-
# where e.g. pyright reports an error that I wish to ignore, but basedpyright
113-
# complains about an unused `# pyright: ignore[...]` comment
114-
# At the time of writing, it appears that this setting can be lifted once
115-
# Python 3.10 is unsupported
116-
reportUnnecessaryTypeIgnoreComment = false
117-
118103
[tool.mypy]
119-
python_version = "3.10"
104+
python_version = "3.11"
120105
strict = true
121106
show_error_codes = true
122107
show_error_context = true

scripts/pre_publish_checks.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# /// script
2-
# requires-python = ">=3.10"
2+
# requires-python = ">=3.11"
33
# dependencies = [
44
# "loguru==0.7.3",
55
# "packaging==24.2",
6-
# "tomli==2.2.1 ; python_version < '3.11'",
76
# ]
87
# ///
98
import re
109
import subprocess
1110
import sys
11+
import tomllib
1212
from dataclasses import dataclass
1313
from difflib import unified_diff
1414
from pathlib import Path
@@ -18,12 +18,6 @@
1818
from packaging.specifiers import Specifier
1919
from packaging.version import Version
2020

21-
if sys.version_info >= (3, 11):
22-
import tomllib
23-
else:
24-
import tomli as tomllib
25-
26-
2721
logger.remove()
2822
logger.add(sys.stderr, colorize=True, format="<level>{level:<5} {message}</level>")
2923

src/inifix_cli/__init__.py

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,13 @@
1212
from textwrap import indent
1313
import inifix
1414

15-
# TODO: replace this with except* when support for Python 3.10 is dropped
16-
from exceptiongroup import catch, BaseExceptionGroup
17-
1815
if sys.version_info >= (3, 12):
1916
from typing import override
2017
else:
2118
from typing_extensions import override
2219

2320
if TYPE_CHECKING:
24-
from inifix._typing import AnyConfig # pyright: ignore[reportPrivateImportUsage]
21+
from inifix._typing import AnyConfig
2522

2623

2724
@click.group("inifix")
@@ -45,7 +42,7 @@ def get_cpu_count() -> int:
4542
base_cpu_count = os.process_cpu_count()
4643
elif hasattr(os, "sched_getaffinity"):
4744
# this function isn't available on all platforms
48-
base_cpu_count = len(os.sched_getaffinity(0)) # pyright: ignore[reportAttributeAccessIssue]
45+
base_cpu_count = len(os.sched_getaffinity(0))
4946
else: # pragma: no cover
5047
# this proxy is good enough in most situations
5148
base_cpu_count = os.cpu_count()
@@ -107,19 +104,17 @@ def _validate_single_file(file: str, sections: SectionsArg) -> TaskResults:
107104
messages.append(Message(f"Error: could not find {file}"))
108105
return TaskResults(status, messages)
109106

110-
# TODO: rewrite this section with try/except*/else when support for Python 3.10 is dropped
111-
def value_error_handler(exc: BaseExceptionGroup[Exception]) -> None:
112-
nonlocal status
107+
# mypy struggles to infer sections.name
108+
sections_name = cast("Literal['allow', 'forbid', 'require']", sections.name) # pyright: ignore[reportUnnecessaryCast] # ty: ignore[redundant-cast]
109+
try:
110+
_ = inifix.load(file, sections=sections_name)
111+
except* ValueError as excgroup:
113112
status = 1
114-
exc_repr = "\n".join(str(e) for e in exc.exceptions)
113+
exc_repr = "\n".join(str(e) for e in excgroup.exceptions)
115114
messages.append(
116115
Message(f"Failed to validate {file}:\n{indent(exc_repr, ' ')}")
117116
)
118-
119-
with catch({ValueError: value_error_handler}):
120-
# mypy struggles to infer sections.name
121-
sections_name = cast("Literal['allow', 'forbid', 'require']", sections.name) # pyright: ignore[reportUnnecessaryCast] # ty: ignore[redundant-cast]
122-
_ = inifix.load(file, sections=sections_name)
117+
else:
123118
messages.append(Message(f"Validated {file}"))
124119

125120
return TaskResults(status, messages)
@@ -195,19 +190,16 @@ def _format_single_file(
195190

196191
validate_baseline: AnyConfig = {}
197192
if not skip_validation:
198-
# TODO: rewrite this section with try/except* when support for Python 3.10 is dropped
199-
def value_error_handler(exc: BaseExceptionGroup[Exception]) -> None:
200-
nonlocal status
193+
# mypy struggles to infer sections.name
194+
sections_name = cast("Literal['allow', 'forbid', 'require']", sections.name) # pyright: ignore[reportUnnecessaryCast] # ty: ignore[redundant-cast]
195+
try:
196+
validate_baseline = inifix.load(file, sections=sections_name)
197+
except* ValueError as excgroup:
201198
status = 1
202-
exc_repr = "\n".join(str(e) for e in exc.exceptions)
199+
exc_repr = "\n".join(str(e) for e in excgroup.exceptions)
203200
messages.append(
204201
Message(f"Failed to format {file}:\n{indent(exc_repr, ' ')}")
205202
)
206-
207-
with catch({ValueError: value_error_handler}):
208-
# mypy struggles to infer sections.name
209-
sections_name = cast("Literal['allow', 'forbid', 'require']", sections.name) # pyright: ignore[reportUnnecessaryCast] # ty: ignore[redundant-cast]
210-
validate_baseline = inifix.load(file, sections=sections_name)
211203
if status != 0:
212204
return TaskResults(status, messages)
213205

0 commit comments

Comments
 (0)