Skip to content

Commit caaf174

Browse files
committed
Drop Python 3.9 support
1 parent b36d97c commit caaf174

File tree

10 files changed

+34
-64
lines changed

10 files changed

+34
-64
lines changed

.github/workflows/lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
strategy:
1818
fail-fast: false
1919
matrix:
20-
python: ["3.9", "3.10", "3.11", "3.12", "3.13"]
20+
python: ["3.10", "3.11", "3.12", "3.13"]
2121

2222
name: "Python ${{ matrix.python }}"
2323
runs-on: ubuntu-24.04

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
fail-fast: false
1919
matrix:
2020
os: ["ubuntu-24.04", "windows-2025"]
21-
python: ["3.9", "3.10", "3.11", "3.12", "3.13"]
21+
python: ["3.10", "3.11", "3.12", "3.13"]
2222

2323
name: "${{ matrix.os }} / Python ${{ matrix.python }}"
2424
runs-on: ${{ matrix.os }}

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ CharonLoad reduces the burden to start writing and experimenting with custom GPU
3838

3939
## Installation
4040

41-
CharonLoad requires **Python >=3.9** and can be installed from PyPI:
41+
CharonLoad requires **Python >=3.10** and can be installed from PyPI:
4242

4343
```sh
4444
pip install charonload

noxfile.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ def docs_live(session: nox.Session) -> None:
7171
# sphinx-build
7272
force_building = "-E"
7373
watch_dirs_and_files = ["src", "README.md", "CHANGELOG.md"]
74-
watch_args = [v for pair in zip(["--watch"] * len(watch_dirs_and_files), watch_dirs_and_files) for v in pair]
74+
watch_args = [
75+
v for pair in zip(["--watch"] * len(watch_dirs_and_files), watch_dirs_and_files, strict=True) for v in pair
76+
]
7577
session.run(
7678
"sphinx-autobuild",
7779
"-b",

pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ version = "0.2.1"
44
authors = [{ name = "Patrick Stotko", email = "[email protected]" }]
55
description = "Develop C++/CUDA extensions with PyTorch like Python scripts"
66
readme = "README.md"
7-
requires-python = ">=3.9"
7+
requires-python = ">=3.10"
88
dependencies = [
99
"cmake>=3.27",
10+
'dlltracer ; platform_system == "Windows"',
1011
'ninja ; platform_system != "Windows"',
1112
"filelock",
1213
"torch",
@@ -21,7 +22,6 @@ classifiers = [
2122
"License :: OSI Approved :: MIT License",
2223
"Programming Language :: C++",
2324
"Programming Language :: Python :: 3 :: Only",
24-
"Programming Language :: Python :: 3.9",
2525
"Programming Language :: Python :: 3.10",
2626
"Programming Language :: Python :: 3.11",
2727
"Programming Language :: Python :: 3.12",
@@ -92,7 +92,7 @@ line-length = 120
9292
[tool.isort]
9393
profile = "black"
9494
multi_line_output = 3
95-
py_version = 39
95+
py_version = 310
9696

9797

9898
[tool.docformatter]

src/charonload/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
import sys
2222

23-
required_version = (3, 8)
23+
required_version = (3, 10)
2424

2525
if sys.version_info[:2] < required_version: # pragma: no cover
2626
msg = "%s requires Python %d.%d+" % (__package__, *required_version) # noqa: UP031

src/charonload/_compat/hashlib.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
import sys
44
from hashlib import * # noqa: F403
5-
from typing import TYPE_CHECKING, BinaryIO, Callable
5+
from typing import TYPE_CHECKING, BinaryIO
66

77
if TYPE_CHECKING:
8+
from collections.abc import Callable
89
from hashlib import _Hash
910

1011

src/charonload/_config.py

Lines changed: 15 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import sysconfig
1212
import tempfile
1313
from collections import UserDict
14-
from dataclasses import dataclass
14+
from dataclasses import KW_ONLY, dataclass
1515
from typing import TYPE_CHECKING
1616

1717
import colorama
@@ -22,7 +22,7 @@
2222
colorama.just_fix_windows_console()
2323

2424

25-
@dataclass(init=False) # Python 3.10+: Use "_: KW_ONLY"
25+
@dataclass
2626
class Config:
2727
"""
2828
Set of user-specified configuration options for setting up the import logic of :class:`JITCompileFinder`.
@@ -33,14 +33,16 @@ class Config:
3333
project_directory: pathlib.Path | str
3434
"""The absolute path to the root directory of the C++/CUDA extension containing the root ``CMakeLists.txt`` file."""
3535

36-
build_directory: pathlib.Path | str | None
36+
build_directory: pathlib.Path | str | None = None
3737
"""
3838
An optional absolute path to a build directory.
3939
4040
If not specified, the build will be placed in the temporary directory of the operating system.
4141
"""
4242

43-
clean_build: bool
43+
_: KW_ONLY
44+
45+
clean_build: bool = False
4446
"""
4547
Whether to remove all cached files of previous builds from the build directory.
4648
@@ -53,13 +55,13 @@ class Config:
5355
:class:`ResolvedConfig`.
5456
"""
5557

56-
build_type: str
58+
build_type: str = "RelWithDebInfo"
5759
"""The build type passed to CMake to compile the extension."""
5860

59-
cmake_options: dict[str, str] | None
61+
cmake_options: dict[str, str] | None = None
6062
"""Additional CMake options to pass to the project when JIT compiling."""
6163

62-
stubs_directory: pathlib.Path | str | None
64+
stubs_directory: pathlib.Path | str | None = None
6365
"""
6466
An optional absolute path to the directory where stub files of the extension should be generated.
6567
@@ -68,7 +70,7 @@ class Config:
6870
if set to ``None``.
6971
"""
7072

71-
stubs_invalid_ok: bool
73+
stubs_invalid_ok: bool = False
7274
"""
7375
Whether to accept invalid stubs and skip raising an error.
7476
@@ -79,7 +81,7 @@ class Config:
7981
:class:`ResolvedConfig`.
8082
"""
8183

82-
verbose: bool
84+
verbose: bool = False
8385
"""
8486
Whether to enable printing the full log of the JIT compilation.
8587
@@ -92,36 +94,17 @@ class Config:
9294
:class:`ResolvedConfig`.
9395
"""
9496

95-
def __init__(
96-
self: Self,
97-
project_directory: pathlib.Path | str,
98-
build_directory: pathlib.Path | str | None = None,
99-
*,
100-
clean_build: bool = False,
101-
build_type: str = "RelWithDebInfo",
102-
cmake_options: dict[str, str] | None = None,
103-
stubs_directory: pathlib.Path | str | None = None,
104-
stubs_invalid_ok: bool = False,
105-
verbose: bool = False,
106-
) -> None:
107-
self.project_directory = project_directory
108-
self.build_directory = build_directory
109-
self.clean_build = clean_build
110-
self.build_type = build_type
111-
self.cmake_options = cmake_options
112-
self.stubs_directory = stubs_directory
113-
self.stubs_invalid_ok = stubs_invalid_ok
114-
self.verbose = verbose
115-
116-
117-
@dataclass(init=False) # Python 3.10+: Use "kw_only=True"
97+
98+
@dataclass
11899
class ResolvedConfig:
119100
"""
120101
Set of resolved configuration options that is **actually used** in the import logic of :class:`JITCompileFinder`.
121102
122103
This has been resolved from :class:`Config` and from the environment variables.
123104
"""
124105

106+
_: KW_ONLY
107+
125108
full_project_directory: pathlib.Path
126109
"""The full absolute path to the project directory."""
127110

@@ -146,27 +129,6 @@ class ResolvedConfig:
146129
verbose: bool
147130
"""Flag to enable printing the full log of the JIT compilation."""
148131

149-
def __init__(
150-
self: Self,
151-
*,
152-
full_project_directory: pathlib.Path,
153-
full_build_directory: pathlib.Path,
154-
clean_build: bool,
155-
build_type: str,
156-
cmake_options: dict[str, str],
157-
full_stubs_directory: pathlib.Path | None,
158-
stubs_invalid_ok: bool,
159-
verbose: bool,
160-
) -> None:
161-
self.full_project_directory = full_project_directory
162-
self.full_build_directory = full_build_directory
163-
self.clean_build = clean_build
164-
self.build_type = build_type
165-
self.cmake_options = cmake_options
166-
self.full_stubs_directory = full_stubs_directory
167-
self.stubs_invalid_ok = stubs_invalid_ok
168-
self.verbose = verbose
169-
170132

171133
class ConfigDict(UserDict[str, ResolvedConfig]):
172134
"""

src/charonload/_persistence.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66
import pathlib
77
import sys
88
from dataclasses import dataclass
9-
from typing import TYPE_CHECKING, Any, Callable
9+
from typing import TYPE_CHECKING, Any
1010

1111
from ._errors import _SerializerNotConnectedError
1212

1313
if TYPE_CHECKING: # pragma: no cover
1414
import enum
15+
from collections.abc import Callable
1516

1617
from ._compat.typing import Self
1718

src/charonload/pybind11_stubgen/__main__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88

99
import pybind11_stubgen
1010

11+
if platform.system() == "Windows":
12+
import dlltracer
13+
1114

1215
def _make_importable(full_extension_path: pathlib.Path, windows_dll_directories: str) -> None: # pragma: no cover
1316
full_extension_directory = str(full_extension_path.parent)
@@ -46,7 +49,8 @@ def main() -> None:
4649
# Patch list of command line argument globally as this list cannot directly be passed to pybind11-stubgen
4750
sys.argv = [sys.argv[0], *original_args]
4851

49-
pybind11_stubgen.main()
52+
with dlltracer.Trace(out=sys.stdout):
53+
pybind11_stubgen.main()
5054

5155

5256
if __name__ == "__main__": # pragma: no cover

0 commit comments

Comments
 (0)