Skip to content

Commit 236f91a

Browse files
authored
Drop Python 3.9 (#602)
# Changes ## Drop Python 3.9 EOL of 2025-10-31. See also: - https://devguide.python.org/versions/#:~:text=Release%20manager-,3.9,-PEP%20596 - https://peps.python.org/pep-0596/
2 parents e215556 + f6194c6 commit 236f91a

File tree

15 files changed

+101
-541
lines changed

15 files changed

+101
-541
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
runs-on: ubuntu-latest
1111
strategy:
1212
matrix:
13-
python-version: ['3.9', '3.14']
13+
python-version: ['3.14']
1414
tmux-version: ['2.6', '2.7', '2.8', '3.0a', '3.1b', '3.2a', '3.3a', '3.4', '3.5', 'master']
1515
steps:
1616
- uses: actions/checkout@v4

CHANGES

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ $ pip install --user --upgrade --pre libtmux
1515

1616
- _Future release notes will be placed here_
1717

18+
### Breaking changes
19+
20+
- Drop support for Python 3.9; the new minimum is Python 3.10 (#602). See also:
21+
- [Python 3.9 EOL timeline](https://devguide.python.org/versions/#:~:text=Release%20manager-,3.9,-PEP%20596)
22+
- [PEP 596](https://peps.python.org/pep-0596/)
23+
1824
### Development
1925

2026
- Add Python 3.14 to test matrix (#601)

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ See donation options at <https://tony.sh/support.html>.
265265
# Project details
266266

267267
- tmux support: 1.8+
268-
- python support: >= 3.9, pypy, pypy3
268+
- python support: >= 3.10, pypy, pypy3
269269
- Source: <https://github.com/tmux-python/libtmux>
270270
- Docs: <https://libtmux.git-pull.com>
271271
- API: <https://libtmux.git-pull.com/api.html>

pyproject.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "libtmux"
33
version = "0.46.2"
44
description = "Typed library that provides an ORM wrapper for tmux, a terminal multiplexer."
5-
requires-python = ">=3.9,<4.0"
5+
requires-python = ">=3.10,<4.0"
66
authors = [
77
{name = "Tony Narlock", email = "tony@git-pull.com"}
88
]
@@ -16,7 +16,6 @@ classifiers = [
1616
"Framework :: Pytest",
1717
"Intended Audience :: Developers",
1818
"Programming Language :: Python",
19-
"Programming Language :: Python :: 3.9",
2019
"Programming Language :: Python :: 3.10",
2120
"Programming Language :: Python :: 3.11",
2221
"Programming Language :: Python :: 3.12",
@@ -122,7 +121,7 @@ build-backend = "hatchling.build"
122121

123122
[tool.mypy]
124123
strict = true
125-
python_version = "3.9"
124+
python_version = "3.10"
126125
files = [
127126
"src",
128127
"tests",
@@ -156,7 +155,7 @@ exclude_lines = [
156155
]
157156

158157
[tool.ruff]
159-
target-version = "py39"
158+
target-version = "py310"
160159

161160
[tool.ruff.lint]
162161
select = [

src/libtmux/_internal/query_list.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,7 @@ def __eq__(
492492
return False
493493

494494
if len(self) == len(data):
495-
for a, b in zip(self, data):
495+
for a, b in zip(self, data, strict=False):
496496
if isinstance(a, Mapping):
497497
a_keys = a.keys()
498498
if a.keys == b.keys():

src/libtmux/_internal/types.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
if t.TYPE_CHECKING:
1515
from os import PathLike
16-
17-
from typing_extensions import TypeAlias
16+
from typing import TypeAlias
1817

1918
StrPath: TypeAlias = "str | PathLike[str]"

src/libtmux/_vendor/version.py

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,13 @@
2121

2222
__all__ = ["VERSION_PATTERN", "InvalidVersion", "Version", "parse"]
2323

24-
InfiniteTypes = t.Union[InfinityType, NegativeInfinityType]
25-
PrePostDevType = t.Union[InfiniteTypes, tuple[str, int]]
26-
SubLocalType = t.Union[InfiniteTypes, int, str]
27-
LocalType = t.Union[
28-
NegativeInfinityType,
29-
tuple[
30-
t.Union[
31-
SubLocalType,
32-
tuple[SubLocalType, str],
33-
tuple[NegativeInfinityType, SubLocalType],
34-
],
35-
...,
36-
],
37-
]
24+
InfiniteTypes = InfinityType | NegativeInfinityType
25+
PrePostDevType = InfiniteTypes | tuple[str, int]
26+
SubLocalType = InfiniteTypes | int | str
27+
LocalTuple = (
28+
SubLocalType | tuple[SubLocalType, str] | tuple[NegativeInfinityType, SubLocalType]
29+
)
30+
LocalType = NegativeInfinityType | tuple[LocalTuple, ...]
3831
CmpKey = tuple[
3932
int,
4033
tuple[int, ...],

src/libtmux/neo.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
if t.TYPE_CHECKING:
1515
ListCmd = t.Literal["list-sessions", "list-windows", "list-panes"]
16-
ListExtraArgs = t.Optional[Iterable[str]]
16+
ListExtraArgs = Iterable[str] | None
1717

1818
from libtmux.server import Server
1919

@@ -174,7 +174,7 @@ def _refresh(
174174
obj_key: str,
175175
obj_id: str,
176176
list_cmd: ListCmd = "list-panes",
177-
list_extra_args: ListExtraArgs | None = None,
177+
list_extra_args: ListExtraArgs = None,
178178
) -> None:
179179
assert isinstance(obj_id, str)
180180
obj = fetch_obj(
@@ -193,7 +193,7 @@ def _refresh(
193193
def fetch_objs(
194194
server: Server,
195195
list_cmd: ListCmd,
196-
list_extra_args: ListExtraArgs | None = None,
196+
list_extra_args: ListExtraArgs = None,
197197
) -> OutputsRaw:
198198
"""Fetch a listing of raw data from a tmux command."""
199199
formats = list(Obj.__dataclass_fields__.keys())
@@ -224,7 +224,7 @@ def fetch_objs(
224224
obj_output = proc.stdout
225225

226226
obj_formatters = [
227-
dict(zip(formats, formatter.split(FORMAT_SEPARATOR)))
227+
dict(zip(formats, formatter.split(FORMAT_SEPARATOR), strict=False))
228228
for formatter in obj_output
229229
]
230230

@@ -237,7 +237,7 @@ def fetch_obj(
237237
obj_key: str,
238238
obj_id: str,
239239
list_cmd: ListCmd = "list-panes",
240-
list_extra_args: ListExtraArgs | None = None,
240+
list_extra_args: ListExtraArgs = None,
241241
) -> OutputRaw:
242242
"""Fetch raw data from tmux command."""
243243
obj_formatters_filtered = fetch_objs(

src/libtmux/pane.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,9 @@ def split(
704704

705705
pane_output = pane_cmd.stdout[0]
706706

707-
pane_formatters = dict(zip(["pane_id"], pane_output.split(FORMAT_SEPARATOR)))
707+
pane_formatters = dict(
708+
zip(["pane_id"], pane_output.split(FORMAT_SEPARATOR), strict=False),
709+
)
708710

709711
return self.from_pane_id(server=self.server, pane_id=pane_formatters["pane_id"])
710712

src/libtmux/server.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,12 @@
3333
)
3434

3535
if t.TYPE_CHECKING:
36-
import sys
3736
import types
37+
from typing import TypeAlias
3838

39-
from libtmux._internal.types import StrPath
39+
from typing_extensions import Self
4040

41-
if sys.version_info >= (3, 10):
42-
from typing import Self, TypeAlias
43-
else:
44-
from typing_extensions import Self, TypeAlias
41+
from libtmux._internal.types import StrPath
4542

4643
DashLiteral: TypeAlias = t.Literal["-"]
4744

@@ -580,7 +577,11 @@ def new_session(
580577
os.environ["TMUX"] = env
581578

582579
session_formatters = dict(
583-
zip(["session_id"], session_stdout.split(formats.FORMAT_SEPARATOR)),
580+
zip(
581+
["session_id"],
582+
session_stdout.split(formats.FORMAT_SEPARATOR),
583+
strict=False,
584+
),
584585
)
585586

586587
return Session.from_session_id(

0 commit comments

Comments
 (0)