Skip to content

Commit 19196a8

Browse files
Drop 3.9 support (#3345)
* Drop 3.9 * Fixes for CI * Address PR feedback * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Better pass through - Fix a few typos - Remove unnecessary generic function infrastructure - Deduplicate `from typing import ...` imports - Fix codecov complains * Undo ruff autofix * A few more codecov changes I'm not so sure about the unix pipes change. I suppose we'll get comments if it doesn't work? I can't tell why the code was there to begin with, which is a bad sign for being able to tell whether it's necessary anymore. * Fix pip-compile files --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent bd3787f commit 19196a8

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+203
-365
lines changed

.github/workflows/autodeps.yml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,21 @@ jobs:
2626
- name: Setup python
2727
uses: actions/setup-python@v5
2828
with:
29-
python-version: "3.9"
29+
python-version: "3.10"
3030

3131
- name: Bump dependencies
3232
run: |
3333
python -m pip install -U pip pre-commit
3434
python -m pip install -r test-requirements.txt
35-
uv pip compile --universal --python-version=3.9 --upgrade test-requirements.in -o test-requirements.txt
35+
uv pip compile --universal --python-version=3.10 --upgrade test-requirements.in -o test-requirements.txt
3636
uv pip compile --universal --python-version=3.11 --upgrade docs-requirements.in -o docs-requirements.txt
3737
pre-commit autoupdate --jobs 0
3838
3939
- name: Install new requirements
4040
run: python -m pip install -r test-requirements.txt
4141

42-
# apply newer versions' formatting
43-
- name: Black
44-
run: black src/trio
45-
46-
- name: uv
47-
run: |
48-
uv pip compile --universal --python-version=3.9 test-requirements.in -o test-requirements.txt
49-
uv pip compile --universal --python-version=3.11 docs-requirements.in -o docs-requirements.txt
42+
- name: Pre-commit fixes
43+
run: pre-commit run -a
5044

5145
- name: Commit changes and create automerge PR
5246
env:

.github/workflows/ci.yml

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -155,18 +155,18 @@ jobs:
155155
strategy:
156156
fail-fast: false
157157
matrix:
158-
python: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
158+
python: ['3.10', '3.11', '3.12', '3.13', '3.14']
159159
arch: ['x86', 'x64']
160160
lsp: ['']
161161
lsp_extract_file: ['']
162162
extra_name: ['']
163163
include:
164-
- python: '3.9'
164+
- python: '3.10'
165165
arch: 'x64'
166166
lsp: 'https://raw.githubusercontent.com/python-trio/trio-ci-assets/master/komodia-based-vpn-setup.zip'
167167
lsp_extract_file: 'komodia-based-vpn-setup.exe'
168168
extra_name: ', with Komodia LSP'
169-
- python: '3.9'
169+
- python: '3.10'
170170
arch: 'x64'
171171
lsp: 'https://www.proxifier.com/download/legacy/ProxifierSetup342.exe'
172172
lsp_extract_file: ''
@@ -176,7 +176,7 @@ jobs:
176176
lsp: ''
177177
lsp_extract_file: ''
178178
extra_name: ''
179-
#- python: '3.9'
179+
#- python: '3.10'
180180
# arch: 'x64'
181181
# lsp: 'http://download.pctools.com/mirror/updates/9.0.0.2308-SDavfree-lite_en.exe'
182182
# lsp_extract_file: ''
@@ -228,7 +228,7 @@ jobs:
228228
strategy:
229229
fail-fast: false
230230
matrix:
231-
python: ['pypy-3.11', '3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
231+
python: ['pypy-3.11', '3.10', '3.11', '3.12', '3.13', '3.14']
232232
check_formatting: ['0']
233233
no_test_requirements: ['0']
234234
extra_name: ['']
@@ -237,7 +237,7 @@ jobs:
237237
check_formatting: '1'
238238
extra_name: ', check formatting'
239239
# separate test run that doesn't install test-requirements.txt
240-
- python: '3.9'
240+
- python: '3.10'
241241
no_test_requirements: '1'
242242
extra_name: ', no test-requirements'
243243
continue-on-error: >-
@@ -301,7 +301,7 @@ jobs:
301301
strategy:
302302
fail-fast: false
303303
matrix:
304-
python: ['pypy-3.11', '3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
304+
python: ['pypy-3.11', '3.10', '3.11', '3.12', '3.13', '3.14']
305305
continue-on-error: >-
306306
${{
307307
(
@@ -389,14 +389,17 @@ jobs:
389389
fail-fast: false
390390
matrix:
391391
include:
392-
- python: '3.9' # We support running on cython 2 and 3 for 3.9
393-
cython: '<3' # cython 2
394-
- python: '3.9'
395-
cython: '>=3' # cython 3 (or greater)
396-
- python: '3.11' # 3.11 is the last version Cy2 supports
397-
cython: '<3' # cython 2
398-
- python: '3.13' # We support running cython3 on 3.13
399-
cython: '>=3' # cython 3 (or greater)
392+
# Cython 2 supports 3.10 and 3.11 and Cython 3 supports all versions we do,
393+
# so test both the lowest and higher version for both
394+
- python: '3.10'
395+
cython: '<3'
396+
- python: '3.11'
397+
cython: '<3'
398+
# TODO: technically we should pin cython versions
399+
- python: '3.10'
400+
cython: '>=3'
401+
- python: '3.14'
402+
cython: '>=3'
400403
steps:
401404
- name: Retrieve the project source from an sdist inside the GHA artifact
402405
uses: re-actors/checkout-python-sdist@release/v2

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
persist-credentials: false
1717
- uses: actions/setup-python@v5
1818
with:
19-
python-version: "3.9"
19+
python-version: "3.10"
2020
- run: python -m pip install build
2121
- run: python -m build
2222

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ repos:
8080
name: uv pip-compile test-requirements.in
8181
args: [
8282
"--universal",
83-
"--python-version=3.9",
83+
"--python-version=3.10",
8484
"test-requirements.in",
8585
"-o",
8686
"test-requirements.txt"]

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ demonstration of implementing the "Happy Eyeballs" algorithm in an
9292
older library versus Trio.
9393

9494
**Cool, but will it work on my system?** Probably! As long as you have
95-
some kind of Python 3.9-or-better (CPython or `currently maintained versions of
95+
some kind of Python 3.10-or-better (CPython or `currently maintained versions of
9696
PyPy3 <https://doc.pypy.org/en/latest/faq.html#which-python-versions-does-pypy-implement>`__
9797
are both fine), and are using Linux, macOS, Windows, or FreeBSD, then Trio
9898
will work. Other environments might work too, but those

docs/source/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Vital statistics:
4545

4646
* Supported environments: We test on
4747

48-
- Python: 3.9+ (CPython and PyPy)
48+
- Python: 3.10+ (CPython and PyPy)
4949
- Windows, macOS, Linux (glibc and musl), FreeBSD
5050

5151
Other environments might also work; give it a try and see.

docs/source/tutorial.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ Okay, ready? Let's get started.
8888
Before you begin
8989
----------------
9090

91-
1. Make sure you're using Python 3.9 or newer.
91+
1. Make sure you're using Python 3.10 or newer.
9292

9393
2. ``python3 -m pip install --upgrade trio`` (or on Windows, maybe
9494
``py -3 -m pip install --upgrade trio`` – `details

newsfragments/3345.removal.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Drop support for Python 3.9.

pyproject.toml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ classifiers = [
2626
"Programming Language :: Python :: Implementation :: CPython",
2727
"Programming Language :: Python :: Implementation :: PyPy",
2828
"Programming Language :: Python :: 3 :: Only",
29-
"Programming Language :: Python :: 3.9",
3029
"Programming Language :: Python :: 3.10",
3130
"Programming Language :: Python :: 3.11",
3231
"Programming Language :: Python :: 3.12",
3332
"Programming Language :: Python :: 3.13",
33+
"Programming Language :: Python :: 3.14",
3434
"Topic :: System :: Networking",
3535
"Typing :: Typed",
3636
]
37-
requires-python = ">=3.9"
37+
requires-python = ">=3.10"
3838
dependencies = [
3939
# attrs 19.2.0 adds `eq` option to decorators
4040
# attrs 20.1.0 adds @frozen
@@ -215,7 +215,7 @@ disallow_untyped_defs = true
215215
check_untyped_defs = true
216216

217217
[tool.pyright]
218-
pythonVersion = "3.9"
218+
pythonVersion = "3.10"
219219
reportUnnecessaryTypeIgnoreComment = true
220220
typeCheckingMode = "strict"
221221

@@ -330,6 +330,7 @@ exclude_also = [
330330
'.*if "sphinx.ext.autodoc" in sys.modules:',
331331
'TODO: test this line',
332332
'if __name__ == "__main__":',
333+
'pass',
333334
]
334335
partial_branches = [
335336
"pragma: no branch",

src/trio/_channel.py

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
MultipleExceptionError,
2323
NoPublicConstructor,
2424
final,
25-
generic_function,
2625
raise_single_exception_from_group,
2726
)
2827

@@ -45,9 +44,9 @@
4544
P = ParamSpec("P")
4645

4746

48-
def _open_memory_channel(
49-
max_buffer_size: int | float, # noqa: PYI041
50-
) -> tuple[MemorySendChannel[T], MemoryReceiveChannel[T]]:
47+
# written as a class so you can say open_memory_channel[int](5)
48+
@final
49+
class open_memory_channel(tuple["MemorySendChannel[T]", "MemoryReceiveChannel[T]"]):
5150
"""Open a channel for passing objects between tasks within a process.
5251
5352
Memory channels are lightweight, cheap to allocate, and entirely
@@ -97,38 +96,24 @@ def _open_memory_channel(
9796
channel (summing over all clones).
9897
* ``tasks_waiting_receive``: The number of tasks blocked in ``receive`` on
9998
this channel (summing over all clones).
100-
10199
"""
102-
if max_buffer_size != inf and not isinstance(max_buffer_size, int):
103-
raise TypeError("max_buffer_size must be an integer or math.inf")
104-
if max_buffer_size < 0:
105-
raise ValueError("max_buffer_size must be >= 0")
106-
state: MemoryChannelState[T] = MemoryChannelState(max_buffer_size)
107-
return (
108-
MemorySendChannel[T]._create(state),
109-
MemoryReceiveChannel[T]._create(state),
110-
)
111-
112-
113-
# This workaround requires python3.9+, once older python versions are not supported
114-
# or there's a better way of achieving type-checking on a generic factory function,
115-
# it could replace the normal function header
116-
if TYPE_CHECKING:
117-
# written as a class so you can say open_memory_channel[int](5)
118-
class open_memory_channel(tuple["MemorySendChannel[T]", "MemoryReceiveChannel[T]"]):
119-
def __new__( # type: ignore[misc] # "must return a subtype"
120-
cls,
121-
max_buffer_size: int | float, # noqa: PYI041
122-
) -> tuple[MemorySendChannel[T], MemoryReceiveChannel[T]]:
123-
return _open_memory_channel(max_buffer_size)
124-
125-
def __init__(self, max_buffer_size: int | float) -> None: # noqa: PYI041
126-
...
127-
128-
else:
129-
# apply the generic_function decorator to make open_memory_channel indexable
130-
# so it's valid to say e.g. ``open_memory_channel[bytes](5)`` at runtime
131-
open_memory_channel = generic_function(_open_memory_channel)
100+
101+
def __new__( # type: ignore[misc] # "must return a subtype"
102+
cls,
103+
max_buffer_size: int | float, # noqa: PYI041
104+
) -> tuple[MemorySendChannel[T], MemoryReceiveChannel[T]]:
105+
if max_buffer_size != inf and not isinstance(max_buffer_size, int):
106+
raise TypeError("max_buffer_size must be an integer or math.inf")
107+
if max_buffer_size < 0:
108+
raise ValueError("max_buffer_size must be >= 0")
109+
state: MemoryChannelState[T] = MemoryChannelState(max_buffer_size)
110+
return (
111+
MemorySendChannel[T]._create(state),
112+
MemoryReceiveChannel[T]._create(state),
113+
)
114+
115+
def __init__(self, max_buffer_size: int | float) -> None: # noqa: PYI041
116+
...
132117

133118

134119
@attrs.frozen

0 commit comments

Comments
 (0)